Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions lib/restate-constructs/register-service-handler/index.mts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,33 @@ export interface RegistrationProperties {

/** Maximum number of drained deployments to prune per run. */
maxPrunedPerRun?: number;

/**
* Whether to force deployment registration, overwriting any existing deployment at the same endpoint and allowing
* breaking changes such as removing handlers.
*
* When `force` is true, both breaking changes (e.g., removing handlers) and overwriting existing deployments are
* allowed. This is the most permissive option but may cause issues with in-flight invocations.
*
* Consider using `breaking` instead if you only need to allow schema changes without overwriting deployments.
*
* @see breaking for a safer alternative that allows breaking changes without overwriting
*/
force?: "true" | "false";

/**
* Whether to allow breaking schema changes (e.g., removing handlers, changing service types) without overwriting
* the existing deployment. This is safer than `force` because it won't affect in-flight invocations that are
* pinned to the existing deployment.
*
* Use this when evolving services that may have breaking API changes but you want to preserve existing deployment
* versions for in-progress work.
*
* Note: If `force` is set to true, it takes precedence and both breaking changes and overwrites are allowed.
*
* @see force for allowing both breaking changes and overwrites
*/
breaking?: "true" | "false";
}

type RegisterDeploymentResponse = {
Expand Down Expand Up @@ -223,6 +250,8 @@ export const handler = async function (event: CloudFormationCustomResourceEvent)
const registrationRequest = JSON.stringify({
arn: props.serviceLambdaArn,
assume_role_arn: props.invokeRoleArn,
force: props.force === "true",
breaking: props.breaking === "true",
});

let failureReason;
Expand Down
45 changes: 45 additions & 0 deletions lib/restate-constructs/service-deployer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,49 @@ export interface ServiceRegistrationProps {
* Default: 10
*/
maxPrunedPerRun?: number;

/**
* Force deployment registration, overwriting any existing deployment at the same endpoint. This allows
* breaking changes such as removing service handlers.
*
* When enabled, both breaking schema changes and deployment overwrites are allowed. This is the most
* permissive option but may cause issues with in-flight invocations that are pinned to the existing
* deployment.
*
* | Setting | Breaking changes | Overwrites |
* |-----------------------|------------------|------------|
* | `force: true` | Allowed | Allowed |
* | `breaking: true` | Allowed | Forbidden |
* | Neither | Forbidden | Forbidden |
*
* Note: If both `force` and `breaking` are set, `force` takes precedence.
*
* @see breaking for a safer alternative that allows breaking changes without overwriting
* @default false
*/
force?: boolean;

/**
* Allow breaking schema changes (e.g., removing handlers, changing service types) without overwriting
* the existing deployment. This is safer than `force` because existing deployments are preserved,
* allowing in-flight invocations to complete on the previous version.
*
* Use this when evolving services that may have breaking API changes but you want to preserve existing
* deployment versions for in-progress work.
*
* | Setting | Breaking changes | Overwrites |
* |-----------------------|------------------|------------|
* | `force: true` | Allowed | Allowed |
* | `breaking: true` | Allowed | Forbidden |
* | Neither | Forbidden | Forbidden |
*
* Note: If both `force` and `breaking` are set, `force` takes precedence. To use the safer `breaking`
* behavior, set `force: false` and `breaking: true`.
*
* @see force for allowing both breaking changes and overwrites
* @default false
*/
breaking?: boolean;
}

/**
Expand Down Expand Up @@ -256,6 +299,8 @@ export class ServiceDeployer extends Construct {
pruneDrainedDeployments: (options?.pruneDrainedDeployments ?? false).toString() as "true" | "false",
revisionHistoryLimit: options?.revisionHistoryLimit ?? 0,
maxPrunedPerRun: options?.maxPrunedPerRun ?? 10,
force: (options?.force ?? false).toString() as "true" | "false",
breaking: (options?.breaking ?? false).toString() as "true" | "false",
} satisfies RegistrationProperties,
});

Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@
"zx": "^8.8.5"
},
"peerDependencies": {
"aws-cdk": "^2.236.0",
"aws-cdk-lib": "^2.236.0",
"constructs": "^10.4.5",
"aws-cdk": "^2.215.0",
"aws-cdk-lib": "^2.215.0",
"constructs": "^10.3.0",
"node-fetch": "^3.3.2"
},
"directories": {
Expand Down
10 changes: 9 additions & 1 deletion test/__snapshots__/restate-constructs.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -1322,6 +1322,8 @@ exports[`Restate constructs Deploy a Lambda service handler to Restate Cloud env
pruneDrainedDeployments: 'false'
revisionHistoryLimit: 0
maxPrunedPerRun: 10
force: 'false'
breaking: 'false'
DependsOn:
- ServiceDeployerInvocationPolicyD09B639D
UpdateReplacePolicy: Delete
Expand Down Expand Up @@ -1518,6 +1520,8 @@ exports[`Restate constructs Deploy a Lambda service handler to existing Restate
pruneDrainedDeployments: 'false'
revisionHistoryLimit: 0
maxPrunedPerRun: 10
force: 'false'
breaking: 'false'
DependsOn:
- ServiceDeployerInvocationPolicyD09B639D
UpdateReplacePolicy: Delete
Expand Down Expand Up @@ -1728,6 +1732,8 @@ exports[`Restate constructs Restate Cloud Environment construct with role refere
pruneDrainedDeployments: 'false'
revisionHistoryLimit: 0
maxPrunedPerRun: 10
force: 'false'
breaking: 'false'
DependsOn:
- ServiceDeployerInvocationPolicyD09B639D
UpdateReplacePolicy: Delete
Expand Down Expand Up @@ -1845,7 +1851,7 @@ exports[`Restate constructs Service Deployer overrides 1`] = `
- arm64
Code:
S3Bucket: cdk-hnb659fds-assets-account-id-region
S3Key: 3e8c1652eeb2e525a478419d4009a3ed4e021bf98fc70eac7f4294d66f5910bc.zip
S3Key: 8ed2b7e40aa8b43d18da885b2d5ec8673277d0810b888d6becb080a6f280a64f.zip
Description: Restate custom registration handler
Handler: entrypoint.handler
MemorySize: 128
Expand Down Expand Up @@ -1944,6 +1950,8 @@ exports[`Restate constructs Service Deployer with removal policy and pruning opt
pruneDrainedDeployments: 'true'
revisionHistoryLimit: 5
maxPrunedPerRun: 10
force: 'false'
breaking: 'false'
DependsOn:
- ServiceDeployerInvocationPolicyD09B639D
UpdateReplacePolicy: Delete
Expand Down