@go-to-k/cdkd 0.30.1 → 0.30.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -7506,7 +7506,11 @@ Error: ${err.message || "Unknown error"}`,
7506
7506
  };
7507
7507
 
7508
7508
  // src/provisioning/providers/custom-resource-provider.ts
7509
- import { InvokeCommand } from "@aws-sdk/client-lambda";
7509
+ import {
7510
+ InvokeCommand,
7511
+ waitUntilFunctionActiveV2,
7512
+ waitUntilFunctionUpdatedV2
7513
+ } from "@aws-sdk/client-lambda";
7510
7514
  import { PublishCommand } from "@aws-sdk/client-sns";
7511
7515
  import {
7512
7516
  S3Client as S3Client6,
@@ -7790,9 +7794,54 @@ var CustomResourceProvider = class _CustomResourceProvider {
7790
7794
  await this.publishToSns(serviceToken, request);
7791
7795
  return await this.pollS3Response(responseKey, logicalId, operation);
7792
7796
  }
7797
+ await this.waitForBackingLambdaReady(serviceToken, logicalId);
7793
7798
  const response = await this.invokeLambda(serviceToken, request);
7794
7799
  return await this.getCustomResourceResponse(response, responseKey, logicalId, operation);
7795
7800
  }
7801
+ /**
7802
+ * Block until the backing Lambda function for a Custom Resource is in a
7803
+ * state that accepts a synchronous Invoke.
7804
+ *
7805
+ * Two sequential waiters:
7806
+ * 1. `waitUntilFunctionActiveV2` — handles the post-CreateFunction
7807
+ * `Pending` window (image pull, VPC ENI attachment, layer init).
7808
+ * 2. `waitUntilFunctionUpdatedV2` — handles the post-Update
7809
+ * `InProgress` window (configuration / code swap settling).
7810
+ * Together they cover the only two transient states that reject
7811
+ * synchronous Invokes.
7812
+ *
7813
+ * In the common case (Lambda has been Active for a while, no in-flight
7814
+ * Update), both waiters return on first poll → ~2 GetFunction calls →
7815
+ * ~200ms overhead. That's the price for correctness; the alternative
7816
+ * (whole-stack Active wait at Lambda CREATE) is ~5–10 minutes per
7817
+ * VPC-attached function.
7818
+ *
7819
+ * `serviceToken` is the Lambda function ARN; the Lambda SDK accepts
7820
+ * both name and ARN as `FunctionName`, so we pass the ARN through
7821
+ * unchanged.
7822
+ *
7823
+ * `maxWaitTime` is set generously (10 min) because VPC ENI attachment
7824
+ * has been observed to take 8+ minutes in pathological cases. The
7825
+ * deploy engine's per-resource `--resource-timeout` (default 30 min)
7826
+ * still bounds the outer Custom Resource provisioning attempt, so
7827
+ * this waiter cap is layered defense, not the only timeout.
7828
+ */
7829
+ async waitForBackingLambdaReady(serviceToken, logicalId) {
7830
+ try {
7831
+ await waitUntilFunctionActiveV2(
7832
+ { client: this.lambdaClient, maxWaitTime: 600 },
7833
+ { FunctionName: serviceToken }
7834
+ );
7835
+ await waitUntilFunctionUpdatedV2(
7836
+ { client: this.lambdaClient, maxWaitTime: 600 },
7837
+ { FunctionName: serviceToken }
7838
+ );
7839
+ } catch (error) {
7840
+ throw new Error(
7841
+ `Lambda backing custom resource ${logicalId} (${serviceToken}) did not reach a ready state for Invoke: ${error instanceof Error ? error.message : String(error)}`
7842
+ );
7843
+ }
7844
+ }
7796
7845
  /**
7797
7846
  * Publish custom resource request to an SNS topic
7798
7847
  */
@@ -12967,8 +13016,7 @@ import {
12967
13016
  ListFunctionsCommand,
12968
13017
  ListTagsCommand,
12969
13018
  ResourceNotFoundException,
12970
- waitUntilFunctionActiveV2,
12971
- waitUntilFunctionUpdatedV2
13019
+ waitUntilFunctionUpdatedV2 as waitUntilFunctionUpdatedV22
12972
13020
  } from "@aws-sdk/client-lambda";
12973
13021
  import {
12974
13022
  DescribeNetworkInterfacesCommand,
@@ -13011,14 +13059,20 @@ var LambdaFunctionProvider = class {
13011
13059
  eniWaitTimeoutMs = 10 * 60 * 1e3;
13012
13060
  eniWaitInitialDelayMs = 1e4;
13013
13061
  eniWaitMaxDelayMs = 3e4;
13014
- // Budget for the post-CreateFunction / post-Update wait that blocks until
13015
- // Configuration.State === 'Active' and LastUpdateStatus === 'Successful'.
13016
- // Must NOT be skipped by --no-wait: downstream resources (Custom Resource
13017
- // Invokes, EventSourceMappings, etc.) cannot operate against a function
13018
- // still in Pending / InProgress, so this is required for correctness, not
13019
- // a "convenience wait" like CloudFront / RDS readiness.
13062
+ // Budget for the post-Update wait that blocks until LastUpdateStatus
13063
+ // === 'Successful'. Required to prevent the SECOND in-flight call (e.g.
13064
+ // UpdateFunctionCode immediately after UpdateFunctionConfiguration)
13065
+ // from racing the first with "function is currently in the following
13066
+ // state: InProgress". Update typically settles in seconds; the 10-min
13067
+ // cap is generous slack for layer-update / VPC-detach edge cases.
13020
13068
  // Seconds (the SDK waiter contract is seconds, not ms).
13021
- functionReadyMaxWaitSeconds = 10 * 60;
13069
+ //
13070
+ // The post-CreateFunction `State=Active` wait used to live here too
13071
+ // (PR #121) but doubled deploy time on benchmark stacks because every
13072
+ // Lambda paid the cost regardless of whether anything synchronously
13073
+ // invoked it. The Active wait now lives in `CustomResourceProvider`
13074
+ // (the only deploy-time consumer that breaks against Pending).
13075
+ functionUpdateMaxWaitSeconds = 10 * 60;
13022
13076
  // delstack-style ENI cleanup tunables.
13023
13077
  // - initial sleep: gives AWS time to publish post-detach ENI state via
13024
13078
  // DescribeNetworkInterfaces (right after the update, the API can return
@@ -13087,7 +13141,6 @@ var LambdaFunctionProvider = class {
13087
13141
  Tags: tags
13088
13142
  };
13089
13143
  const response = await this.lambdaClient.send(new CreateFunctionCommand(createParams));
13090
- await this.waitForFunctionActive(logicalId, resourceType, functionName);
13091
13144
  this.logger.debug(`Successfully created Lambda function ${logicalId}: ${functionName}`);
13092
13145
  return {
13093
13146
  physicalId: response.FunctionName || functionName,
@@ -13097,9 +13150,6 @@ var LambdaFunctionProvider = class {
13097
13150
  }
13098
13151
  };
13099
13152
  } catch (error) {
13100
- if (error instanceof ProvisioningError) {
13101
- throw error;
13102
- }
13103
13153
  const cause = error instanceof Error ? error : void 0;
13104
13154
  throw new ProvisioningError(
13105
13155
  `Failed to create Lambda function ${logicalId}: ${error instanceof Error ? error.message : String(error)}`,
@@ -13355,45 +13405,28 @@ var LambdaFunctionProvider = class {
13355
13405
  * Timeout is a soft warning — downstream Subnet/SG deletion has its own
13356
13406
  * retries.
13357
13407
  */
13358
- /**
13359
- * Block until the function's State === 'Active'.
13360
- *
13361
- * Used after CreateFunction. Wraps the SDK's built-in
13362
- * `waitUntilFunctionActiveV2` (acceptors: SUCCESS=Active, FAILURE=Failed,
13363
- * RETRY=Pending). The waiter throws on FAILURE / TIMEOUT — both surface
13364
- * as `ProvisioningError` with the function-name as physicalId so the
13365
- * deploy engine's per-resource error handling treats them identically to
13366
- * a CreateFunction failure.
13367
- */
13368
- async waitForFunctionActive(logicalId, resourceType, functionName) {
13369
- try {
13370
- await waitUntilFunctionActiveV2(
13371
- { client: this.lambdaClient, maxWaitTime: this.functionReadyMaxWaitSeconds },
13372
- { FunctionName: functionName }
13373
- );
13374
- } catch (error) {
13375
- const cause = error instanceof Error ? error : void 0;
13376
- throw new ProvisioningError(
13377
- `Lambda function ${logicalId} did not reach Active state: ${error instanceof Error ? error.message : String(error)}`,
13378
- resourceType,
13379
- logicalId,
13380
- functionName,
13381
- cause
13382
- );
13383
- }
13384
- }
13385
13408
  /**
13386
13409
  * Block until the function's LastUpdateStatus === 'Successful'.
13387
13410
  *
13388
13411
  * Used after UpdateFunctionConfiguration / UpdateFunctionCode. Wraps the
13389
13412
  * SDK's `waitUntilFunctionUpdatedV2` (acceptors: SUCCESS=Successful,
13390
- * FAILURE=Failed, RETRY=InProgress). Same error-wrapping contract as
13391
- * `waitForFunctionActive`.
13413
+ * FAILURE=Failed, RETRY=InProgress). Errors are surfaced as
13414
+ * `ProvisioningError` so the deploy engine's per-resource error
13415
+ * handling treats them identically to an Update API failure.
13416
+ *
13417
+ * NOTE: post-CreateFunction `State=Active` wait was deliberately moved
13418
+ * out of this provider in favor of an on-demand wait inside
13419
+ * `CustomResourceProvider.sendRequest` (the only deploy-time consumer
13420
+ * that breaks against a Pending Lambda). Blocking the entire deploy
13421
+ * DAG behind every Lambda's Active transition more than doubled
13422
+ * deploy time on benchmark stacks; the on-demand wait scoped to the
13423
+ * one resource type that actually needs it preserves the bug fix
13424
+ * without paying the whole-stack tax.
13392
13425
  */
13393
13426
  async waitForFunctionUpdated(logicalId, resourceType, functionName) {
13394
13427
  try {
13395
- await waitUntilFunctionUpdatedV2(
13396
- { client: this.lambdaClient, maxWaitTime: this.functionReadyMaxWaitSeconds },
13428
+ await waitUntilFunctionUpdatedV22(
13429
+ { client: this.lambdaClient, maxWaitTime: this.functionUpdateMaxWaitSeconds },
13397
13430
  { FunctionName: functionName }
13398
13431
  );
13399
13432
  } catch (error) {
@@ -36139,7 +36172,7 @@ function reorderArgs(argv) {
36139
36172
  }
36140
36173
  async function main() {
36141
36174
  const program = new Command13();
36142
- program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.30.1");
36175
+ program.name("cdkd").description("CDK Direct - Deploy AWS CDK apps directly via SDK/Cloud Control API").version("0.30.2");
36143
36176
  program.addCommand(createBootstrapCommand());
36144
36177
  program.addCommand(createSynthCommand());
36145
36178
  program.addCommand(createListCommand());