From 9f9403ff9a5588549bbee06349afc44e4a60adad Mon Sep 17 00:00:00 2001 From: Momo Kornher Date: Mon, 18 Nov 2024 21:03:47 +0000 Subject: [PATCH] errors --- text/0300-programmatic-toolkit.md | 124 ++++++++++++++++++++++++++---- 1 file changed, 110 insertions(+), 14 deletions(-) diff --git a/text/0300-programmatic-toolkit.md b/text/0300-programmatic-toolkit.md index ac64d2c38..4ef4786ad 100644 --- a/text/0300-programmatic-toolkit.md +++ b/text/0300-programmatic-toolkit.md @@ -24,7 +24,7 @@ The package provides implementations for the following actions: ```ts // Create a [Programmatic Toolkit] -const cdk = new Toolkit({ +await using cdk = new Toolkit({ ioHost: new CloudWatchLogsIoHost('my-log-stream'), // write all output to CW logs // awsSdkProvider: new DefaultAwsSdk(), // optional }); @@ -80,8 +80,8 @@ interface IoMessage { data?: T; } -interface IoRequest extends IoMessage { - defaultResponse: T; +interface IoRequest extends IoMessage { + defaultResponse: U; } ``` @@ -130,7 +130,7 @@ interface IIoHost { * If the host does not return a response the suggested * default response from the input message will be used. */ - async requestResponse(msg: IoRequest): T | undefined; + async requestResponse(msg: IoRequest): U | undefined; } ``` @@ -223,14 +223,110 @@ It returns a list of stack deployments. #### Errors - +```ts +interface ToolkitError extends IoMessage { + source: 'toolkit' | 'user'; + type: 'authentication' | 'cloudformation' | 'validation' ...; + fqn?: string; +} +``` - +The toolkit might throw other exceptions. +These are bugs and you should report them by [raising an issue](https://github.com/aws/aws-cdk/issues/new?assignees=&labels=bug%2Cneeds-triage&projects=&template=bug-report.yml&title=%28toolkit%29%3A+Untyped+Exception+%28short+description%29). +To assist integrators with detecting the type of error, the following helper methods are available. +Even though errors are typed, you should not rely on `instanceof` checks because it can behave unexpectedly when working with multiple copies of the same package. [TODO: insert reference link] +```ts +try { + await cdk.deploy(...); +} catch (e: unknown) { + if (ToolkitError.isToolkitError(error)) { + // handle toolkit errors + } else if (ToolkitError.isUserError(e)) { + // handle user code errors + } + + if (ToolkitError.isCdkError(e)) { + // handle any cdk errors + } +} +``` + +##### Recoverable Errors [TODO: Naming. All errors in JS are recoverable. Ruby calls this rescue/retry] + + [Alternative: Make retry a boolean] + [Alternative: Limit to exactly 1 rescue attempt] + +While most errors are terminal, it's possible to recover from some. +For example if an authentication token is expired, an integrator may prompt the user to re-authenticate via a browser login, before continuing with the action. +Formally, recoverable errors allow the integrator to return to the regular program flow after an issue has been addressed. +Recoverable errors are rare as they require special programming and are not always possible. + +In the [Programmatic Toolkit], recoverable errors are implemented as a special type of request. +By default, errors will not be attempted to recover. + +```ts +interface RecoverableError extends IoRequest { + level: 'error'; + defaultResponse: { + retry: number; // the budget for retries + // ... other response values + }; + data: { + attempt: number; + } +} +``` + +When `IoHost.requestResponse()` is called with a recoverable error, the integrator may choose to return `retry: 1` (or any number) to indicate the block should be retried. +This value is called the retry budget. +If the block fails again with the same error, the `IoHost` will be called again until the retry budget is used up. +Retries are not guaranteed and integrators must handle the case where a requested retry is not executed. +Once the retry budged is depleted, the error from the final attempt will be raised as an exception. + +##### Synth-time Errors + +There is a subtle semantic difference between errors that originate from the [Programmatic Toolkit] and from a Cloud Executable, i.e. from a user's app: +Errors from the [Programmatic Toolkit] are typically misconfigurations and maybe fixable by an integrator, +while errors from a Cloud Executable are usually code problems and only fixable by the user. + +The [Programmatic Toolkit] emits all synth-time errors as recoverable errors. +When implementing a custom Cloud Executable in code, you may prefer to handle synth-time errors directly in code: + +```ts +class MyCloudExecutable implements ICloudExecutable { + async exec(context: Record): cxapi.CloudAssembly { + try { + const app = new cdk.App({ context }); + const stack = new cdk.Stack(app); + return app.synth(); + } catch(e: unknown) { + // handle errors here + } + } +} +``` + +#### Dispose + +The `Toolkit` class implements an `AsyncDisposable` Resource according to the [Explicit Resource Management](https://github.com/tc39/proposal-explicit-resource-management) feature in ECMAScript. +This means that any resources used by the [Programmatic Toolkit] are automatically cleaned-up. +`AsyncDisposable` guarantees this clean-up even in case of an uncaught exception. + +You may also call the `dispose()` method directly. +We recommend to do this inside a `finally` statement to guarantee execution. + +```ts +const cdk = new Toolkit(); +try { + cdk.deploy(...); +} finally { + await cdk.dispose(); +} +``` --- @@ -394,7 +490,7 @@ The project will be delivered incrementally over multiple months. We start with core functionalities and the most commonly used actions. A more detailed project plan will be provided when it is available. -#### Milestone 1 +#### Milestone 1 // 8 two-dev-weeks Covers foundational features and the most commonly used actions. @@ -406,7 +502,7 @@ Covers foundational features and the most commonly used actions. * implement options for cli-lib * generate options from toolkit interface -#### Milestone 2 +#### Milestone 2 // 8 two-dev-weeks Added support for actions required to cover the complete lifecycle of a CDK app. Typed returns to increase support for even more complex scenarios. @@ -418,7 +514,7 @@ Use [Programmatic Toolkit] in `integ-runner` and integration tests. * integration Tests * integ-runner -#### Milestone 3 +#### Milestone 3 // 4 two-dev-weeks GA. Added support for operational actions and release of the jsii toolkit. @@ -427,7 +523,7 @@ GA. Added support for operational actions and release of the jsii toolkit. * events for above actions * new jsii package, removal of cli-lib-alpha -#### Milestone 4 +#### Milestone 4 // 4 two-dev-weeks GA. Added support for highly interactive actions. @@ -568,4 +664,4 @@ to spawn cli commands directly. It will improve the performance and simplify use cases like running the AWS CDK inside an AWS Lambda Function. As a jsii package, the construct will be -available to all jsii target languages. \ No newline at end of file +available to all jsii target languages.a \ No newline at end of file