Skip to content

Commit 40f07ae

Browse files
feat(redshift-alpha): query execution timeout setting during table creation (#31818)
### Issue # (if applicable) Closes #31329. ### Reason for this change The timeout setting for the custom resource that executes the query is fixed at 1 minute, causing a timeout when attempting to run heavy operations. Detail example is describe in [the original issue](#31329 (comment)). ### Description of changes - Add timeout prop to `DatabaseQueryProps` and `TableProps` ### Description of how you validated changes Added both unit and integ tests. ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 09256db commit 40f07ae

File tree

30 files changed

+567
-409
lines changed

30 files changed

+567
-409
lines changed

packages/@aws-cdk/aws-redshift-alpha/README.md

+18
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,24 @@ new Table(this, 'Table', {
274274
});
275275
```
276276

277+
Query execution duration is limited to 1 minute by default. You can change this by setting the `timeout` property.
278+
279+
Valid timeout values are between 1 seconds and 15 minutes.
280+
281+
```ts fixture=cluster
282+
import { Duration } from 'aws-cdk-lib';
283+
284+
new Table(this, 'Table', {
285+
tableColumns: [
286+
{ id: 'col1', name: 'col1', dataType: 'varchar(4)' },
287+
{ id: 'col2', name: 'col2', dataType: 'float' }
288+
],
289+
cluster: cluster,
290+
databaseName: 'databaseName',
291+
timeout: Duration.minutes(15),
292+
});
293+
```
294+
277295
### Granting Privileges
278296

279297
You can give a user privileges to perform certain actions on a table by using the

packages/@aws-cdk/aws-redshift-alpha/lib/private/database-query.ts

+17-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@ export interface DatabaseQueryProps<HandlerProps> extends DatabaseOptions {
1818
* @default cdk.RemovalPolicy.Destroy
1919
*/
2020
readonly removalPolicy?: cdk.RemovalPolicy;
21+
22+
/**
23+
* The handler timeout duration
24+
*
25+
* @default cdk.Duration.minutes(1)
26+
*/
27+
readonly timeout?: cdk.Duration;
2128
}
2229

2330
export class DatabaseQuery<HandlerProps> extends Construct implements iam.IGrantable {
@@ -29,14 +36,23 @@ export class DatabaseQuery<HandlerProps> extends Construct implements iam.IGrant
2936
constructor(scope: Construct, id: string, props: DatabaseQueryProps<HandlerProps>) {
3037
super(scope, id);
3138

39+
if (props.timeout && !cdk.Token.isUnresolved(props.timeout)) {
40+
if (props.timeout.toMilliseconds() < cdk.Duration.seconds(1).toMilliseconds()) {
41+
throw new Error(`The timeout for the handler must be BETWEEN 1 second and 15 minutes, got ${props.timeout.toMilliseconds()} milliseconds.`);
42+
}
43+
if (props.timeout.toSeconds() > cdk.Duration.minutes(15).toSeconds()) {
44+
throw new Error(`The timeout for the handler must be between 1 second and 15 minutes, got ${props.timeout.toSeconds()} seconds.`);
45+
}
46+
}
47+
3248
const adminUser = this.getAdminUser(props);
3349
const handler = new lambda.SingletonFunction(this, 'Handler', {
3450
code: lambda.Code.fromAsset(path.join(__dirname, 'database-query-provider'), {
3551
exclude: ['*.ts'],
3652
}),
3753
runtime: lambda.determineLatestNodeRuntime(this),
3854
handler: 'index.handler',
39-
timeout: cdk.Duration.minutes(1),
55+
timeout: props.timeout ?? cdk.Duration.minutes(1),
4056
uuid: '3de5bea7-27da-4796-8662-5efb56431b5f',
4157
lambdaPurpose: 'Query Redshift Database',
4258
});

packages/@aws-cdk/aws-redshift-alpha/lib/table.ts

+9
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,15 @@ export interface TableProps extends DatabaseOptions {
149149
* @default - no comment
150150
*/
151151
readonly tableComment?: string;
152+
153+
/**
154+
* Handler timeout duration.
155+
*
156+
* Valid values are between 1 second and 15 minutes.
157+
*
158+
* @default - 1 minute
159+
*/
160+
readonly timeout?: cdk.Duration;
152161
}
153162

154163
/**

packages/@aws-cdk/aws-redshift-alpha/test/database-query.test.ts

+32
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,38 @@ describe('database query', () => {
166166
});
167167
});
168168

169+
describe('timeout', () => {
170+
it('passes timeout', () => {
171+
new DatabaseQuery(stack, 'Query', {
172+
...minimalProps,
173+
timeout: cdk.Duration.minutes(5),
174+
});
175+
176+
Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', {
177+
Timeout: 300,
178+
Role: { 'Fn::GetAtt': ['QueryRedshiftDatabase3de5bea727da479686625efb56431b5fServiceRole0A90D717', 'Arn'] },
179+
Handler: 'index.handler',
180+
Code: {
181+
S3Bucket: { 'Fn::Sub': 'cdk-hnb659fds-assets-${AWS::AccountId}-${AWS::Region}' },
182+
},
183+
});
184+
});
185+
186+
it('throw error for timeout being too short', () => {
187+
expect(() => new DatabaseQuery(stack, 'Query', {
188+
...minimalProps,
189+
timeout: cdk.Duration.millis(999),
190+
})).toThrow('The timeout for the handler must be BETWEEN 1 second and 15 minutes, got 999 milliseconds.');
191+
});
192+
193+
it('throw error for timeout being too long', () => {
194+
expect(() => new DatabaseQuery(stack, 'Query', {
195+
...minimalProps,
196+
timeout: cdk.Duration.minutes(16),
197+
})).toThrow('The timeout for the handler must be between 1 second and 15 minutes, got 960 seconds.');
198+
});
199+
});
200+
169201
it('passes removal policy through', () => {
170202
new DatabaseQuery(stack, 'Query', {
171203
...minimalProps,

packages/@aws-cdk/aws-redshift-alpha/test/integ.database-columnid.js.snapshot/asset.15197a5512179542fe2cff74af89bb047793c9c4e0b4395f114641a81cd52ae5/cfn-response.js

-88
This file was deleted.

0 commit comments

Comments
 (0)