Skip to content

Commit d52d485

Browse files
authored
fix(sdk): remove singleton pattern from checkpoint system (#327)
**Changes** - Remove Checkpoint Singleton Architecture - ESLint plugin configuration from monorepo root to examples package only - ESLint plugin build issues (empty dist folder) By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. **Important Note** Checkpoint, Termination, DurableExecution, pendingOperation and many other objects need access to oher one and although I address some of the issues including circular dependencies and right order to create those, there are still room to improve this. Ideally all the data and operations that are for the entire execution should be inside DurableExecution and operation and data related to DurableContext and child context should be in DurableContext. But this PR is getting too big and I'll address remaining issue in next PRs
1 parent f242c2d commit d52d485

File tree

51 files changed

+896
-607
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+896
-607
lines changed

eslint.config.js

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,3 @@
1-
import { createRequire } from "module";
2-
const require = createRequire(import.meta.url);
3-
4-
const durableFunctionsPlugin = require("./packages/aws-durable-execution-sdk-js-eslint-plugin/dist/index.js");
5-
const typescriptParser = require("@typescript-eslint/parser");
6-
71
export default [
82
{
93
ignores: [
@@ -13,26 +7,4 @@ export default [
137
"**/build/**",
148
],
159
},
16-
{
17-
files: [
18-
"packages/aws-durable-execution-sdk-js-examples/src/examples/**/*.ts",
19-
"packages/aws-durable-execution-sdk-js-examples/src/examples/**/*.js",
20-
"test-eslint.ts",
21-
],
22-
plugins: {
23-
"aws-durable-execution-eslint": durableFunctionsPlugin,
24-
},
25-
rules: {
26-
"aws-durable-execution-eslint/no-nested-durable-operations": "error",
27-
},
28-
languageOptions: {
29-
parser: typescriptParser,
30-
ecmaVersion: 2022,
31-
sourceType: "module",
32-
globals: {
33-
console: "readonly",
34-
process: "readonly",
35-
},
36-
},
37-
},
3810
];

package-lock.json

Lines changed: 1 addition & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 27 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,37 @@
1-
import js from "@eslint/js";
2-
import { defineConfig } from "eslint/config";
3-
import tseslint from "typescript-eslint";
4-
import { fileURLToPath } from "url";
5-
import { dirname } from "path";
1+
import { createRequire } from "module";
2+
const require = createRequire(import.meta.url);
63

7-
const __dirname = dirname(fileURLToPath(import.meta.url));
4+
const durableFunctionsPlugin = require("../aws-durable-execution-sdk-js-eslint-plugin/dist/index.js");
5+
const typescriptParser = require("@typescript-eslint/parser");
86

9-
// Import the plugin directly
10-
const durableFunctionsPlugin = {
11-
rules: {
12-
"no-nested-durable-operations": (
13-
await import(
14-
"../aws-durable-execution-sdk-js-eslint-plugin/dist/rules/no-nested-durable-operations.js"
15-
)
16-
).noNestedDurableOperations,
17-
"no-non-deterministic-outside-step": (
18-
await import(
19-
"../aws-durable-execution-sdk-js-eslint-plugin/dist/rules/no-non-deterministic-outside-step.js"
20-
)
21-
).noNonDeterministicOutsideStep,
22-
},
23-
};
24-
25-
export default defineConfig([
26-
js.configs.recommended,
27-
...tseslint.configs.recommended,
7+
export default [
288
{
29-
languageOptions: {
30-
parserOptions: {
31-
tsconfigRootDir: __dirname,
32-
},
33-
},
9+
ignores: [
10+
"**/coverage/**",
11+
"**/node_modules/**",
12+
"**/dist/**",
13+
"**/build/**",
14+
],
3415
},
3516
{
17+
files: [
18+
"src/examples/**/*.ts",
19+
"src/examples/**/*.js",
20+
],
3621
plugins: {
37-
"durable-functions": durableFunctionsPlugin,
22+
"aws-durable-execution-eslint": durableFunctionsPlugin,
3823
},
3924
rules: {
40-
"durable-functions/no-nested-durable-operations": "error",
41-
"durable-functions/no-non-deterministic-outside-step": "error",
25+
"aws-durable-execution-eslint/no-nested-durable-operations": "error",
26+
},
27+
languageOptions: {
28+
parser: typescriptParser,
29+
ecmaVersion: 2022,
30+
sourceType: "module",
31+
globals: {
32+
console: "readonly",
33+
process: "readonly",
34+
},
4235
},
43-
ignores: "**/*.test.ts",
4436
},
45-
]);
37+
];

packages/aws-durable-execution-sdk-js-examples/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
"dotenv": "^17.2.3"
5656
},
5757
"devDependencies": {
58+
"@aws/durable-execution-sdk-js-eslint-plugin": "*",
5859
"@eslint/js": "^9.23.0",
5960
"@rollup/plugin-commonjs": "^28.0.6",
6061
"@rollup/plugin-node-resolve": "^16.0.2",

packages/aws-durable-execution-sdk-js-examples/template.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,6 +1081,30 @@ Resources:
10811081
DURABLE_VERBOSE_MODE: "true"
10821082
Metadata:
10831083
SkipBuild: "True"
1084+
SimplePowertoolsLogger:
1085+
Type: AWS::Serverless::Function
1086+
Properties:
1087+
FunctionName: SimplePowertoolsLogger-TypeScript
1088+
CodeUri: ./dist
1089+
Handler: simple-powertools-logger.handler
1090+
Runtime: nodejs22.x
1091+
Architectures:
1092+
- x86_64
1093+
MemorySize: 128
1094+
Timeout: 60
1095+
Role:
1096+
Fn::GetAtt:
1097+
- DurableFunctionRole
1098+
- Arn
1099+
DurableConfig:
1100+
ExecutionTimeout: 3600
1101+
RetentionPeriodInDays: 7
1102+
Environment:
1103+
Variables:
1104+
AWS_ENDPOINT_URL_LAMBDA: http://host.docker.internal:5000
1105+
DURABLE_VERBOSE_MODE: "true"
1106+
Metadata:
1107+
SkipBuild: "True"
10841108
StepBasic:
10851109
Type: AWS::Serverless::Function
10861110
Properties:

packages/aws-durable-execution-sdk-js/src/context/durable-context/durable-context.ts

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ import {
2828
DurableLogData,
2929
} from "../../types";
3030
import { Context } from "aws-lambda";
31-
import { createCheckpoint } from "../../utils/checkpoint/checkpoint";
31+
import { CheckpointManager } from "../../utils/checkpoint/checkpoint-manager";
32+
import { EventEmitter } from "events";
3233
import { createStepHandler } from "../../handlers/step-handler/step-handler";
3334
import { createInvokeHandler } from "../../handlers/invoke-handler/invoke-handler";
3435
import { createRunInChildContextHandler } from "../../handlers/run-in-child-context-handler/run-in-child-context-handler";
@@ -42,7 +43,6 @@ import { createPromiseHandler } from "../../handlers/promise-handler/promise-han
4243
import { createConcurrentExecutionHandler } from "../../handlers/concurrent-execution-handler/concurrent-execution-handler";
4344
import { OperationStatus } from "@aws-sdk/client-lambda";
4445
import { ModeManagement } from "./mode-management/mode-management";
45-
import { EventEmitter } from "events";
4646
import { OPERATIONS_COMPLETE_EVENT } from "../../utils/constants/constants";
4747
import {
4848
getActiveContext,
@@ -52,9 +52,14 @@ import {
5252
DurableLogger,
5353
DurableLoggingContext,
5454
} from "../../types/durable-logger";
55-
import { createDefaultLogger } from "../../utils/logger/default-logger";
5655
import { hashId } from "../../utils/step-id-utils/step-id-utils";
5756

57+
export interface DurableExecution {
58+
checkpointManager: CheckpointManager;
59+
stepDataEmitter: EventEmitter;
60+
setTerminating(): void;
61+
}
62+
5863
export class DurableContextImpl<Logger extends DurableLogger>
5964
implements DurableContext<Logger>
6065
{
@@ -64,35 +69,32 @@ export class DurableContextImpl<Logger extends DurableLogger>
6469
private modeAwareLoggingEnabled: boolean = true;
6570
private runningOperations = new Set<string>();
6671
private operationsEmitter = new EventEmitter();
67-
private checkpoint: ReturnType<typeof createCheckpoint>;
72+
private checkpoint: CheckpointManager;
6873
private durableExecutionMode: DurableExecutionMode;
6974
private _parentId?: string;
7075
private modeManagement: ModeManagement;
76+
private durableExecution: DurableExecution;
7177

7278
constructor(
7379
private executionContext: ExecutionContext,
7480
public lambdaContext: Context,
7581
durableExecutionMode: DurableExecutionMode,
7682
inheritedLogger: Logger,
77-
stepPrefix?: string,
78-
checkpointToken?: string,
83+
stepPrefix: string | undefined,
84+
durableExecution: DurableExecution,
7985
parentId?: string,
8086
) {
8187
this._stepPrefix = stepPrefix;
8288
this._parentId = parentId;
89+
this.durableExecution = durableExecution;
8390
this.contextLogger = inheritedLogger;
8491
this.contextLogger.configureDurableLoggingContext?.(
8592
this.getDurableLoggingContext(),
8693
);
8794

8895
this.durableExecutionMode = durableExecutionMode;
8996

90-
this.checkpoint = createCheckpoint(
91-
executionContext,
92-
checkpointToken || "",
93-
this.operationsEmitter,
94-
createDefaultLogger(this.executionContext),
95-
);
97+
this.checkpoint = durableExecution.checkpointManager;
9698

9799
this.modeManagement = new ModeManagement(
98100
this.captureExecutionState.bind(this),
@@ -321,7 +323,25 @@ export class DurableContextImpl<Logger extends DurableLogger>
321323
this.lambdaContext,
322324
this.createStepId.bind(this),
323325
() => this.contextLogger,
324-
createDurableContext,
326+
// Adapter function to maintain compatibility
327+
(
328+
executionContext,
329+
parentContext,
330+
durableExecutionMode,
331+
inheritedLogger,
332+
stepPrefix,
333+
_checkpointToken,
334+
parentId,
335+
) =>
336+
createDurableContext(
337+
executionContext,
338+
parentContext,
339+
durableExecutionMode,
340+
inheritedLogger,
341+
stepPrefix,
342+
this.durableExecution,
343+
parentId,
344+
),
325345
this._parentId,
326346
);
327347
return blockHandler(nameOrFn, fnOrOptions, maybeOptions);
@@ -561,8 +581,8 @@ export const createDurableContext = <Logger extends DurableLogger>(
561581
parentContext: Context,
562582
durableExecutionMode: DurableExecutionMode,
563583
inheritedLogger: Logger,
564-
stepPrefix?: string,
565-
checkpointToken?: string,
584+
stepPrefix: string | undefined,
585+
durableExecution: DurableExecution,
566586
parentId?: string,
567587
): DurableContextImpl<Logger> => {
568588
return new DurableContextImpl<Logger>(
@@ -571,7 +591,7 @@ export const createDurableContext = <Logger extends DurableLogger>(
571591
durableExecutionMode,
572592
inheritedLogger,
573593
stepPrefix,
574-
checkpointToken,
594+
durableExecution,
575595
parentId,
576596
);
577597
};

0 commit comments

Comments
 (0)