deepline 0.1.60 → 0.1.61
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/index.js +2 -2
- package/dist/cli/index.mjs +2 -2
- package/dist/index.js +2 -2
- package/dist/index.mjs +2 -2
- package/dist/repo/apps/play-runner-workers/src/coordinator-entry.ts +8 -5
- package/dist/repo/apps/play-runner-workers/src/entry.ts +46 -30
- package/dist/repo/apps/play-runner-workers/src/runtime/receipts.ts +65 -41
- package/dist/repo/sdk/src/release.ts +2 -2
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -220,10 +220,10 @@ function resolveConfig(options) {
|
|
|
220
220
|
|
|
221
221
|
// src/release.ts
|
|
222
222
|
var SDK_RELEASE = {
|
|
223
|
-
version: "0.1.
|
|
223
|
+
version: "0.1.61",
|
|
224
224
|
apiContract: "2026-05-play-bootstrap-dataset-summary",
|
|
225
225
|
supportPolicy: {
|
|
226
|
-
latest: "0.1.
|
|
226
|
+
latest: "0.1.61",
|
|
227
227
|
minimumSupported: "0.1.53",
|
|
228
228
|
deprecatedBelow: "0.1.53"
|
|
229
229
|
}
|
package/dist/cli/index.mjs
CHANGED
|
@@ -197,10 +197,10 @@ function resolveConfig(options) {
|
|
|
197
197
|
|
|
198
198
|
// src/release.ts
|
|
199
199
|
var SDK_RELEASE = {
|
|
200
|
-
version: "0.1.
|
|
200
|
+
version: "0.1.61",
|
|
201
201
|
apiContract: "2026-05-play-bootstrap-dataset-summary",
|
|
202
202
|
supportPolicy: {
|
|
203
|
-
latest: "0.1.
|
|
203
|
+
latest: "0.1.61",
|
|
204
204
|
minimumSupported: "0.1.53",
|
|
205
205
|
deprecatedBelow: "0.1.53"
|
|
206
206
|
}
|
package/dist/index.js
CHANGED
|
@@ -232,10 +232,10 @@ function resolveConfig(options) {
|
|
|
232
232
|
|
|
233
233
|
// src/release.ts
|
|
234
234
|
var SDK_RELEASE = {
|
|
235
|
-
version: "0.1.
|
|
235
|
+
version: "0.1.61",
|
|
236
236
|
apiContract: "2026-05-play-bootstrap-dataset-summary",
|
|
237
237
|
supportPolicy: {
|
|
238
|
-
latest: "0.1.
|
|
238
|
+
latest: "0.1.61",
|
|
239
239
|
minimumSupported: "0.1.53",
|
|
240
240
|
deprecatedBelow: "0.1.53"
|
|
241
241
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -170,10 +170,10 @@ function resolveConfig(options) {
|
|
|
170
170
|
|
|
171
171
|
// src/release.ts
|
|
172
172
|
var SDK_RELEASE = {
|
|
173
|
-
version: "0.1.
|
|
173
|
+
version: "0.1.61",
|
|
174
174
|
apiContract: "2026-05-play-bootstrap-dataset-summary",
|
|
175
175
|
supportPolicy: {
|
|
176
|
-
latest: "0.1.
|
|
176
|
+
latest: "0.1.61",
|
|
177
177
|
minimumSupported: "0.1.53",
|
|
178
178
|
deprecatedBelow: "0.1.53"
|
|
179
179
|
}
|
|
@@ -545,7 +545,7 @@ const WORKFLOW_POOL_PROTOCOL_VERSION =
|
|
|
545
545
|
const WORKFLOW_POOL_DO_NAME = 'workflow-pool:v2';
|
|
546
546
|
const WORKFLOW_POOL_START_EVENT_TYPE = 'play_start';
|
|
547
547
|
const WORKFLOW_POOL_TTL_MS = 8 * 60 * 1000;
|
|
548
|
-
const WORKFLOW_POOL_TARGET_SIZE =
|
|
548
|
+
const WORKFLOW_POOL_TARGET_SIZE = 0;
|
|
549
549
|
const WORKFLOW_POOL_READY_TIMEOUT_MS = 1_500;
|
|
550
550
|
const WORKFLOW_POOL_READY_POLL_MS = 250;
|
|
551
551
|
const WORKFLOW_POOL_REFILL_ON_MISS_TIMEOUT_MS = 2_500;
|
|
@@ -3637,10 +3637,10 @@ async function handleWorkflowRoute(input: {
|
|
|
3637
3637
|
}
|
|
3638
3638
|
return Response.json({ runId, status: 'cancelled' });
|
|
3639
3639
|
}
|
|
3640
|
-
if (!instance) {
|
|
3641
|
-
return new Response('not found', { status: 404 });
|
|
3642
|
-
}
|
|
3643
3640
|
if (action === 'signal') {
|
|
3641
|
+
if (!instance) {
|
|
3642
|
+
return new Response('not found', { status: 404 });
|
|
3643
|
+
}
|
|
3644
3644
|
const body = (await request.json().catch(() => ({}))) as Record<
|
|
3645
3645
|
string,
|
|
3646
3646
|
unknown
|
|
@@ -3697,11 +3697,14 @@ async function handleWorkflowRoute(input: {
|
|
|
3697
3697
|
waitMs: 0,
|
|
3698
3698
|
workflowStatus: 'terminal-cache',
|
|
3699
3699
|
statusPolls: 0,
|
|
3700
|
-
instanceId: instance
|
|
3700
|
+
instanceId: instance?.id ?? null,
|
|
3701
3701
|
},
|
|
3702
3702
|
...(includeTrace ? { coordinatorTrace } : {}),
|
|
3703
3703
|
});
|
|
3704
3704
|
}
|
|
3705
|
+
if (!instance) {
|
|
3706
|
+
return new Response('not found', { status: 404 });
|
|
3707
|
+
}
|
|
3705
3708
|
const status = await instance.status();
|
|
3706
3709
|
const workflowError = readWorkflowError(status);
|
|
3707
3710
|
if (workflowError) {
|
|
@@ -3141,6 +3141,7 @@ function createMinimalWorkerCtx(
|
|
|
3141
3141
|
): unknown {
|
|
3142
3142
|
let playCallCount = 0;
|
|
3143
3143
|
const parentChildCalls: Record<string, number> = {};
|
|
3144
|
+
const stepCallCounts: Record<string, number> = {};
|
|
3144
3145
|
const inFlightChildCallsByPlayName: Record<string, number> = {};
|
|
3145
3146
|
let inFlightChildPlayCalls = 0;
|
|
3146
3147
|
const childPlaySlotWaiters: Array<() => void> = [];
|
|
@@ -3182,6 +3183,7 @@ function createMinimalWorkerCtx(
|
|
|
3182
3183
|
const executeWithRuntimeReceipt = async <T>(
|
|
3183
3184
|
key: string,
|
|
3184
3185
|
execute: () => Promise<T> | T,
|
|
3186
|
+
repairRunningReceiptForSameRun = false,
|
|
3185
3187
|
): Promise<T> => {
|
|
3186
3188
|
const serialized = await runWorkerRuntimeReceiptBoundary<unknown>({
|
|
3187
3189
|
baseUrl: req.baseUrl,
|
|
@@ -3192,9 +3194,36 @@ function createMinimalWorkerCtx(
|
|
|
3192
3194
|
key,
|
|
3193
3195
|
postRuntimeApi,
|
|
3194
3196
|
execute: async () => serializeDurableStepValue(await execute()),
|
|
3197
|
+
repairRunningReceiptForSameRun,
|
|
3195
3198
|
});
|
|
3196
3199
|
return deserializeDurableStepValue(serialized) as T;
|
|
3197
3200
|
};
|
|
3201
|
+
const executeWithWorkflowStep = async <T>(
|
|
3202
|
+
name: string,
|
|
3203
|
+
execute: () => Promise<T> | T,
|
|
3204
|
+
): Promise<T> => {
|
|
3205
|
+
if (!workflowStep) {
|
|
3206
|
+
return await executeWithRuntimeReceipt(name, execute);
|
|
3207
|
+
}
|
|
3208
|
+
return await executeWithRuntimeReceipt(
|
|
3209
|
+
name,
|
|
3210
|
+
async () => {
|
|
3211
|
+
const serialized = await (
|
|
3212
|
+
workflowStep.do as unknown as (
|
|
3213
|
+
name: string,
|
|
3214
|
+
callback: () => Promise<unknown>,
|
|
3215
|
+
) => Promise<unknown>
|
|
3216
|
+
)(name, async () => serializeDurableStepValue(await execute()));
|
|
3217
|
+
return deserializeDurableStepValue(serialized) as T;
|
|
3218
|
+
},
|
|
3219
|
+
true,
|
|
3220
|
+
);
|
|
3221
|
+
};
|
|
3222
|
+
const nextCtxStepReceiptKey = (name: string): string => {
|
|
3223
|
+
const count = stepCallCounts[name] ?? 0;
|
|
3224
|
+
stepCallCounts[name] = count + 1;
|
|
3225
|
+
return count === 0 ? `step:${name}` : `step:${name}:${count}`;
|
|
3226
|
+
};
|
|
3198
3227
|
const staleRuntimeSuffix = (staleAfterSeconds?: number): string => {
|
|
3199
3228
|
if (staleAfterSeconds === undefined) return '';
|
|
3200
3229
|
if (
|
|
@@ -3952,11 +3981,8 @@ function createMinimalWorkerCtx(
|
|
|
3952
3981
|
if (!normalizedName) {
|
|
3953
3982
|
throw new Error('ctx.step(name, callback) requires a name.');
|
|
3954
3983
|
}
|
|
3955
|
-
|
|
3956
|
-
|
|
3957
|
-
// inside the JS stage before they reach subsequent event waits.
|
|
3958
|
-
return await executeWithRuntimeReceipt(
|
|
3959
|
-
`step:${normalizedName}${staleRuntimeSuffix(options?.staleAfterSeconds)}`,
|
|
3984
|
+
return await executeWithWorkflowStep(
|
|
3985
|
+
`${nextCtxStepReceiptKey(normalizedName)}${staleRuntimeSuffix(options?.staleAfterSeconds)}`,
|
|
3960
3986
|
callback,
|
|
3961
3987
|
);
|
|
3962
3988
|
},
|
|
@@ -4607,7 +4633,7 @@ async function executeRunRequest(
|
|
|
4607
4633
|
runtimeBackend: 'cf_workflows_dynamic_worker',
|
|
4608
4634
|
},
|
|
4609
4635
|
];
|
|
4610
|
-
let lastLedgerFlushAt =
|
|
4636
|
+
let lastLedgerFlushAt = startedAt;
|
|
4611
4637
|
let ledgerFlushInFlight: Promise<void> = Promise.resolve();
|
|
4612
4638
|
|
|
4613
4639
|
const appendRunLogLine = (line: string) => {
|
|
@@ -4760,7 +4786,6 @@ async function executeRunRequest(
|
|
|
4760
4786
|
terminalEvent: PlayRunLedgerEvent,
|
|
4761
4787
|
): Promise<void> => {
|
|
4762
4788
|
if (!options?.persistResultDatasets) return;
|
|
4763
|
-
await ledgerFlushInFlight.catch(() => undefined);
|
|
4764
4789
|
const now = nowMs();
|
|
4765
4790
|
pendingRunLogLines = runLogBuffer;
|
|
4766
4791
|
dirtyProgressNodeIds = new Set([
|
|
@@ -4768,6 +4793,7 @@ async function executeRunRequest(
|
|
|
4768
4793
|
...Object.keys(stepProgressByNodeId),
|
|
4769
4794
|
]);
|
|
4770
4795
|
pendingLedgerEvents = [...pendingLedgerEvents, terminalEvent];
|
|
4796
|
+
await ledgerFlushInFlight;
|
|
4771
4797
|
const events = drainPendingLedgerEvents(now);
|
|
4772
4798
|
if (events.length === 0) return;
|
|
4773
4799
|
try {
|
|
@@ -4851,7 +4877,7 @@ async function executeRunRequest(
|
|
|
4851
4877
|
});
|
|
4852
4878
|
if (options?.persistResultDatasets) {
|
|
4853
4879
|
const ledgerFlushWaitStartedAt = nowMs();
|
|
4854
|
-
await ledgerFlushInFlight
|
|
4880
|
+
await ledgerFlushInFlight;
|
|
4855
4881
|
recordRunnerPerfTrace({
|
|
4856
4882
|
req,
|
|
4857
4883
|
phase: 'runner.run_ledger_flush_wait',
|
|
@@ -4866,29 +4892,19 @@ async function executeRunRequest(
|
|
|
4866
4892
|
});
|
|
4867
4893
|
const terminalResult = trimResultForStatus(serializedResult);
|
|
4868
4894
|
const terminalOccurredAt = nowMs();
|
|
4869
|
-
const
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
|
|
4877
|
-
|
|
4878
|
-
|
|
4879
|
-
|
|
4880
|
-
|
|
4881
|
-
ms: nowMs() - terminalUpdateStartedAt,
|
|
4882
|
-
});
|
|
4883
|
-
})().catch((error) => {
|
|
4884
|
-
console.error(
|
|
4885
|
-
`[play-harness] non-fatal terminal ledger append failed runId=${req.runId}: ${
|
|
4886
|
-
error instanceof Error ? error.message : String(error)
|
|
4887
|
-
}`,
|
|
4888
|
-
);
|
|
4895
|
+
const terminalUpdateStartedAt = nowMs();
|
|
4896
|
+
await flushTerminalLedgerEvents({
|
|
4897
|
+
type: 'run.completed',
|
|
4898
|
+
runId: req.runId,
|
|
4899
|
+
source: 'worker',
|
|
4900
|
+
occurredAt: terminalOccurredAt,
|
|
4901
|
+
result: terminalResult,
|
|
4902
|
+
});
|
|
4903
|
+
recordRunnerPerfTrace({
|
|
4904
|
+
req,
|
|
4905
|
+
phase: 'runner.terminal_ledger_append',
|
|
4906
|
+
ms: nowMs() - terminalUpdateStartedAt,
|
|
4889
4907
|
});
|
|
4890
|
-
|
|
4891
|
-
await terminalLedgerPromise;
|
|
4892
4908
|
|
|
4893
4909
|
const billingStartedAt = nowMs();
|
|
4894
4910
|
const billingPromise = finalizeWorkerComputeBilling({
|
|
@@ -59,6 +59,10 @@ type RuntimeReceiptContext = {
|
|
|
59
59
|
) => Promise<WorkerRuntimeReceiptResponse>;
|
|
60
60
|
};
|
|
61
61
|
|
|
62
|
+
type PostRuntimeReceiptAction = (
|
|
63
|
+
body: WorkerRuntimeReceiptAction,
|
|
64
|
+
) => Promise<WorkerRuntimeReceiptResponse>;
|
|
65
|
+
|
|
62
66
|
function scopedReceiptKey(input: {
|
|
63
67
|
orgId?: string | null;
|
|
64
68
|
playName: string;
|
|
@@ -81,27 +85,57 @@ function runningReceiptError(key: string, receipt: WorkerRuntimeReceipt): Error
|
|
|
81
85
|
);
|
|
82
86
|
}
|
|
83
87
|
|
|
88
|
+
async function executeAndPersistReceipt<T>(input: {
|
|
89
|
+
key: string;
|
|
90
|
+
playName: string;
|
|
91
|
+
runId: string;
|
|
92
|
+
execute: () => Promise<T> | T;
|
|
93
|
+
postRuntimeReceiptAction: PostRuntimeReceiptAction;
|
|
94
|
+
ownership: 'claimed' | 'workflow_replay';
|
|
95
|
+
}): Promise<T> {
|
|
96
|
+
let output: T;
|
|
97
|
+
try {
|
|
98
|
+
output = await input.execute();
|
|
99
|
+
} catch (error) {
|
|
100
|
+
const failed = await input.postRuntimeReceiptAction({
|
|
101
|
+
action: 'fail_runtime_step_receipt',
|
|
102
|
+
playName: input.playName,
|
|
103
|
+
runId: input.runId,
|
|
104
|
+
key: input.key,
|
|
105
|
+
error: errorMessage(error),
|
|
106
|
+
});
|
|
107
|
+
if (!failed.receipt) {
|
|
108
|
+
throw new Error(
|
|
109
|
+
`Runtime receipt ${input.key} ${input.ownership} execution failed and failed receipt could not be persisted: ${errorMessage(error)}`,
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
throw error;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
const completed = await input.postRuntimeReceiptAction({
|
|
116
|
+
action: 'complete_runtime_step_receipt',
|
|
117
|
+
playName: input.playName,
|
|
118
|
+
runId: input.runId,
|
|
119
|
+
key: input.key,
|
|
120
|
+
output,
|
|
121
|
+
});
|
|
122
|
+
if (!completed.receipt) {
|
|
123
|
+
throw new Error(
|
|
124
|
+
`Runtime receipt ${input.key} ${input.ownership} execution completed but completed receipt could not be persisted.`,
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
return output;
|
|
128
|
+
}
|
|
129
|
+
|
|
84
130
|
export async function runWorkerRuntimeReceiptBoundary<T>(
|
|
85
131
|
input: RuntimeReceiptContext & {
|
|
86
132
|
execute: () => Promise<T> | T;
|
|
133
|
+
repairRunningReceiptForSameRun?: boolean;
|
|
87
134
|
},
|
|
88
135
|
): Promise<T> {
|
|
89
136
|
const key = scopedReceiptKey(input);
|
|
90
137
|
const postRuntimeReceiptAction = (body: WorkerRuntimeReceiptAction) =>
|
|
91
138
|
input.postRuntimeApi(input.baseUrl, input.executorToken, body);
|
|
92
|
-
const existing = await postRuntimeReceiptAction({
|
|
93
|
-
action: 'get_runtime_step_receipt',
|
|
94
|
-
playName: input.playName,
|
|
95
|
-
runId: input.runId,
|
|
96
|
-
key,
|
|
97
|
-
});
|
|
98
|
-
if (
|
|
99
|
-
existing.receipt?.status === 'completed' ||
|
|
100
|
-
existing.receipt?.status === 'skipped'
|
|
101
|
-
) {
|
|
102
|
-
return receiptOutput<T>(existing.receipt);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
139
|
const claimed = await postRuntimeReceiptAction({
|
|
106
140
|
action: 'claim_runtime_step_receipt',
|
|
107
141
|
playName: input.playName,
|
|
@@ -122,6 +156,19 @@ export async function runWorkerRuntimeReceiptBoundary<T>(
|
|
|
122
156
|
return receiptOutput<T>(latest.receipt);
|
|
123
157
|
}
|
|
124
158
|
if (latest.receipt?.status === 'running') {
|
|
159
|
+
if (
|
|
160
|
+
input.repairRunningReceiptForSameRun &&
|
|
161
|
+
latest.receipt.runId === input.runId
|
|
162
|
+
) {
|
|
163
|
+
return executeAndPersistReceipt({
|
|
164
|
+
key,
|
|
165
|
+
playName: input.playName,
|
|
166
|
+
runId: input.runId,
|
|
167
|
+
execute: input.execute,
|
|
168
|
+
postRuntimeReceiptAction,
|
|
169
|
+
ownership: 'workflow_replay',
|
|
170
|
+
});
|
|
171
|
+
}
|
|
125
172
|
throw runningReceiptError(key, latest.receipt);
|
|
126
173
|
}
|
|
127
174
|
if (latest.receipt?.status === 'failed') {
|
|
@@ -134,35 +181,12 @@ export async function runWorkerRuntimeReceiptBoundary<T>(
|
|
|
134
181
|
);
|
|
135
182
|
}
|
|
136
183
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
output = await input.execute();
|
|
140
|
-
} catch (error) {
|
|
141
|
-
const failed = await postRuntimeReceiptAction({
|
|
142
|
-
action: 'fail_runtime_step_receipt',
|
|
143
|
-
playName: input.playName,
|
|
144
|
-
runId: input.runId,
|
|
145
|
-
key,
|
|
146
|
-
error: errorMessage(error),
|
|
147
|
-
});
|
|
148
|
-
if (!failed.receipt) {
|
|
149
|
-
throw new Error(
|
|
150
|
-
`Runtime receipt ${key} execution failed and failed receipt could not be persisted: ${errorMessage(error)}`,
|
|
151
|
-
);
|
|
152
|
-
}
|
|
153
|
-
throw error;
|
|
154
|
-
}
|
|
155
|
-
const completed = await postRuntimeReceiptAction({
|
|
156
|
-
action: 'complete_runtime_step_receipt',
|
|
184
|
+
return executeAndPersistReceipt({
|
|
185
|
+
key,
|
|
157
186
|
playName: input.playName,
|
|
158
187
|
runId: input.runId,
|
|
159
|
-
|
|
160
|
-
|
|
188
|
+
execute: input.execute,
|
|
189
|
+
postRuntimeReceiptAction,
|
|
190
|
+
ownership: 'claimed',
|
|
161
191
|
});
|
|
162
|
-
if (!completed.receipt) {
|
|
163
|
-
throw new Error(
|
|
164
|
-
`Runtime receipt ${key} execution completed but completed receipt could not be persisted.`,
|
|
165
|
-
);
|
|
166
|
-
}
|
|
167
|
-
return output;
|
|
168
192
|
}
|
|
@@ -50,10 +50,10 @@ export type SdkRelease = {
|
|
|
50
50
|
};
|
|
51
51
|
|
|
52
52
|
export const SDK_RELEASE = {
|
|
53
|
-
version: '0.1.
|
|
53
|
+
version: '0.1.61',
|
|
54
54
|
apiContract: '2026-05-play-bootstrap-dataset-summary',
|
|
55
55
|
supportPolicy: {
|
|
56
|
-
latest: '0.1.
|
|
56
|
+
latest: '0.1.61',
|
|
57
57
|
minimumSupported: '0.1.53',
|
|
58
58
|
deprecatedBelow: '0.1.53',
|
|
59
59
|
},
|