deepline 0.3.283 → 0.3.285
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/bundling-sources/sdk/src/release.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/activity-observation.ts +26 -2
- package/dist/bundling-sources/shared_libs/play-runtime/batch-runtime.ts +7 -0
- package/dist/bundling-sources/shared_libs/play-runtime/context.ts +817 -2236
- package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +19 -6
- package/dist/bundling-sources/shared_libs/play-runtime/durable-receipt-execution.ts +127 -789
- package/dist/bundling-sources/shared_libs/play-runtime/run-ledger.ts +180 -14
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/index.ts +1 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +3 -22
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-incident-drills.ts +26 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +50 -8
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-progress.ts +122 -18
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +218 -41
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-sandbox-capacity.ts +20 -2
- package/dist/bundling-sources/shared_libs/play-runtime/test-runtime-seams.ts +13 -2
- package/dist/bundling-sources/shared_libs/play-runtime/tool-call/receipt-cohort.ts +181 -326
- package/dist/bundling-sources/shared_libs/play-runtime/tool-call/runtime-step-receipts-adapter.ts +38 -151
- package/dist/bundling-sources/shared_libs/play-runtime/worker-api-types.ts +8 -0
- package/dist/bundling-sources/shared_libs/security/secret-redaction.ts +89 -1
- package/dist/cli/index.js +28 -3
- package/dist/cli/index.mjs +28 -3
- package/dist/{client-B0AjIkgb.d.mts → client-Cl-zj2oS.d.mts} +4 -0
- package/dist/{client-BCXQ_Ftc.d.ts → client-T2jVnZrq.d.ts} +4 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +25 -1
- package/dist/index.mjs +25 -1
- package/dist/install-integrity.json +2 -2
- package/dist/plays/run-request.d.mts +1 -1
- package/dist/plays/run-request.d.ts +1 -1
- package/dist/release.d.mts +1 -1
- package/dist/release.d.ts +1 -1
- package/dist/release.js +1 -1
- package/dist/release.mjs +1 -1
- package/package.json +1 -1
|
@@ -44,6 +44,13 @@ export type PlayRunLedgerStepStatus =
|
|
|
44
44
|
|
|
45
45
|
export type PlayRunLedgerEventSource = RunEventSource;
|
|
46
46
|
|
|
47
|
+
/** Authority of the row sample, independent of gateway process lifetime. */
|
|
48
|
+
export type PlayMapRowActivitySource =
|
|
49
|
+
| 'resolver'
|
|
50
|
+
| 'map_start'
|
|
51
|
+
| 'map_event'
|
|
52
|
+
| 'log';
|
|
53
|
+
|
|
47
54
|
/**
|
|
48
55
|
* Live progress for a single step/node.
|
|
49
56
|
*
|
|
@@ -76,6 +83,13 @@ export type PlayRunLedgerStepProgress = {
|
|
|
76
83
|
startedRows?: number;
|
|
77
84
|
activeRows?: number;
|
|
78
85
|
waitingRows?: number;
|
|
86
|
+
/** Internal provenance for merging stateless progress batches. */
|
|
87
|
+
rowActivitySource?: PlayMapRowActivitySource;
|
|
88
|
+
/** Existing logical map identity, absent from legacy progress writers. */
|
|
89
|
+
mapInvocationId?: string;
|
|
90
|
+
/** Existing runner event times for pool boundaries and row observations. */
|
|
91
|
+
rowActivityStartedAt?: number;
|
|
92
|
+
rowActivityObservedAt?: number;
|
|
79
93
|
completedRows?: number;
|
|
80
94
|
supersededRows?: number;
|
|
81
95
|
message?: string;
|
|
@@ -1073,8 +1087,112 @@ function mergeMonotonicStepProgress(input: {
|
|
|
1073
1087
|
current?: PlayRunLedgerStepProgress | null;
|
|
1074
1088
|
next: PlayRunLedgerStepProgress;
|
|
1075
1089
|
}): PlayRunLedgerStepProgress {
|
|
1076
|
-
const
|
|
1077
|
-
const
|
|
1090
|
+
const previous = input.current ?? {};
|
|
1091
|
+
const hasMapInvocationIdentities =
|
|
1092
|
+
previous.mapInvocationId !== undefined &&
|
|
1093
|
+
input.next.mapInvocationId !== undefined;
|
|
1094
|
+
const differentMapInvocation =
|
|
1095
|
+
hasMapInvocationIdentities &&
|
|
1096
|
+
previous.mapInvocationId !== input.next.mapInvocationId;
|
|
1097
|
+
const sameMapInvocation =
|
|
1098
|
+
previous.mapInvocationId !== undefined &&
|
|
1099
|
+
previous.mapInvocationId === input.next.mapInvocationId;
|
|
1100
|
+
const previousPoolStartedAt =
|
|
1101
|
+
previous.rowActivityStartedAt ?? previous.rowActivityObservedAt;
|
|
1102
|
+
const observesEarlierSourceTime =
|
|
1103
|
+
typeof previous.rowActivityObservedAt === 'number' &&
|
|
1104
|
+
typeof input.next.rowActivityObservedAt === 'number' &&
|
|
1105
|
+
input.next.rowActivityObservedAt < previous.rowActivityObservedAt;
|
|
1106
|
+
const replaysOlderMapBoundary =
|
|
1107
|
+
hasMapInvocationIdentities &&
|
|
1108
|
+
input.next.rowActivitySource === 'map_start' &&
|
|
1109
|
+
(observesEarlierSourceTime ||
|
|
1110
|
+
(sameMapInvocation &&
|
|
1111
|
+
typeof previousPoolStartedAt === 'number' &&
|
|
1112
|
+
typeof input.next.rowActivityStartedAt === 'number' &&
|
|
1113
|
+
input.next.rowActivityStartedAt <= previousPoolStartedAt));
|
|
1114
|
+
const replaysOlderResolverSample =
|
|
1115
|
+
hasMapInvocationIdentities &&
|
|
1116
|
+
input.next.rowActivitySource === 'resolver' &&
|
|
1117
|
+
observesEarlierSourceTime;
|
|
1118
|
+
const replaysOlderCountObservation =
|
|
1119
|
+
hasMapInvocationIdentities &&
|
|
1120
|
+
input.next.rowActivitySource === 'map_event' &&
|
|
1121
|
+
input.next.completedAt === undefined &&
|
|
1122
|
+
observesEarlierSourceTime;
|
|
1123
|
+
const replaysOlderMapObservation =
|
|
1124
|
+
replaysOlderMapBoundary ||
|
|
1125
|
+
replaysOlderResolverSample ||
|
|
1126
|
+
replaysOlderCountObservation;
|
|
1127
|
+
const changesMapInvocation =
|
|
1128
|
+
differentMapInvocation &&
|
|
1129
|
+
!replaysOlderMapObservation &&
|
|
1130
|
+
input.next.rowActivitySource !== undefined &&
|
|
1131
|
+
input.next.rowActivitySource !== 'log';
|
|
1132
|
+
const startsExecutionPool =
|
|
1133
|
+
sameMapInvocation &&
|
|
1134
|
+
!replaysOlderMapObservation &&
|
|
1135
|
+
(input.next.rowActivitySource === 'map_start' ||
|
|
1136
|
+
((input.next.rowActivitySource === 'resolver' ||
|
|
1137
|
+
input.next.rowActivitySource === 'map_event') &&
|
|
1138
|
+
typeof previousPoolStartedAt === 'number' &&
|
|
1139
|
+
typeof input.next.rowActivityStartedAt === 'number' &&
|
|
1140
|
+
input.next.rowActivityStartedAt > previousPoolStartedAt));
|
|
1141
|
+
const replacesInferredActivity =
|
|
1142
|
+
sameMapInvocation &&
|
|
1143
|
+
!replaysOlderMapObservation &&
|
|
1144
|
+
input.next.rowActivitySource === 'resolver' &&
|
|
1145
|
+
previous.rowActivitySource !== undefined &&
|
|
1146
|
+
previous.rowActivitySource !== 'resolver';
|
|
1147
|
+
// Admission belongs to the current execution pool. The logical map identity
|
|
1148
|
+
// survives replay/pages, so only a witnessed pool boundary or newer typed
|
|
1149
|
+
// invocation resets activity. Accepted row outcomes remain monotonic.
|
|
1150
|
+
const current =
|
|
1151
|
+
changesMapInvocation || startsExecutionPool || replacesInferredActivity
|
|
1152
|
+
? {
|
|
1153
|
+
...previous,
|
|
1154
|
+
startedRows: undefined,
|
|
1155
|
+
activeRows: undefined,
|
|
1156
|
+
waitingRows: undefined,
|
|
1157
|
+
rowActivitySource: undefined,
|
|
1158
|
+
...(changesMapInvocation
|
|
1159
|
+
? {
|
|
1160
|
+
rowActivityStartedAt: undefined,
|
|
1161
|
+
rowActivityObservedAt: undefined,
|
|
1162
|
+
}
|
|
1163
|
+
: {}),
|
|
1164
|
+
}
|
|
1165
|
+
: previous;
|
|
1166
|
+
// A gateway reporter is recreated for every batch. Only the durable fold
|
|
1167
|
+
// can keep a row-resolver sample authoritative when a later batch contains
|
|
1168
|
+
// tool-call or page-setup diagnostics without a repeated activity sample.
|
|
1169
|
+
// Lifecycle facts explicitly reset this authority; legacy absence retains
|
|
1170
|
+
// the historical merge behavior instead of guessing from numeric fields.
|
|
1171
|
+
const next =
|
|
1172
|
+
(current.rowActivitySource === 'resolver' &&
|
|
1173
|
+
input.next.rowActivitySource === 'log') ||
|
|
1174
|
+
(differentMapInvocation &&
|
|
1175
|
+
input.next.rowActivitySource === 'log' &&
|
|
1176
|
+
(current.rowActivitySource === 'map_start' ||
|
|
1177
|
+
current.rowActivitySource === 'map_event')) ||
|
|
1178
|
+
replaysOlderMapObservation
|
|
1179
|
+
? {
|
|
1180
|
+
...input.next,
|
|
1181
|
+
completed: current.completed,
|
|
1182
|
+
total: current.total,
|
|
1183
|
+
failed: current.failed,
|
|
1184
|
+
startedRows: current.startedRows,
|
|
1185
|
+
activeRows: current.activeRows,
|
|
1186
|
+
waitingRows: current.waitingRows,
|
|
1187
|
+
completedRows: current.completedRows,
|
|
1188
|
+
supersededRows: current.supersededRows,
|
|
1189
|
+
message: current.message,
|
|
1190
|
+
rowActivitySource: current.rowActivitySource,
|
|
1191
|
+
mapInvocationId: current.mapInvocationId,
|
|
1192
|
+
rowActivityStartedAt: current.rowActivityStartedAt,
|
|
1193
|
+
rowActivityObservedAt: current.rowActivityObservedAt,
|
|
1194
|
+
}
|
|
1195
|
+
: input.next;
|
|
1078
1196
|
const supersededRows = maxProgressNumber(
|
|
1079
1197
|
current.supersededRows,
|
|
1080
1198
|
next.supersededRows === undefined
|
|
@@ -1084,6 +1202,7 @@ function mergeMonotonicStepProgress(input: {
|
|
|
1084
1202
|
return {
|
|
1085
1203
|
...current,
|
|
1086
1204
|
...next,
|
|
1205
|
+
rowActivitySource: next.rowActivitySource,
|
|
1087
1206
|
...(maxProgressNumber(current.completed, next.completed) !== undefined
|
|
1088
1207
|
? { completed: maxProgressNumber(current.completed, next.completed) }
|
|
1089
1208
|
: {}),
|
|
@@ -1118,13 +1237,14 @@ function mergeMonotonicStepProgress(input: {
|
|
|
1118
1237
|
}
|
|
1119
1238
|
|
|
1120
1239
|
/**
|
|
1121
|
-
*
|
|
1122
|
-
* flight
|
|
1123
|
-
*
|
|
1124
|
-
* so leaving the last observed values renders a contradiction like
|
|
1240
|
+
* Clear stale in-flight row accounting on a settled step. Once a step is
|
|
1241
|
+
* terminal nothing is in flight or waiting, so leaving the last observed
|
|
1242
|
+
* values renders a contradiction like
|
|
1125
1243
|
* "status: completed · 1 in flight · waiting 29". This preserves the settled
|
|
1126
|
-
* counts (including supersededRows)
|
|
1127
|
-
*
|
|
1244
|
+
* counts (including supersededRows). A terminal map event or reconciliation
|
|
1245
|
+
* explicitly witnesses zero active and waiting rows; retain those zeros for
|
|
1246
|
+
* readers that follow the same counters through completion. Older writers
|
|
1247
|
+
* and nonterminal activity samples retain their existing omission behavior.
|
|
1128
1248
|
*/
|
|
1129
1249
|
function clearInFlightProgressOnTerminal(
|
|
1130
1250
|
progress: PlayRunLedgerStepProgress | null | undefined,
|
|
@@ -1134,16 +1254,23 @@ function clearInFlightProgressOnTerminal(
|
|
|
1134
1254
|
typeof progress.message === 'string'
|
|
1135
1255
|
? settledProgressMessage(progress.message, progress)
|
|
1136
1256
|
: progress.message;
|
|
1257
|
+
const witnessedTerminalZeroActivity =
|
|
1258
|
+
progress.rowActivitySource === 'map_event' &&
|
|
1259
|
+
progress.activeRows === 0 &&
|
|
1260
|
+
progress.waitingRows === 0;
|
|
1137
1261
|
if (
|
|
1138
|
-
|
|
1139
|
-
|
|
1262
|
+
(witnessedTerminalZeroActivity ||
|
|
1263
|
+
(progress.activeRows === undefined &&
|
|
1264
|
+
progress.waitingRows === undefined)) &&
|
|
1140
1265
|
message === progress.message
|
|
1141
1266
|
) {
|
|
1142
1267
|
return progress;
|
|
1143
1268
|
}
|
|
1144
1269
|
const cleared = { ...progress };
|
|
1145
|
-
|
|
1146
|
-
|
|
1270
|
+
if (!witnessedTerminalZeroActivity) {
|
|
1271
|
+
delete cleared.activeRows;
|
|
1272
|
+
delete cleared.waitingRows;
|
|
1273
|
+
}
|
|
1147
1274
|
if (message === undefined) delete cleared.message;
|
|
1148
1275
|
else cleared.message = message;
|
|
1149
1276
|
return cleared;
|
|
@@ -1222,6 +1349,29 @@ function normalizeStepProgress(
|
|
|
1222
1349
|
...(optionalFiniteNumber(value.waitingRows) !== undefined
|
|
1223
1350
|
? { waitingRows: optionalFiniteNumber(value.waitingRows) }
|
|
1224
1351
|
: {}),
|
|
1352
|
+
...(value.rowActivitySource === 'resolver' ||
|
|
1353
|
+
value.rowActivitySource === 'map_start' ||
|
|
1354
|
+
value.rowActivitySource === 'map_event' ||
|
|
1355
|
+
value.rowActivitySource === 'log'
|
|
1356
|
+
? { rowActivitySource: value.rowActivitySource }
|
|
1357
|
+
: {}),
|
|
1358
|
+
...(optionalString(value.mapInvocationId)
|
|
1359
|
+
? { mapInvocationId: optionalString(value.mapInvocationId) }
|
|
1360
|
+
: {}),
|
|
1361
|
+
...(optionalFiniteNumber(value.rowActivityStartedAt) !== undefined
|
|
1362
|
+
? {
|
|
1363
|
+
rowActivityStartedAt: optionalFiniteNumber(
|
|
1364
|
+
value.rowActivityStartedAt,
|
|
1365
|
+
),
|
|
1366
|
+
}
|
|
1367
|
+
: {}),
|
|
1368
|
+
...(optionalFiniteNumber(value.rowActivityObservedAt) !== undefined
|
|
1369
|
+
? {
|
|
1370
|
+
rowActivityObservedAt: optionalFiniteNumber(
|
|
1371
|
+
value.rowActivityObservedAt,
|
|
1372
|
+
),
|
|
1373
|
+
}
|
|
1374
|
+
: {}),
|
|
1225
1375
|
...(optionalFiniteNumber(value.completedRows) !== undefined
|
|
1226
1376
|
? { completedRows: optionalFiniteNumber(value.completedRows) }
|
|
1227
1377
|
: {}),
|
|
@@ -1936,8 +2086,8 @@ export function reducePlayRunLedgerEvent(
|
|
|
1936
2086
|
(status === 'completed' || status === 'failed'
|
|
1937
2087
|
? (completedAt ?? event.progress.updatedAt ?? occurredAt)
|
|
1938
2088
|
: null);
|
|
1939
|
-
// Once the step is settled,
|
|
1940
|
-
//
|
|
2089
|
+
// Once the step is settled, clear stale live counters while retaining
|
|
2090
|
+
// explicit terminal zero activity from the owning map event.
|
|
1941
2091
|
const progress = isTerminalStepStatus(status)
|
|
1942
2092
|
? clearInFlightProgressOnTerminal(mergedProgress)
|
|
1943
2093
|
: mergedProgress;
|
|
@@ -2139,6 +2289,10 @@ function progressSignature(
|
|
|
2139
2289
|
startedRows: progress?.startedRows ?? null,
|
|
2140
2290
|
activeRows: progress?.activeRows ?? null,
|
|
2141
2291
|
waitingRows: progress?.waitingRows ?? null,
|
|
2292
|
+
rowActivitySource: progress?.rowActivitySource ?? null,
|
|
2293
|
+
mapInvocationId: progress?.mapInvocationId ?? null,
|
|
2294
|
+
rowActivityStartedAt: progress?.rowActivityStartedAt ?? null,
|
|
2295
|
+
rowActivityObservedAt: progress?.rowActivityObservedAt ?? null,
|
|
2142
2296
|
completedRows: progress?.completedRows ?? null,
|
|
2143
2297
|
supersededRows: progress?.supersededRows ?? null,
|
|
2144
2298
|
message: progress?.message ?? null,
|
|
@@ -2438,6 +2592,18 @@ export function buildPlayRunLedgerEventsFromStatusPatch(input: {
|
|
|
2438
2592
|
...(progress.waitingRows !== undefined
|
|
2439
2593
|
? { waitingRows: progress.waitingRows }
|
|
2440
2594
|
: {}),
|
|
2595
|
+
...(progress.rowActivitySource !== undefined
|
|
2596
|
+
? { rowActivitySource: progress.rowActivitySource }
|
|
2597
|
+
: {}),
|
|
2598
|
+
...(progress.mapInvocationId !== undefined
|
|
2599
|
+
? { mapInvocationId: progress.mapInvocationId }
|
|
2600
|
+
: {}),
|
|
2601
|
+
...(progress.rowActivityStartedAt !== undefined
|
|
2602
|
+
? { rowActivityStartedAt: progress.rowActivityStartedAt }
|
|
2603
|
+
: {}),
|
|
2604
|
+
...(progress.rowActivityObservedAt !== undefined
|
|
2605
|
+
? { rowActivityObservedAt: progress.rowActivityObservedAt }
|
|
2606
|
+
: {}),
|
|
2441
2607
|
...(progress.completedRows !== undefined
|
|
2442
2608
|
? { completedRows: progress.completedRows }
|
|
2443
2609
|
: {}),
|
|
@@ -1839,29 +1839,10 @@ export const daytonaPlayRunnerBackend: PlayRunnerBackend = {
|
|
|
1839
1839
|
}),
|
|
1840
1840
|
);
|
|
1841
1841
|
} catch (error) {
|
|
1842
|
-
//
|
|
1843
|
-
//
|
|
1844
|
-
//
|
|
1845
|
-
// play that never began executing customer code. The sandbox exists
|
|
1846
|
-
// before that durable callback can succeed, so synchronously delete it
|
|
1847
|
-
// before returning the control-plane error. The old fire-and-forget
|
|
1848
|
-
// cleanup path was skipped by this rethrow and leaked the acquisition.
|
|
1842
|
+
// Publication can fail after it commits, or after a successor adopts
|
|
1843
|
+
// this sandbox. Preserve the scheduler error and leave deletion to its
|
|
1844
|
+
// fenced cleanup owner; this backend no longer has deletion authority.
|
|
1849
1845
|
if (runtimeResourceReportErrors.has(error)) {
|
|
1850
|
-
const sandbox = sandboxCleanup.currentSandbox();
|
|
1851
|
-
if (sandbox) {
|
|
1852
|
-
try {
|
|
1853
|
-
await preparedExecution.daytona.delete(sandbox, 30);
|
|
1854
|
-
console.info(
|
|
1855
|
-
'[play-runner.daytona.resource_report_failure_cleanup_done]',
|
|
1856
|
-
{ sandboxId: sandbox.id },
|
|
1857
|
-
);
|
|
1858
|
-
} catch (cleanupError) {
|
|
1859
|
-
throw new AggregateError(
|
|
1860
|
-
[error, cleanupError],
|
|
1861
|
-
`Failed to persist or delete acquired Daytona sandbox ${sandbox.id}.`,
|
|
1862
|
-
);
|
|
1863
|
-
}
|
|
1864
|
-
}
|
|
1865
1846
|
throw error;
|
|
1866
1847
|
}
|
|
1867
1848
|
if (isRuntimeSandboxCapacityLimitError(error)) {
|
|
@@ -13,6 +13,7 @@ export const RUNTIME_TEST_FAULT_IDS = [
|
|
|
13
13
|
'receipt_fail_write_fail',
|
|
14
14
|
'worker_receipt_complete_write_fail',
|
|
15
15
|
'invocation_response_delivery_abort',
|
|
16
|
+
'execution_upstream_response_loss',
|
|
16
17
|
'receipt_gateway_hold_ms',
|
|
17
18
|
'receipt_claim_query_hold_once_ms',
|
|
18
19
|
'receipt_claim_response_timeout',
|
|
@@ -226,6 +227,31 @@ export const RUNTIME_INCIDENT_DRILL_CATALOG: readonly RuntimeIncidentDrill[] = [
|
|
|
226
227
|
target: 'invocation-delivery-replay-e2e',
|
|
227
228
|
},
|
|
228
229
|
},
|
|
230
|
+
{
|
|
231
|
+
id: 'execution_upstream_response_loss',
|
|
232
|
+
description:
|
|
233
|
+
'Lose the first response of each keyed execution after the upstream app durably stores it.',
|
|
234
|
+
topologies: ['preview_fly'],
|
|
235
|
+
control: {
|
|
236
|
+
kind: 'runtime_test_fault',
|
|
237
|
+
defaultValue: 1,
|
|
238
|
+
valueMeaning: 'occurrence',
|
|
239
|
+
},
|
|
240
|
+
expected: {
|
|
241
|
+
outcome:
|
|
242
|
+
'The same invocation recovers the stored response without repeating provider work or customer charges, and every row retains its usable result.',
|
|
243
|
+
safetyFacts: [
|
|
244
|
+
'same_logical_run',
|
|
245
|
+
'bounded_provider_execution',
|
|
246
|
+
'all_rows_settle_once',
|
|
247
|
+
'no_false_success',
|
|
248
|
+
],
|
|
249
|
+
},
|
|
250
|
+
verification: {
|
|
251
|
+
kind: 'preview_black_box',
|
|
252
|
+
target: '101-agent-heavy-gateway-load-e2e',
|
|
253
|
+
},
|
|
254
|
+
},
|
|
229
255
|
{
|
|
230
256
|
id: 'receipt_gateway_hold_ms',
|
|
231
257
|
description: 'Hold one checked-out receipt-gateway scheduler client.',
|
package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts
CHANGED
|
@@ -175,6 +175,7 @@ import {
|
|
|
175
175
|
readPostgresSchedulerRunnerTerminal,
|
|
176
176
|
readPostgresSchedulerRunnerLiveness,
|
|
177
177
|
readPostgresSchedulerRuntimeResourcesForRun,
|
|
178
|
+
isPostgresSchedulerRunnerProgressAttemptCurrent,
|
|
178
179
|
requestComputeBillingDispatchToken,
|
|
179
180
|
blockPostgresSchedulerCronSchedule,
|
|
180
181
|
PostgresSchedulerCronScheduleConfigurationError,
|
|
@@ -2640,7 +2641,26 @@ async function executeAbsurdAttemptAdapter(
|
|
|
2640
2641
|
runtimeApi,
|
|
2641
2642
|
});
|
|
2642
2643
|
} catch (error) {
|
|
2643
|
-
if (error instanceof SuspendTask || error instanceof DeferTask)
|
|
2644
|
+
if (error instanceof SuspendTask || error instanceof DeferTask) {
|
|
2645
|
+
throw error;
|
|
2646
|
+
}
|
|
2647
|
+
if (error instanceof RuntimeResourceFenceLostError) {
|
|
2648
|
+
// A rejected resource promotion can retain the current attempt fence.
|
|
2649
|
+
// Its final failure must settle visibly; a successor's fence denies
|
|
2650
|
+
// this terminal write before any resource settlement or cleanup.
|
|
2651
|
+
await salvageAbsurdFinalAttemptTerminal({
|
|
2652
|
+
ctx,
|
|
2653
|
+
deps,
|
|
2654
|
+
options,
|
|
2655
|
+
runId,
|
|
2656
|
+
launch: executionLaunch,
|
|
2657
|
+
generation,
|
|
2658
|
+
leaseToken,
|
|
2659
|
+
error,
|
|
2660
|
+
detachedRecovery: isDetachedRecovery,
|
|
2661
|
+
});
|
|
2662
|
+
throw error;
|
|
2663
|
+
}
|
|
2644
2664
|
let detached: Awaited<
|
|
2645
2665
|
ReturnType<typeof resumePostgresSchedulerDetachedRunnerAttempt>
|
|
2646
2666
|
>;
|
|
@@ -3397,6 +3417,20 @@ async function executeAssignedAbsurdAttempt(input: {
|
|
|
3397
3417
|
)
|
|
3398
3418
|
)
|
|
3399
3419
|
return;
|
|
3420
|
+
const stillOwnsAttempt = await deps.runWithClient((client) =>
|
|
3421
|
+
isPostgresSchedulerRunnerProgressAttemptCurrent(
|
|
3422
|
+
client,
|
|
3423
|
+
{ runId, attempt: generation },
|
|
3424
|
+
options,
|
|
3425
|
+
),
|
|
3426
|
+
);
|
|
3427
|
+
if (!stillOwnsAttempt) {
|
|
3428
|
+
console.info('[absurd-runtime.worker] stale_attempt_cleanup_skipped', {
|
|
3429
|
+
runId,
|
|
3430
|
+
attempt: generation,
|
|
3431
|
+
});
|
|
3432
|
+
return;
|
|
3433
|
+
}
|
|
3400
3434
|
const cleanupTerminalReason =
|
|
3401
3435
|
error instanceof CancelledTask ? 'lease_expired' : 'runner_failed';
|
|
3402
3436
|
await deps
|
|
@@ -3407,6 +3441,7 @@ async function executeAssignedAbsurdAttempt(input: {
|
|
|
3407
3441
|
runId,
|
|
3408
3442
|
billingEndedAt: Date.now(),
|
|
3409
3443
|
terminalReason: cleanupTerminalReason,
|
|
3444
|
+
throughAttempt: generation,
|
|
3410
3445
|
},
|
|
3411
3446
|
options,
|
|
3412
3447
|
),
|
|
@@ -3422,10 +3457,8 @@ async function executeAssignedAbsurdAttempt(input: {
|
|
|
3422
3457
|
: String(settlementError),
|
|
3423
3458
|
});
|
|
3424
3459
|
});
|
|
3425
|
-
//
|
|
3426
|
-
//
|
|
3427
|
-
// attempt's sandbox is recorded under the OLD generation and would leak
|
|
3428
|
-
// if the cleanup read only this attempt's resources.
|
|
3460
|
+
// Include resources from retired attempts through this generation, while
|
|
3461
|
+
// excluding a successor if one is assigned during cleanup.
|
|
3429
3462
|
let attemptResourceReadFailed = false;
|
|
3430
3463
|
const attemptResources = await deps
|
|
3431
3464
|
.runWithClient((client) =>
|
|
@@ -3451,7 +3484,7 @@ async function executeAssignedAbsurdAttempt(input: {
|
|
|
3451
3484
|
.runWithClient((client) =>
|
|
3452
3485
|
readPostgresSchedulerRuntimeResourcesForRun(
|
|
3453
3486
|
client,
|
|
3454
|
-
{ runId, attempt: null },
|
|
3487
|
+
{ runId, attempt: null, throughAttempt: generation },
|
|
3455
3488
|
options,
|
|
3456
3489
|
),
|
|
3457
3490
|
)
|
|
@@ -3462,7 +3495,7 @@ async function executeAssignedAbsurdAttempt(input: {
|
|
|
3462
3495
|
await deps.runWithClient((client) =>
|
|
3463
3496
|
enqueuePostgresSchedulerSandboxCleanupForRun(
|
|
3464
3497
|
client,
|
|
3465
|
-
{ runId },
|
|
3498
|
+
{ runId, throughAttempt: generation },
|
|
3466
3499
|
options,
|
|
3467
3500
|
),
|
|
3468
3501
|
);
|
|
@@ -3490,6 +3523,7 @@ async function executeAssignedAbsurdAttempt(input: {
|
|
|
3490
3523
|
readSandboxCrashDiagnostic: deps.readSandboxCrashDiagnostic,
|
|
3491
3524
|
leaseOwner: `attempt-error:${runId}:${generation}`,
|
|
3492
3525
|
runId,
|
|
3526
|
+
throughAttempt: generation,
|
|
3493
3527
|
environment,
|
|
3494
3528
|
schedulerOptions: options,
|
|
3495
3529
|
timeoutMs: deps.sandboxGcTimeoutMs,
|
|
@@ -3905,7 +3939,11 @@ async function executeAssignedAbsurdAttempt(input: {
|
|
|
3905
3939
|
reservationInput,
|
|
3906
3940
|
options,
|
|
3907
3941
|
);
|
|
3908
|
-
const reserve = () =>
|
|
3942
|
+
const reserve = () =>
|
|
3943
|
+
deps.runWithClient(reserveOperation, {
|
|
3944
|
+
runId,
|
|
3945
|
+
phase: 'sandbox_capacity_admission',
|
|
3946
|
+
});
|
|
3909
3947
|
const deferForSchedulerFailure = (error: unknown): never => {
|
|
3910
3948
|
console.warn(
|
|
3911
3949
|
'[absurd-runtime.worker] sandbox_capacity_admission_deferred',
|
|
@@ -6974,6 +7012,7 @@ async function claimPostgresSchedulerSandboxCleanupBatch(input: {
|
|
|
6974
7012
|
runWithClient: AbsurdRuntimeWorkerDeps['runWithClient'];
|
|
6975
7013
|
leaseOwner: string;
|
|
6976
7014
|
runId?: string;
|
|
7015
|
+
throughAttempt?: number;
|
|
6977
7016
|
environment: 'preview' | 'production';
|
|
6978
7017
|
schedulerOptions: Pick<PostgresSchedulerOptions, 'schema'>;
|
|
6979
7018
|
limit: number;
|
|
@@ -6985,6 +7024,7 @@ async function claimPostgresSchedulerSandboxCleanupBatch(input: {
|
|
|
6985
7024
|
{
|
|
6986
7025
|
leaseOwner: input.leaseOwner,
|
|
6987
7026
|
runId: input.runId,
|
|
7027
|
+
throughAttempt: input.throughAttempt,
|
|
6988
7028
|
environment: input.environment,
|
|
6989
7029
|
limit: input.limit,
|
|
6990
7030
|
providers: input.providers,
|
|
@@ -7300,6 +7340,7 @@ export async function drainPostgresSchedulerSandboxCleanupOnce(input: {
|
|
|
7300
7340
|
deleteRuntimeSandboxWithOutcome?: AbsurdRuntimeWorkerDeps['deleteRuntimeSandboxWithOutcome'];
|
|
7301
7341
|
leaseOwner: string;
|
|
7302
7342
|
runId?: string;
|
|
7343
|
+
throughAttempt?: number;
|
|
7303
7344
|
environment: 'preview' | 'production';
|
|
7304
7345
|
schedulerOptions?: Pick<PostgresSchedulerOptions, 'schema'>;
|
|
7305
7346
|
limit?: number;
|
|
@@ -7322,6 +7363,7 @@ export async function drainPostgresSchedulerSandboxCleanupOnce(input: {
|
|
|
7322
7363
|
runWithClient: input.runWithClient,
|
|
7323
7364
|
leaseOwner: input.leaseOwner,
|
|
7324
7365
|
runId: input.runId,
|
|
7366
|
+
throughAttempt: input.throughAttempt,
|
|
7325
7367
|
environment: input.environment,
|
|
7326
7368
|
schedulerOptions: options,
|
|
7327
7369
|
limit,
|