Skip to content

Commit 000eb3a

Browse files
SilanHehsilan
andauthored
fix(sdk): Use current time for onOperationAttemptStart startTimestamp (#718)
*Issue #, if available:* *Description of changes:* Replace the startTimestamp derived from stepData (the checkpoint record) with new Date() so that plugins receive the actual wall-clock time when each attempt begins executing. Updated tests to assert startTimestamp is a recent Date instance. By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice. Co-authored-by: hsilan <hsilan@amazon.com>
1 parent f4373e8 commit 000eb3a

4 files changed

Lines changed: 29 additions & 2 deletions

File tree

packages/aws-durable-execution-sdk-js/src/handlers/step-handler/step-handler.plugin.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ describe("Step Handler - plugin hooks", () => {
7878
});
7979

8080
it("should call onOperationAttemptStart and onOperationAttemptEnd with succeeded outcome on success", async () => {
81+
const beforeTime = new Date();
8182
const stepHandler = createStepHandler(
8283
mockContext,
8384
mockCheckpoint,
@@ -92,12 +93,24 @@ describe("Step Handler - plugin hooks", () => {
9293
const stepFn = jest.fn().mockResolvedValue("result");
9394

9495
await stepHandler("my-step", stepFn);
96+
const afterTime = new Date();
9597

9698
expect(mockPlugin.onOperationAttemptStart).toHaveBeenCalledTimes(1);
9799
expect(mockPlugin.onOperationAttemptStart).toHaveBeenCalledWith(
98100
expect.objectContaining({ attempt: 1, isReplay: false }),
99101
);
100102

103+
// Verify startTimestamp is the current time, not from stepData
104+
const attemptInfo = (mockPlugin.onOperationAttemptStart as jest.Mock).mock
105+
.calls[0][0];
106+
expect(attemptInfo.startTimestamp).toBeInstanceOf(Date);
107+
expect(attemptInfo.startTimestamp.getTime()).toBeGreaterThanOrEqual(
108+
beforeTime.getTime(),
109+
);
110+
expect(attemptInfo.startTimestamp.getTime()).toBeLessThanOrEqual(
111+
afterTime.getTime(),
112+
);
113+
101114
expect(mockPlugin.wrapOperationAttemptFn).toHaveBeenCalledTimes(1);
102115
expect(mockPlugin.wrapOperationAttemptFn).toHaveBeenCalledWith(
103116
expect.objectContaining({ attempt: 1, isReplay: false }),

packages/aws-durable-execution-sdk-js/src/handlers/step-handler/step-handler.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@ export const createStepHandler = <Logger extends DurableLogger>(
323323
);
324324
const attemptInfo = toAttemptInfo(stepData, currentAttempt);
325325
backfillOperationInfo(attemptInfo, opInfo);
326+
attemptInfo.startTimestamp = new Date();
326327
await plugin.onOperationAttemptStart?.(attemptInfo);
327328
let result: T;
328329
const stepFn = (): Promise<T> => fn(stepContext);

packages/aws-durable-execution-sdk-js/src/handlers/wait-for-condition-handler/wait-for-condition-handler.plugin.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ describe("WaitForCondition Handler - plugin hooks", () => {
8484
(_info: unknown, fn: () => unknown) => fn(),
8585
);
8686

87+
const beforeTime = new Date();
8788
const handler = createWaitForConditionHandler(
8889
mockContext,
8990
mockCheckpoint,
@@ -103,12 +104,24 @@ describe("WaitForCondition Handler - plugin hooks", () => {
103104
};
104105

105106
await handler("my-condition", checkFunc, config);
107+
const afterTime = new Date();
106108

107109
expect(mockPlugin.onOperationAttemptStart).toHaveBeenCalledTimes(1);
108110
expect(mockPlugin.onOperationAttemptStart).toHaveBeenCalledWith(
109111
expect.objectContaining({ attempt: 1, isReplay: false }),
110112
);
111113

114+
// Verify startTimestamp is the current time, not from stepData
115+
const attemptInfo = (mockPlugin.onOperationAttemptStart as jest.Mock).mock
116+
.calls[0][0];
117+
expect(attemptInfo.startTimestamp).toBeInstanceOf(Date);
118+
expect(attemptInfo.startTimestamp.getTime()).toBeGreaterThanOrEqual(
119+
beforeTime.getTime(),
120+
);
121+
expect(attemptInfo.startTimestamp.getTime()).toBeLessThanOrEqual(
122+
afterTime.getTime(),
123+
);
124+
112125
expect(mockPlugin.wrapOperationAttemptFn).toHaveBeenCalledTimes(1);
113126
expect(mockPlugin.wrapOperationAttemptFn).toHaveBeenCalledWith(
114127
expect.objectContaining({ attempt: 1, isReplay: false }),

packages/aws-durable-execution-sdk-js/src/handlers/wait-for-condition-handler/wait-for-condition-handler.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,7 @@ export const createWaitForConditionHandler = <Logger extends DurableLogger>(
5555
return <T>(
5656
nameOrCheck: string | undefined | WaitForConditionCheckFunc<T, Logger>,
5757
checkOrConfig?:
58-
| WaitForConditionCheckFunc<T, Logger>
59-
| WaitForConditionConfig<T>,
58+
WaitForConditionCheckFunc<T, Logger> | WaitForConditionConfig<T>,
6059
maybeConfig?: WaitForConditionConfig<T>,
6160
): DurablePromise<T> => {
6261
let name: string | undefined;
@@ -248,6 +247,7 @@ export const createWaitForConditionHandler = <Logger extends DurableLogger>(
248247

249248
const attemptInfo = toAttemptInfo(stepData, currentAttempt);
250249
backfillOperationInfo(attemptInfo, opInfo);
250+
attemptInfo.startTimestamp = new Date();
251251
const checkFunc = () => check(currentState, waitForConditionContext);
252252

253253
await plugin.onOperationAttemptStart?.(attemptInfo);

0 commit comments

Comments
 (0)