deepline 0.1.227 → 0.1.229
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/apps/play-runner-workers/src/coordinator-entry.ts +76 -1842
- package/dist/bundling-sources/apps/play-runner-workers/src/dedup-do.ts +0 -113
- package/dist/bundling-sources/apps/play-runner-workers/src/entry.ts +144 -1000
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/ledger-event-batches.ts +81 -0
- package/dist/bundling-sources/apps/play-runner-workers/src/workflow-retry-state.ts +1 -50
- package/dist/bundling-sources/sdk/src/client.ts +24 -2
- package/dist/bundling-sources/sdk/src/play.ts +2 -2
- package/dist/bundling-sources/sdk/src/release.ts +2 -2
- package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +382 -31
- package/dist/bundling-sources/shared_libs/play-runtime/child-execution-strategy.ts +84 -79
- package/dist/bundling-sources/shared_libs/play-runtime/context.ts +201 -705
- package/dist/bundling-sources/shared_libs/play-runtime/coordinator-headers.ts +3 -10
- package/dist/bundling-sources/shared_libs/play-runtime/ctx-contract.ts +2 -2
- package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +12 -47
- package/dist/bundling-sources/shared_libs/play-runtime/governor/block-reserving-budget-state-backend.ts +0 -2
- package/dist/bundling-sources/shared_libs/play-runtime/governor/governor.ts +12 -200
- package/dist/bundling-sources/shared_libs/play-runtime/governor/policy.ts +2 -17
- package/dist/bundling-sources/shared_libs/play-runtime/live-state-contract.ts +3 -9
- package/dist/bundling-sources/shared_libs/play-runtime/play-call-execution.ts +6 -1
- package/dist/bundling-sources/shared_libs/play-runtime/play-latency-trace.ts +28 -0
- package/dist/bundling-sources/shared_libs/play-runtime/run-execution-scope.ts +16 -64
- package/dist/bundling-sources/shared_libs/play-runtime/run-ledger.ts +26 -0
- package/dist/bundling-sources/shared_libs/play-runtime/run-lifecycle-policy.ts +5 -2
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-api-paths.ts +0 -4
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +81 -18
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backend.ts +0 -36
- package/dist/bundling-sources/shared_libs/play-runtime/suspension.ts +3 -21
- package/dist/bundling-sources/shared_libs/play-runtime/test-runtime-seams.ts +9 -1
- package/dist/bundling-sources/shared_libs/play-runtime/transport-error-diagnostics.ts +63 -0
- package/dist/bundling-sources/shared_libs/plays/static-pipeline.ts +2 -0
- package/dist/cli/index.js +78 -11
- package/dist/cli/index.mjs +78 -11
- package/dist/{compiler-manifest-BhgZ23A4.d.ts → compiler-manifest-CYcwzSOJ.d.mts} +2 -0
- package/dist/{compiler-manifest-BhgZ23A4.d.mts → compiler-manifest-CYcwzSOJ.d.ts} +2 -0
- package/dist/index.d.mts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +14 -5
- package/dist/index.mjs +14 -5
- package/dist/plays/bundle-play-file.d.mts +2 -2
- package/dist/plays/bundle-play-file.d.ts +2 -2
- package/package.json +1 -1
- package/dist/bundling-sources/apps/play-runner-workers/src/child-manifest-resolver.ts +0 -108
- package/dist/bundling-sources/apps/play-runner-workers/src/child-play-await.ts +0 -374
- package/dist/bundling-sources/apps/play-runner-workers/src/child-play-submit.ts +0 -203
- package/dist/bundling-sources/shared_libs/play-runtime/child-execution-placement.ts +0 -14
- package/dist/bundling-sources/shared_libs/play-runtime/child-run-id.ts +0 -121
|
@@ -3,10 +3,7 @@ import {
|
|
|
3
3
|
type RuntimeExecutionCapability,
|
|
4
4
|
} from './execution-capabilities';
|
|
5
5
|
|
|
6
|
-
export type RunExecutionPlacementKind =
|
|
7
|
-
| 'root'
|
|
8
|
-
| 'inline_child'
|
|
9
|
-
| 'scheduled_child';
|
|
6
|
+
export type RunExecutionPlacementKind = 'root' | 'inline_child';
|
|
10
7
|
|
|
11
8
|
export type RunExecutionAuthorityInput = {
|
|
12
9
|
readonly orgId: string;
|
|
@@ -59,21 +56,12 @@ export type RootRunExecutionScopeInput = {
|
|
|
59
56
|
readonly authority: RunExecutionAuthorityInput;
|
|
60
57
|
};
|
|
61
58
|
|
|
62
|
-
export type ChildRunExecutionScopeInput =
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
| {
|
|
70
|
-
readonly placement: 'scheduled';
|
|
71
|
-
readonly runId: string;
|
|
72
|
-
readonly playId: string;
|
|
73
|
-
readonly attempt: number;
|
|
74
|
-
readonly receiptNamespace: string;
|
|
75
|
-
readonly authority?: Partial<Omit<RunExecutionAuthorityInput, 'orgId'>>;
|
|
76
|
-
};
|
|
59
|
+
export type ChildRunExecutionScopeInput = {
|
|
60
|
+
readonly placement: 'inline';
|
|
61
|
+
readonly runId: string;
|
|
62
|
+
readonly playId: string;
|
|
63
|
+
readonly receiptNamespace: string;
|
|
64
|
+
};
|
|
77
65
|
|
|
78
66
|
function requireIdentity(value: string, field: string): string {
|
|
79
67
|
if (
|
|
@@ -203,54 +191,18 @@ export function deriveChildRunExecutionScope(
|
|
|
203
191
|
rootPlayId: parent.logical.rootPlayId,
|
|
204
192
|
};
|
|
205
193
|
|
|
206
|
-
if (input.placement === 'inline') {
|
|
207
|
-
return freezeScope({
|
|
208
|
-
logical,
|
|
209
|
-
receipt: {
|
|
210
|
-
ownerRunId: parent.receipt.ownerRunId,
|
|
211
|
-
ownerAttempt: parent.receipt.ownerAttempt,
|
|
212
|
-
namespace,
|
|
213
|
-
},
|
|
214
|
-
placement: {
|
|
215
|
-
kind: 'inline_child',
|
|
216
|
-
executorRunId: parent.placement.executorRunId,
|
|
217
|
-
executorPlayId: parent.placement.executorPlayId,
|
|
218
|
-
},
|
|
219
|
-
authority: parent.authority,
|
|
220
|
-
});
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
const attempt = requireAttempt(input.attempt, 'attempt');
|
|
224
194
|
return freezeScope({
|
|
225
195
|
logical,
|
|
226
|
-
receipt: {
|
|
196
|
+
receipt: {
|
|
197
|
+
ownerRunId: parent.receipt.ownerRunId,
|
|
198
|
+
ownerAttempt: parent.receipt.ownerAttempt,
|
|
199
|
+
namespace,
|
|
200
|
+
},
|
|
227
201
|
placement: {
|
|
228
|
-
kind: '
|
|
229
|
-
executorRunId:
|
|
230
|
-
executorPlayId:
|
|
202
|
+
kind: 'inline_child',
|
|
203
|
+
executorRunId: parent.placement.executorRunId,
|
|
204
|
+
executorPlayId: parent.placement.executorPlayId,
|
|
231
205
|
},
|
|
232
|
-
authority:
|
|
233
|
-
runId,
|
|
234
|
-
playId,
|
|
235
|
-
orgId: parent.authority.orgId,
|
|
236
|
-
authority: {
|
|
237
|
-
workflowId: input.authority?.workflowId,
|
|
238
|
-
billingRunId:
|
|
239
|
-
input.authority?.billingRunId === undefined
|
|
240
|
-
? parent.authority.billingRunId
|
|
241
|
-
: input.authority.billingRunId,
|
|
242
|
-
maxCreditsPerRun:
|
|
243
|
-
input.authority?.maxCreditsPerRun === undefined
|
|
244
|
-
? parent.authority.maxCreditsPerRun
|
|
245
|
-
: input.authority.maxCreditsPerRun,
|
|
246
|
-
integrationMode:
|
|
247
|
-
input.authority?.integrationMode === undefined
|
|
248
|
-
? parent.authority.integrationMode
|
|
249
|
-
: input.authority.integrationMode,
|
|
250
|
-
synthetic: input.authority?.synthetic ?? parent.authority.synthetic,
|
|
251
|
-
capabilities:
|
|
252
|
-
input.authority?.capabilities ?? parent.authority.capabilities,
|
|
253
|
-
},
|
|
254
|
-
}),
|
|
206
|
+
authority: parent.authority,
|
|
255
207
|
});
|
|
256
208
|
}
|
|
@@ -166,6 +166,12 @@ export type PlayRunLedgerEvent =
|
|
|
166
166
|
playName?: string | null;
|
|
167
167
|
runtimeBackend?: string | null;
|
|
168
168
|
})
|
|
169
|
+
| (PlayRunLedgerBaseEvent & {
|
|
170
|
+
type: 'run.waiting';
|
|
171
|
+
})
|
|
172
|
+
| (PlayRunLedgerBaseEvent & {
|
|
173
|
+
type: 'run.resumed';
|
|
174
|
+
})
|
|
169
175
|
| (PlayRunLedgerBaseEvent & {
|
|
170
176
|
type: 'run.completed';
|
|
171
177
|
result?: unknown;
|
|
@@ -1025,6 +1031,16 @@ export function reducePlayRunLedgerEvent(
|
|
|
1025
1031
|
if (event.runId !== snapshot.runId) {
|
|
1026
1032
|
return snapshot;
|
|
1027
1033
|
}
|
|
1034
|
+
// The scheduler's outbox can replay an older wait transition after its run
|
|
1035
|
+
// reached a terminal state. That transition is no longer meaningful and
|
|
1036
|
+
// must be byte-for-byte inert: even advancing `updatedAt` would re-publish
|
|
1037
|
+
// a stale terminal snapshot to every observer.
|
|
1038
|
+
if (
|
|
1039
|
+
(event.type === 'run.waiting' || event.type === 'run.resumed') &&
|
|
1040
|
+
shouldIgnoreNonTerminalAfterStickyTerminal(snapshot)
|
|
1041
|
+
) {
|
|
1042
|
+
return snapshot;
|
|
1043
|
+
}
|
|
1028
1044
|
const occurredAt = Math.max(0, event.occurredAt);
|
|
1029
1045
|
const base: PlayRunLedgerSnapshot = {
|
|
1030
1046
|
...snapshot,
|
|
@@ -1062,6 +1078,16 @@ export function reducePlayRunLedgerEvent(
|
|
|
1062
1078
|
: 'running',
|
|
1063
1079
|
startedAt: base.startedAt ?? occurredAt,
|
|
1064
1080
|
});
|
|
1081
|
+
case 'run.waiting':
|
|
1082
|
+
return withTiming({
|
|
1083
|
+
...base,
|
|
1084
|
+
status: 'waiting',
|
|
1085
|
+
});
|
|
1086
|
+
case 'run.resumed':
|
|
1087
|
+
return withTiming({
|
|
1088
|
+
...base,
|
|
1089
|
+
status: 'running',
|
|
1090
|
+
});
|
|
1065
1091
|
case 'run.completed':
|
|
1066
1092
|
return (
|
|
1067
1093
|
conflictingTerminalSnapshot(base, event.type, occurredAt, null, {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export type PlayRunLifecycleStatus =
|
|
2
2
|
| 'queued'
|
|
3
3
|
| 'running'
|
|
4
|
+
| 'waiting'
|
|
4
5
|
| 'completed'
|
|
5
6
|
| 'failed'
|
|
6
7
|
| 'cancelled'
|
|
@@ -35,8 +36,9 @@ export function normalizePlayRunLifecycleStatus(
|
|
|
35
36
|
return 'running';
|
|
36
37
|
case 'running':
|
|
37
38
|
case 'started':
|
|
38
|
-
case 'waiting':
|
|
39
39
|
return 'running';
|
|
40
|
+
case 'waiting':
|
|
41
|
+
return 'waiting';
|
|
40
42
|
case 'completed':
|
|
41
43
|
case 'complete':
|
|
42
44
|
case 'succeeded':
|
|
@@ -62,7 +64,8 @@ export function isTerminalPlayRunLifecycleStatus(status: unknown): boolean {
|
|
|
62
64
|
}
|
|
63
65
|
|
|
64
66
|
export function isActivePlayRunLifecycleStatus(status: unknown): boolean {
|
|
65
|
-
|
|
67
|
+
const normalized = normalizePlayRunLifecycleStatus(status);
|
|
68
|
+
return normalized === 'running' || normalized === 'waiting';
|
|
66
69
|
}
|
|
67
70
|
|
|
68
71
|
export function isRecoverableDatasetRowStatus(status: unknown): boolean {
|
|
@@ -2,10 +2,6 @@ export const PLAY_RUNTIME_API_COMPAT_PATH = '/api/v2/plays/internal/runtime';
|
|
|
2
2
|
export const PLAY_RUNTIME_API_CURRENT_PATH = '/api/v2/internal/play-runtime';
|
|
3
3
|
export const PLAY_RUNTIME_ATTEMPT_EXECUTOR_TOKEN_PATH =
|
|
4
4
|
'/api/v2/internal/play-runtime/executor-token';
|
|
5
|
-
export const PLAY_RUNTIME_CHILD_EXECUTOR_TOKEN_COMPAT_PATH =
|
|
6
|
-
'/api/v2/plays/internal/child-executor-token';
|
|
7
|
-
export const PLAY_RUNTIME_CHILD_EXECUTOR_TOKEN_CURRENT_PATH =
|
|
8
|
-
'/api/v2/internal/play-runtime/child-executor-token';
|
|
9
5
|
export const PLAY_RUNTIME_TAIL_LOG_COMPAT_PATH =
|
|
10
6
|
'/api/v2/plays/internal/tail-log';
|
|
11
7
|
export const PLAY_RUNTIME_TAIL_LOG_CURRENT_PATH =
|
|
@@ -371,7 +371,22 @@ export type ResolvedRuntimePlay = {
|
|
|
371
371
|
sourceCode?: string | null;
|
|
372
372
|
artifact?: PlayBundleArtifact | null;
|
|
373
373
|
codeFormat?: 'function' | 'cjs_module' | 'esm_module';
|
|
374
|
+
/**
|
|
375
|
+
* The runtime must receive the child contract with its artifact. Inline
|
|
376
|
+
* composition rejects unresolved or dataset-backed children before running
|
|
377
|
+
* their code, so dropping this field at the API boundary makes valid scalar
|
|
378
|
+
* children indistinguishable from unknown ones.
|
|
379
|
+
*/
|
|
380
|
+
staticPipeline?: PlayStaticPipeline | null;
|
|
374
381
|
contractSnapshot?: Record<string, unknown> | null;
|
|
382
|
+
/** Preview-only contract propagation evidence, emitted by the server and
|
|
383
|
+
* logged by the runner while diagnosing a cross-runtime child resolution
|
|
384
|
+
* failure. It intentionally contains no source, inputs, or credentials. */
|
|
385
|
+
resolutionDiagnostics?: {
|
|
386
|
+
serverPlayPipeline: boolean;
|
|
387
|
+
manifestPipeline: boolean;
|
|
388
|
+
responsePipeline: boolean;
|
|
389
|
+
} | null;
|
|
375
390
|
};
|
|
376
391
|
|
|
377
392
|
export type PrepareRuntimeSheetResult = {
|
|
@@ -522,6 +537,14 @@ function resolveRuntimeApiHeaders(
|
|
|
522
537
|
'content-type': 'application/json',
|
|
523
538
|
authorization: `Bearer ${token}`,
|
|
524
539
|
[PLAY_RUNTIME_CONTRACT_HEADER]: String(PLAY_RUNTIME_CONTRACT),
|
|
540
|
+
// A run has many callback HTTP attempts. Preserve the logical run
|
|
541
|
+
// correlation in headers while Vercel keeps its own per-attempt request id.
|
|
542
|
+
...(context.runId?.trim()
|
|
543
|
+
? {
|
|
544
|
+
'x-deepline-run-id': context.runId.trim(),
|
|
545
|
+
'x-deepline-correlation-id': `run:${context.runId.trim()}`,
|
|
546
|
+
}
|
|
547
|
+
: {}),
|
|
525
548
|
...vercelHeaders,
|
|
526
549
|
...(context.runtimeTestFaultHeader?.trim()
|
|
527
550
|
? {
|
|
@@ -677,7 +700,7 @@ function runtimeApiMaxAttempts(
|
|
|
677
700
|
}
|
|
678
701
|
|
|
679
702
|
export function isTransientRuntimeApiErrorMessage(message: string): boolean {
|
|
680
|
-
return /timeout exceeded when trying to connect|timed out|fetch failed|ECONNRESET|ECONNREFUSED|UND_ERR_CONNECT_TIMEOUT|requested endpoint could not be found, or you don't have access|
|
|
703
|
+
return /timeout exceeded when trying to connect|timed out|fetch failed|ECONNRESET|ECONNREFUSED|UND_ERR_CONNECT_TIMEOUT|requested endpoint could not be found, or you don't have access|RUNTIME_SCHEDULER_(?:SATURATED|UNAVAILABLE)|Runtime scheduler DB pool is saturated|Runtime scheduler DB circuit breaker is open/i.test(
|
|
681
704
|
message,
|
|
682
705
|
);
|
|
683
706
|
}
|
|
@@ -1779,11 +1802,22 @@ function isMissingRelationError(error: unknown): boolean {
|
|
|
1779
1802
|
}
|
|
1780
1803
|
|
|
1781
1804
|
function isPostgresPermissionDeniedError(error: unknown): boolean {
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1805
|
+
if (error === null || typeof error !== 'object') {
|
|
1806
|
+
return false;
|
|
1807
|
+
}
|
|
1808
|
+
if ('code' in error && String(error.code) === '42501') {
|
|
1809
|
+
return true;
|
|
1810
|
+
}
|
|
1811
|
+
const message =
|
|
1812
|
+
'message' in error && typeof error.message === 'string'
|
|
1813
|
+
? error.message
|
|
1814
|
+
: '';
|
|
1815
|
+
// Postgres errors raised by a direct session retain SQLSTATE 42501. The
|
|
1816
|
+
// same failure crossing the runtime API boundary is intentionally rendered
|
|
1817
|
+
// as a safe Error message, so preserve the exact permission-denied shape as
|
|
1818
|
+
// the repair signal without treating arbitrary 500s as storage drift.
|
|
1819
|
+
return /permission denied for (?:database|schema|relation|table|sequence)/i.test(
|
|
1820
|
+
message,
|
|
1787
1821
|
);
|
|
1788
1822
|
}
|
|
1789
1823
|
|
|
@@ -2932,15 +2966,28 @@ export async function resolveRuntimeReferencedPlay(
|
|
|
2932
2966
|
playRef: string,
|
|
2933
2967
|
options?: { artifactKind?: PlayArtifactKind },
|
|
2934
2968
|
): Promise<ResolvedRuntimePlay | null> {
|
|
2935
|
-
const response = await postRuntimeApi<{
|
|
2936
|
-
|
|
2937
|
-
{
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
},
|
|
2942
|
-
);
|
|
2943
|
-
|
|
2969
|
+
const response = await postRuntimeApi<{
|
|
2970
|
+
play: ResolvedRuntimePlay | null;
|
|
2971
|
+
manifest?: { staticPipeline?: PlayStaticPipeline | null } | null;
|
|
2972
|
+
}>(context, {
|
|
2973
|
+
action: 'resolve_play',
|
|
2974
|
+
playRef,
|
|
2975
|
+
...(options?.artifactKind ? { artifactKind: options.artifactKind } : {}),
|
|
2976
|
+
});
|
|
2977
|
+
if (!response.play) {
|
|
2978
|
+
return null;
|
|
2979
|
+
}
|
|
2980
|
+
|
|
2981
|
+
// The server builds the manifest and child artifact together. Its manifest
|
|
2982
|
+
// carries the canonical empty scalar contract when a published scalar's
|
|
2983
|
+
// revision snapshot has no pipeline. Keep that contract on the object the
|
|
2984
|
+
// runner passes to ctx.runPlay; otherwise a valid scalar leaf arrives as an
|
|
2985
|
+
// indistinguishable "missing static contract" at runtime.
|
|
2986
|
+
return {
|
|
2987
|
+
...response.play,
|
|
2988
|
+
staticPipeline:
|
|
2989
|
+
response.play.staticPipeline ?? response.manifest?.staticPipeline ?? null,
|
|
2990
|
+
};
|
|
2944
2991
|
}
|
|
2945
2992
|
|
|
2946
2993
|
export async function ensureRuntimeSheet(
|
|
@@ -2951,12 +2998,28 @@ export async function ensureRuntimeSheet(
|
|
|
2951
2998
|
sheetContract: PlaySheetContract;
|
|
2952
2999
|
},
|
|
2953
3000
|
): Promise<void> {
|
|
2954
|
-
|
|
2955
|
-
action: 'ensure_sheet',
|
|
3001
|
+
const request = {
|
|
3002
|
+
action: 'ensure_sheet' as const,
|
|
2956
3003
|
...input,
|
|
2957
3004
|
runId: context.runId ?? null,
|
|
2958
3005
|
userEmail: normalizeRuntimeUserEmail(context.userEmail),
|
|
2959
|
-
}
|
|
3006
|
+
};
|
|
3007
|
+
try {
|
|
3008
|
+
await postRuntimeApi<{ ok: true }>(context, request);
|
|
3009
|
+
} catch (error) {
|
|
3010
|
+
if (!isPostgresPermissionDeniedError(error)) {
|
|
3011
|
+
throw error;
|
|
3012
|
+
}
|
|
3013
|
+
// Fresh tenant databases can become visible through the pooled endpoint
|
|
3014
|
+
// before their runtime-role grants are usable. Non-preloaded file runs hit
|
|
3015
|
+
// ensure_sheet before any direct Postgres operation, so the existing
|
|
3016
|
+
// operation-level self-heal cannot observe this boundary. Repair the
|
|
3017
|
+
// canonical storage contract once, then retry the exact ensure request.
|
|
3018
|
+
await repairRuntimeStorageGrants(context, {
|
|
3019
|
+
playName: input.playName,
|
|
3020
|
+
});
|
|
3021
|
+
await postRuntimeApi<{ ok: true }>(context, request);
|
|
3022
|
+
}
|
|
2960
3023
|
}
|
|
2961
3024
|
|
|
2962
3025
|
async function prepareRuntimeSheetDatasetRows(
|
|
@@ -17,7 +17,6 @@ import type {
|
|
|
17
17
|
PlayRowUpdate,
|
|
18
18
|
} from './ctx-types';
|
|
19
19
|
import type { ExecutionPlan } from './execution-plan';
|
|
20
|
-
import type { PlayRuntimeManifestMap } from '../plays/compiler-manifest';
|
|
21
20
|
import type { PreloadedRuntimeDbSession } from './db-session';
|
|
22
21
|
import type { RuntimeAuthorityDescriptor } from './execution-capabilities';
|
|
23
22
|
import type { PlayRunnerRuntimeTiming } from './protocol';
|
|
@@ -42,39 +41,6 @@ export type PlaySchedulerBackendId =
|
|
|
42
41
|
|
|
43
42
|
export type { PlayRunInputPayload };
|
|
44
43
|
|
|
45
|
-
export type PlayCallGovernanceSnapshot = {
|
|
46
|
-
rootRunId: string;
|
|
47
|
-
parentRunId: string;
|
|
48
|
-
parentPlayName: string;
|
|
49
|
-
key: string;
|
|
50
|
-
ancestryPlayIds: string[];
|
|
51
|
-
callDepth: number;
|
|
52
|
-
/**
|
|
53
|
-
* Cumulative lineage-global budget counters consumed by ancestors at the
|
|
54
|
-
* moment this child was launched. The child seeds its own counters from these
|
|
55
|
-
* so the corresponding budgets (`maxPlayCallCount`, `maxToolCallCount`,
|
|
56
|
-
* `maxRetryCount`, `maxDescendants`, `maxWaterfallStepExecutions`) accumulate
|
|
57
|
-
* down the dispatch lineage instead of resetting to 0 in each worker isolate —
|
|
58
|
-
* matching the cjs forkChild path, which threads all of them. The Governor
|
|
59
|
-
* documents these budgets as global across the nested-play tree, not
|
|
60
|
-
* per-worker (see policy.ts / rate-state-backend.ts); threading them here is
|
|
61
|
-
* what makes that true on `esm_workers`.
|
|
62
|
-
*
|
|
63
|
-
* `descendantCount` is load-bearing for fan-out: forkChild charges
|
|
64
|
-
* `descendant` on every child launch, so without threading it a deep/wide tree
|
|
65
|
-
* would reset descendant accounting at each isolate and never converge on the
|
|
66
|
-
* lineage-global cap.
|
|
67
|
-
*
|
|
68
|
-
* All optional and fail-safe: if absent (older callers / dropped in transit)
|
|
69
|
-
* the child falls back to 0, i.e. prior behavior.
|
|
70
|
-
*/
|
|
71
|
-
playCallCount?: number;
|
|
72
|
-
toolCallCount?: number;
|
|
73
|
-
retryCount?: number;
|
|
74
|
-
descendantCount?: number;
|
|
75
|
-
waterfallStepExecutions?: number;
|
|
76
|
-
};
|
|
77
|
-
|
|
78
44
|
export type PlaySchedulerSubmitInput = {
|
|
79
45
|
runId: string;
|
|
80
46
|
playId: string;
|
|
@@ -122,8 +88,6 @@ export type PlaySchedulerSubmitInput = {
|
|
|
122
88
|
}> | null;
|
|
123
89
|
contractSnapshot?: unknown;
|
|
124
90
|
executionPlan?: ExecutionPlan | null;
|
|
125
|
-
childPlayManifests?: PlayRuntimeManifestMap | null;
|
|
126
|
-
playCallGovernance?: PlayCallGovernanceSnapshot | null;
|
|
127
91
|
preloadedDbSessions?: PreloadedRuntimeDbSession[] | null;
|
|
128
92
|
/**
|
|
129
93
|
* Secret that decrypts `preloadedDbSessions` postgres URLs. Equals the run's
|
|
@@ -18,20 +18,6 @@ export type PlayExecutionSuspension =
|
|
|
18
18
|
timeoutMs: number;
|
|
19
19
|
}>;
|
|
20
20
|
}
|
|
21
|
-
| {
|
|
22
|
-
kind: 'child_play';
|
|
23
|
-
boundaryId: string;
|
|
24
|
-
childRunId: string;
|
|
25
|
-
childPlayName: string;
|
|
26
|
-
}
|
|
27
|
-
| {
|
|
28
|
-
kind: 'child_play_batch';
|
|
29
|
-
boundaries: Array<{
|
|
30
|
-
boundaryId: string;
|
|
31
|
-
childRunId: string;
|
|
32
|
-
childPlayName: string;
|
|
33
|
-
}>;
|
|
34
|
-
}
|
|
35
21
|
| {
|
|
36
22
|
/**
|
|
37
23
|
* Push-execution park (B2-final): the Daytona runner command was started
|
|
@@ -72,13 +58,9 @@ export class PlayExecutionSuspendedError extends Error {
|
|
|
72
58
|
? `Play execution suspended for durable sleep (${suspension.delayMs}ms).`
|
|
73
59
|
: suspension.kind === 'integration_event_batch'
|
|
74
60
|
? `Play execution suspended waiting for ${suspension.boundaries.length} integration events.`
|
|
75
|
-
: suspension.kind === '
|
|
76
|
-
? `Play execution
|
|
77
|
-
: suspension.
|
|
78
|
-
? `Play execution suspended waiting for child play ${JSON.stringify(suspension.childPlayName)}.`
|
|
79
|
-
: suspension.kind === 'detached_runner'
|
|
80
|
-
? `Play execution parked on detached runner ${suspension.cmdId} (sandbox ${suspension.sandboxId}).`
|
|
81
|
-
: `Play execution suspended waiting for integration event ${JSON.stringify(suspension.eventKey)}.`,
|
|
61
|
+
: suspension.kind === 'detached_runner'
|
|
62
|
+
? `Play execution parked on detached runner ${suspension.cmdId} (sandbox ${suspension.sandboxId}).`
|
|
63
|
+
: `Play execution suspended waiting for integration event ${JSON.stringify(suspension.eventKey)}.`,
|
|
82
64
|
);
|
|
83
65
|
this.name = 'PlayExecutionSuspendedError';
|
|
84
66
|
this.suspension = suspension;
|
|
@@ -5,7 +5,14 @@ export const PLAY_RUNTIME_TEST_FAULT_HEADER = 'x-deepline-test-fault';
|
|
|
5
5
|
export type RuntimeTestFaultName =
|
|
6
6
|
| 'receipt_complete_write_fail'
|
|
7
7
|
| 'receipt_fail_write_fail'
|
|
8
|
-
| 'worker_receipt_complete_write_fail'
|
|
8
|
+
| 'worker_receipt_complete_write_fail'
|
|
9
|
+
/**
|
|
10
|
+
* Holds an already checked-out receipt-gateway scheduler client for the
|
|
11
|
+
* supplied bounded millisecond value. Preview/CI only: this creates a
|
|
12
|
+
* deterministic real-Pg-pool pressure window without changing an action's
|
|
13
|
+
* SQL or outcome.
|
|
14
|
+
*/
|
|
15
|
+
| 'receipt_gateway_hold_ms';
|
|
9
16
|
|
|
10
17
|
export type RuntimeTestFaultRegistry = {
|
|
11
18
|
consume(name: RuntimeTestFaultName): boolean;
|
|
@@ -63,6 +70,7 @@ const SUPPORTED_RUNTIME_TEST_FAULTS = new Set<RuntimeTestFaultName>([
|
|
|
63
70
|
'receipt_complete_write_fail',
|
|
64
71
|
'receipt_fail_write_fail',
|
|
65
72
|
'worker_receipt_complete_write_fail',
|
|
73
|
+
'receipt_gateway_hold_ms',
|
|
66
74
|
]);
|
|
67
75
|
|
|
68
76
|
const RUNTIME_TEST_POLICY_MS_FIELDS = new Set([
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { redactLedgerString } from './ledger-safe-payload';
|
|
2
|
+
|
|
3
|
+
type ErrorLike = Record<string, unknown>;
|
|
4
|
+
|
|
5
|
+
export type TransportErrorDiagnostic = {
|
|
6
|
+
name: string | null;
|
|
7
|
+
message: string | null;
|
|
8
|
+
code: string | null;
|
|
9
|
+
errno: string | null;
|
|
10
|
+
syscall: string | null;
|
|
11
|
+
cause: TransportErrorDiagnostic | null;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
function asErrorLike(value: unknown): ErrorLike | null {
|
|
15
|
+
return value !== null && typeof value === 'object'
|
|
16
|
+
? (value as ErrorLike)
|
|
17
|
+
: null;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function safeString(value: unknown): string | null {
|
|
21
|
+
if (typeof value !== 'string' && typeof value !== 'number') return null;
|
|
22
|
+
return redactLedgerString(String(value))?.slice(0, 500) ?? null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function transportGatewayOriginForDiagnostic(url: string): string {
|
|
26
|
+
try {
|
|
27
|
+
return new URL(url).origin;
|
|
28
|
+
} catch {
|
|
29
|
+
return '<invalid-gateway-origin>';
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Make a small, secret-redacted transport diagnostic that can safely cross the
|
|
35
|
+
* runner -> gateway -> durable run-log boundary. Keep stacks in process logs:
|
|
36
|
+
* serializing them into run state leaks implementation details and is rarely
|
|
37
|
+
* useful without the original error's code/errno/cause chain.
|
|
38
|
+
*/
|
|
39
|
+
export function describeTransportError(
|
|
40
|
+
error: unknown,
|
|
41
|
+
depth = 0,
|
|
42
|
+
): TransportErrorDiagnostic {
|
|
43
|
+
const value = asErrorLike(error);
|
|
44
|
+
const errorValue = error instanceof Error ? error : null;
|
|
45
|
+
const name =
|
|
46
|
+
safeString(errorValue?.name ?? value?.name) ?? (value ? 'Error' : null);
|
|
47
|
+
const message = safeString(errorValue?.message ?? value?.message ?? error);
|
|
48
|
+
const cause = value?.cause;
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
name,
|
|
52
|
+
message,
|
|
53
|
+
code: safeString(value?.code),
|
|
54
|
+
errno: safeString(value?.errno),
|
|
55
|
+
syscall: safeString(value?.syscall),
|
|
56
|
+
// A short cause chain is enough for fetch/undici errors and prevents a
|
|
57
|
+
// pathological custom error graph from making durable traces unbounded.
|
|
58
|
+
cause:
|
|
59
|
+
cause !== undefined && depth < 2
|
|
60
|
+
? describeTransportError(cause, depth + 1)
|
|
61
|
+
: null,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
@@ -586,6 +586,8 @@ export type PlayStaticSubstep = PlayStaticSubstepMetadata &
|
|
|
586
586
|
type: 'play_call';
|
|
587
587
|
playId: string;
|
|
588
588
|
execution?: 'inline' | 'child-workflow';
|
|
589
|
+
timeoutMs?: number;
|
|
590
|
+
hasExplicitTimeout?: boolean;
|
|
589
591
|
field: string;
|
|
590
592
|
inLoop?: boolean;
|
|
591
593
|
pipeline?: PlayStaticPipeline | null;
|