deepline 0.1.209 → 0.1.211
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 +0 -2
- package/dist/bundling-sources/apps/play-runner-workers/src/entry.ts +155 -139
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/map-chunk-plan.ts +15 -0
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/map-latency-profile.ts +90 -0
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/tool-dispatch.ts +173 -103
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/tool-receipts.ts +25 -92
- package/dist/bundling-sources/sdk/src/play.ts +4 -2
- package/dist/bundling-sources/sdk/src/release.ts +2 -2
- package/dist/bundling-sources/shared_libs/play-runtime/child-run-id.ts +4 -5
- package/dist/bundling-sources/shared_libs/play-runtime/context.ts +348 -109
- package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +1 -2
- package/dist/bundling-sources/shared_libs/play-runtime/durable-call-cache.ts +2 -4
- package/dist/bundling-sources/shared_libs/play-runtime/durable-receipt-execution.ts +42 -3
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-payload-transport.ts +5 -1
- package/dist/bundling-sources/shared_libs/play-runtime/single-flight.ts +31 -0
- package/dist/bundling-sources/shared_libs/play-runtime/test-runtime-seams.ts +12 -1
- package/dist/bundling-sources/shared_libs/plays/dataset.ts +41 -5
- package/dist/cli/index.js +94 -16
- package/dist/cli/index.mjs +94 -16
- package/dist/index.d.mts +18 -3
- package/dist/index.d.ts +18 -3
- package/dist/index.js +22 -5
- package/dist/index.mjs +22 -5
- package/package.json +1 -1
|
@@ -2445,8 +2445,6 @@ function runRequestFromPlayWorkflowParams(
|
|
|
2445
2445
|
preloadedDbSessions: params.preloadedDbSessions ?? null,
|
|
2446
2446
|
runtimeTestFaultHeader: params.runtimeTestFaultHeader ?? null,
|
|
2447
2447
|
testPolicyOverrides: params.testPolicyOverrides ?? null,
|
|
2448
|
-
inlineChildRunRegistered:
|
|
2449
|
-
params.runtimeBackend === 'cf_workflows_dynamic_worker_inline_child',
|
|
2450
2448
|
coordinatorUrl: params.coordinatorUrl ?? null,
|
|
2451
2449
|
coordinatorInternalToken: params.coordinatorInternalToken ?? null,
|
|
2452
2450
|
totalRows: params.totalRows,
|
|
@@ -32,6 +32,7 @@ import {
|
|
|
32
32
|
type WorkflowEvent,
|
|
33
33
|
type WorkflowStep,
|
|
34
34
|
} from 'cloudflare:workers';
|
|
35
|
+
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
35
36
|
import {
|
|
36
37
|
deterministicMapChunkStepName,
|
|
37
38
|
type ExecutionPlan,
|
|
@@ -40,7 +41,6 @@ import {
|
|
|
40
41
|
STANDARD_PLAY_RUNTIME_LIMIT_LABEL,
|
|
41
42
|
STANDARD_PLAY_RUNTIME_LIMIT_SECONDS,
|
|
42
43
|
} from '../../../shared_libs/play-runtime/runtime-constants';
|
|
43
|
-
import { childSubmitIdempotencyKey } from '../../../shared_libs/play-runtime/child-run-id';
|
|
44
44
|
import {
|
|
45
45
|
createPlayExecutionGovernor,
|
|
46
46
|
type GovernanceSnapshot,
|
|
@@ -104,7 +104,7 @@ import {
|
|
|
104
104
|
import { createDeferredPlayDataset } from '../../../shared_libs/plays/dataset';
|
|
105
105
|
import {
|
|
106
106
|
buildDurableCtxCallCacheKey,
|
|
107
|
-
|
|
107
|
+
buildDurableRunPlayInvocationScope,
|
|
108
108
|
} from '../../../shared_libs/play-runtime/durable-call-cache';
|
|
109
109
|
import {
|
|
110
110
|
resolveRuntimeToolReceiptWaitMaxAttempts,
|
|
@@ -166,6 +166,7 @@ import {
|
|
|
166
166
|
createWorkerWorkBudgetMeter,
|
|
167
167
|
type WorkerWorkBudgetMeter,
|
|
168
168
|
} from './runtime/work-budget';
|
|
169
|
+
import { MapLatencyProfile } from './runtime/map-latency-profile';
|
|
169
170
|
import {
|
|
170
171
|
WORKER_RUN_DISPATCHER_DEFAULT_MAX_RESIDENT_ROW_BYTES,
|
|
171
172
|
WorkerRunWorkDispatcher,
|
|
@@ -368,8 +369,6 @@ type RunRequest = {
|
|
|
368
369
|
/** Internal ctx.runPlay lineage. Public SDK/users never see this. */
|
|
369
370
|
playCallGovernance?: PlayCallGovernanceSnapshot | null;
|
|
370
371
|
preloadedDbSessions?: PreloadedRuntimeDbSession[] | null;
|
|
371
|
-
/** Coordinator already created the child run row before invoking /run-inline. */
|
|
372
|
-
inlineChildRunRegistered?: boolean | null;
|
|
373
372
|
/** Cloudflare coordinator URL for direct Workflow control-plane signals. */
|
|
374
373
|
coordinatorUrl?: string | null;
|
|
375
374
|
/** Request-scoped coordinator auth token for preview/dev direct control calls. */
|
|
@@ -1148,11 +1147,29 @@ async function drainRunnerPerfTraces(req: RunRequest): Promise<void> {
|
|
|
1148
1147
|
|
|
1149
1148
|
let workerRequestSequence = 0;
|
|
1150
1149
|
|
|
1150
|
+
const workerRunPlayRowContext = new AsyncLocalStorage<{
|
|
1151
|
+
tableNamespace: string;
|
|
1152
|
+
rowKey: string;
|
|
1153
|
+
fieldName: string;
|
|
1154
|
+
}>();
|
|
1155
|
+
|
|
1151
1156
|
function makeRequestId(): string {
|
|
1152
1157
|
workerRequestSequence = (workerRequestSequence + 1) % Number.MAX_SAFE_INTEGER;
|
|
1153
1158
|
return `worker-request-${workerRequestSequence}`;
|
|
1154
1159
|
}
|
|
1155
1160
|
|
|
1161
|
+
async function executeFreshChildInvocation<T>(
|
|
1162
|
+
input: {
|
|
1163
|
+
parentRunId: string;
|
|
1164
|
+
key: string;
|
|
1165
|
+
invocationScope: string;
|
|
1166
|
+
},
|
|
1167
|
+
execute: (invocationId: string) => Promise<T>,
|
|
1168
|
+
): Promise<T> {
|
|
1169
|
+
const invocationId = `${input.parentRunId}:runPlay:${input.key}:${input.invocationScope}`;
|
|
1170
|
+
return await execute(invocationId);
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1156
1173
|
function makeRuntimeSheetAttempt(input: {
|
|
1157
1174
|
runId: string;
|
|
1158
1175
|
runAttempt?: number | null;
|
|
@@ -1665,27 +1682,6 @@ async function hashChildPlayEventKey(input: unknown): Promise<string> {
|
|
|
1665
1682
|
return (await hashJson(input)).slice(0, 32);
|
|
1666
1683
|
}
|
|
1667
1684
|
|
|
1668
|
-
function workerChildRevisionFingerprint(input: {
|
|
1669
|
-
playName: string;
|
|
1670
|
-
manifest: PlayRuntimeManifest | null | undefined;
|
|
1671
|
-
}): string | null {
|
|
1672
|
-
const manifest = input.manifest;
|
|
1673
|
-
if (!manifest) return null;
|
|
1674
|
-
return sha256Hex(
|
|
1675
|
-
stableStringify({
|
|
1676
|
-
playId: manifest.playName?.trim() || input.playName,
|
|
1677
|
-
codeFormat: 'cjs_module',
|
|
1678
|
-
artifactHash: manifest.artifactHash ?? null,
|
|
1679
|
-
graphHash: manifest.graphHash ?? null,
|
|
1680
|
-
sourceHash: null,
|
|
1681
|
-
sourceCodeHash:
|
|
1682
|
-
typeof manifest.sourceCode === 'string'
|
|
1683
|
-
? sha256Hex(manifest.sourceCode)
|
|
1684
|
-
: null,
|
|
1685
|
-
}),
|
|
1686
|
-
);
|
|
1687
|
-
}
|
|
1688
|
-
|
|
1689
1685
|
type RuntimeResolvedPlayResponse = {
|
|
1690
1686
|
manifest?: PlayRuntimeManifest | null;
|
|
1691
1687
|
};
|
|
@@ -4603,6 +4599,11 @@ function createMinimalWorkerCtx(
|
|
|
4603
4599
|
opts?: WorkerMapOptions,
|
|
4604
4600
|
): Promise<unknown> => {
|
|
4605
4601
|
const mapStartedAt = nowMs();
|
|
4602
|
+
const mapLatencyProfile = new MapLatencyProfile(
|
|
4603
|
+
req.testPolicyOverrides?.mapLatencyProfile === true,
|
|
4604
|
+
name,
|
|
4605
|
+
mapStartedAt,
|
|
4606
|
+
);
|
|
4606
4607
|
const mapNodeId = `map:${name}`;
|
|
4607
4608
|
const inputRows = rows;
|
|
4608
4609
|
const rowCountHint = datasetRowCountHint(inputRows);
|
|
@@ -4940,6 +4941,7 @@ function createMinimalWorkerCtx(
|
|
|
4940
4941
|
blockedRows: prepared.blockedRows.length,
|
|
4941
4942
|
},
|
|
4942
4943
|
});
|
|
4944
|
+
mapLatencyProfile.recordPhase('prepare_rows', nowMs() - prepareStartedAt);
|
|
4943
4945
|
const progressTotalRows = rowCountHint ?? chunkRows.length;
|
|
4944
4946
|
const preparedCompletedRows = Math.min(
|
|
4945
4947
|
progressTotalRows,
|
|
@@ -5220,7 +5222,10 @@ function createMinimalWorkerCtx(
|
|
|
5220
5222
|
deserializeDurableValue: deserializeDurableStepValue,
|
|
5221
5223
|
nowMs,
|
|
5222
5224
|
batchGraceMs: req.testPolicyOverrides?.batchGraceMs,
|
|
5223
|
-
recordPerfTrace: (trace) =>
|
|
5225
|
+
recordPerfTrace: (trace) => {
|
|
5226
|
+
mapLatencyProfile.recordToolTrace(trace);
|
|
5227
|
+
recordRunnerPerfTrace({ req, ...trace });
|
|
5228
|
+
},
|
|
5224
5229
|
abortSignal,
|
|
5225
5230
|
onRequestsSettled: reportSettledToolRequests,
|
|
5226
5231
|
callbacks,
|
|
@@ -5510,9 +5515,16 @@ function createMinimalWorkerCtx(
|
|
|
5510
5515
|
if (circuitError) throw circuitError;
|
|
5511
5516
|
const myIndex = idx++;
|
|
5512
5517
|
if (myIndex >= rowsToExecute.length) return;
|
|
5518
|
+
const rowQueueStartedAt = mapLatencyProfile.enabled ? nowMs() : 0;
|
|
5513
5519
|
const rowSlot = await governor.acquireRowSlot({
|
|
5514
5520
|
signal: abortSignal,
|
|
5515
5521
|
});
|
|
5522
|
+
if (mapLatencyProfile.enabled) {
|
|
5523
|
+
mapLatencyProfile.recordRowQueue(nowMs() - rowQueueStartedAt);
|
|
5524
|
+
}
|
|
5525
|
+
const rowExecutionStartedAt = mapLatencyProfile.enabled
|
|
5526
|
+
? nowMs()
|
|
5527
|
+
: 0;
|
|
5516
5528
|
let rowMarkedActive = false;
|
|
5517
5529
|
try {
|
|
5518
5530
|
startedExecutedRows += 1;
|
|
@@ -5580,37 +5592,49 @@ function createMinimalWorkerCtx(
|
|
|
5580
5592
|
})
|
|
5581
5593
|
: null,
|
|
5582
5594
|
});
|
|
5583
|
-
const resolved = await
|
|
5584
|
-
|
|
5585
|
-
|
|
5586
|
-
|
|
5587
|
-
|
|
5588
|
-
|
|
5589
|
-
|
|
5590
|
-
|
|
5591
|
-
|
|
5592
|
-
|
|
5593
|
-
|
|
5594
|
-
|
|
5595
|
-
|
|
5596
|
-
|
|
5597
|
-
|
|
5598
|
-
|
|
5599
|
-
|
|
5600
|
-
|
|
5601
|
-
|
|
5602
|
-
|
|
5603
|
-
|
|
5604
|
-
|
|
5605
|
-
|
|
5606
|
-
status
|
|
5607
|
-
|
|
5608
|
-
|
|
5595
|
+
const resolved = await workerRunPlayRowContext.run(
|
|
5596
|
+
{
|
|
5597
|
+
tableNamespace: name,
|
|
5598
|
+
rowKey: entry.rowKey,
|
|
5599
|
+
fieldName: key,
|
|
5600
|
+
},
|
|
5601
|
+
() =>
|
|
5602
|
+
executeWorkerStepResolver(
|
|
5603
|
+
value,
|
|
5604
|
+
enriched,
|
|
5605
|
+
rowCtx,
|
|
5606
|
+
absoluteIndex,
|
|
5607
|
+
previousCell,
|
|
5608
|
+
isWorkerStepProgram(value)
|
|
5609
|
+
? {
|
|
5610
|
+
parentField: key,
|
|
5611
|
+
path: [],
|
|
5612
|
+
outputs: stepProgramOutputs,
|
|
5613
|
+
onOutput: async (stepOutput) => {
|
|
5614
|
+
generatedOutputFields.add(
|
|
5615
|
+
stepOutput.columnName,
|
|
5616
|
+
);
|
|
5617
|
+
const status =
|
|
5618
|
+
stepOutput.status ?? 'completed';
|
|
5619
|
+
if (status === 'skipped')
|
|
5620
|
+
stepCellsSkipped += 1;
|
|
5621
|
+
else stepCellsCompleted += 1;
|
|
5622
|
+
await enqueueLiveRowUpdate({
|
|
5623
|
+
key: entry.rowKey,
|
|
5624
|
+
dataPatch: {
|
|
5625
|
+
[stepOutput.columnName]: stepOutput.value,
|
|
5626
|
+
},
|
|
5627
|
+
cellMetaPatch: {
|
|
5628
|
+
[stepOutput.columnName]: {
|
|
5629
|
+
status,
|
|
5630
|
+
stage: stepOutput.stepId,
|
|
5631
|
+
},
|
|
5632
|
+
},
|
|
5633
|
+
});
|
|
5609
5634
|
},
|
|
5610
|
-
}
|
|
5611
|
-
|
|
5612
|
-
|
|
5613
|
-
: undefined,
|
|
5635
|
+
}
|
|
5636
|
+
: undefined,
|
|
5637
|
+
),
|
|
5614
5638
|
);
|
|
5615
5639
|
enriched[key] = resolved.value;
|
|
5616
5640
|
fieldOutputs[key] = resolved.value;
|
|
@@ -5737,6 +5761,11 @@ function createMinimalWorkerCtx(
|
|
|
5737
5761
|
// single clean run failure.
|
|
5738
5762
|
}
|
|
5739
5763
|
} finally {
|
|
5764
|
+
if (mapLatencyProfile.enabled) {
|
|
5765
|
+
mapLatencyProfile.recordRowExecution(
|
|
5766
|
+
nowMs() - rowExecutionStartedAt,
|
|
5767
|
+
);
|
|
5768
|
+
}
|
|
5740
5769
|
if (rowMarkedActive) {
|
|
5741
5770
|
activeExecutedRows = Math.max(0, activeExecutedRows - 1);
|
|
5742
5771
|
reportExecutionHeartbeat(false);
|
|
@@ -5789,6 +5818,10 @@ function createMinimalWorkerCtx(
|
|
|
5789
5818
|
concurrency,
|
|
5790
5819
|
},
|
|
5791
5820
|
});
|
|
5821
|
+
mapLatencyProfile.recordPhase(
|
|
5822
|
+
'worker_execution',
|
|
5823
|
+
nowMs() - workersStartedAt,
|
|
5824
|
+
);
|
|
5792
5825
|
const buildRowFailureSamples = () =>
|
|
5793
5826
|
failedRowEntries
|
|
5794
5827
|
.map((failure, executedIndex) =>
|
|
@@ -5916,6 +5949,10 @@ function createMinimalWorkerCtx(
|
|
|
5916
5949
|
rowsToExecute: rowsToExecute.length,
|
|
5917
5950
|
},
|
|
5918
5951
|
});
|
|
5952
|
+
mapLatencyProfile.recordPhase(
|
|
5953
|
+
'persist_rows',
|
|
5954
|
+
nowMs() - persistRowsStartedAt,
|
|
5955
|
+
);
|
|
5919
5956
|
} catch (error) {
|
|
5920
5957
|
if (
|
|
5921
5958
|
workflowStep &&
|
|
@@ -6021,6 +6058,7 @@ function createMinimalWorkerCtx(
|
|
|
6021
6058
|
ms: nowMs() - hashStartedAt,
|
|
6022
6059
|
extra: { mapName: name, chunkIndex, rows: out.length },
|
|
6023
6060
|
});
|
|
6061
|
+
mapLatencyProfile.recordPhase('hash', nowMs() - hashStartedAt);
|
|
6024
6062
|
recordRunnerPerfTrace({
|
|
6025
6063
|
req,
|
|
6026
6064
|
phase: 'runner.map_chunk.total',
|
|
@@ -6636,6 +6674,27 @@ function createMinimalWorkerCtx(
|
|
|
6636
6674
|
chunks: dispatchResult.chunksExecuted,
|
|
6637
6675
|
},
|
|
6638
6676
|
});
|
|
6677
|
+
if (mapLatencyProfile.enabled) {
|
|
6678
|
+
const endedAt = nowMs();
|
|
6679
|
+
const summary = mapLatencyProfile.summary(endedAt, {
|
|
6680
|
+
chunks: dispatchResult.chunksExecuted,
|
|
6681
|
+
rows: totalRowsWritten,
|
|
6682
|
+
});
|
|
6683
|
+
recordRunnerPerfTrace({
|
|
6684
|
+
req,
|
|
6685
|
+
phase: 'runner.map.profile',
|
|
6686
|
+
ms: endedAt - mapStartedAt,
|
|
6687
|
+
extra: summary,
|
|
6688
|
+
});
|
|
6689
|
+
// Local Absurd does not always forward dynamic-worker perf traces. Keep
|
|
6690
|
+
// one bounded copy in the durable run log for the diagnostic command.
|
|
6691
|
+
emitEvent({
|
|
6692
|
+
type: 'log',
|
|
6693
|
+
level: 'info',
|
|
6694
|
+
message: `[perf] map_latency_profile ${JSON.stringify(summary)}`,
|
|
6695
|
+
ts: endedAt,
|
|
6696
|
+
});
|
|
6697
|
+
}
|
|
6639
6698
|
return dataset;
|
|
6640
6699
|
};
|
|
6641
6700
|
|
|
@@ -6933,7 +6992,6 @@ function createMinimalWorkerCtx(
|
|
|
6933
6992
|
options?: {
|
|
6934
6993
|
description?: string;
|
|
6935
6994
|
timeoutMs?: number;
|
|
6936
|
-
staleAfterSeconds?: number;
|
|
6937
6995
|
},
|
|
6938
6996
|
): Promise<unknown> {
|
|
6939
6997
|
const normalizedKey = normalizeContextKey(key, 'runPlay');
|
|
@@ -6947,34 +7005,49 @@ function createMinimalWorkerCtx(
|
|
|
6947
7005
|
playRef: resolvedName,
|
|
6948
7006
|
cache: childManifestCache,
|
|
6949
7007
|
});
|
|
6950
|
-
const
|
|
6951
|
-
|
|
6952
|
-
|
|
6953
|
-
|
|
6954
|
-
|
|
6955
|
-
|
|
6956
|
-
|
|
6957
|
-
|
|
6958
|
-
|
|
6959
|
-
|
|
6960
|
-
|
|
6961
|
-
input,
|
|
6962
|
-
}),
|
|
6963
|
-
staleAfterSeconds: options?.staleAfterSeconds,
|
|
7008
|
+
const rowScope = workerRunPlayRowContext.getStore();
|
|
7009
|
+
const invocationScope = buildDurableRunPlayInvocationScope({
|
|
7010
|
+
childPlayName: resolvedName,
|
|
7011
|
+
input,
|
|
7012
|
+
rowScope: rowScope
|
|
7013
|
+
? {
|
|
7014
|
+
fieldName: rowScope.fieldName,
|
|
7015
|
+
rowKey: rowScope.rowKey,
|
|
7016
|
+
tableNamespace: rowScope.tableNamespace,
|
|
7017
|
+
}
|
|
7018
|
+
: null,
|
|
6964
7019
|
});
|
|
6965
|
-
return await
|
|
6966
|
-
|
|
6967
|
-
|
|
7020
|
+
return await executeFreshChildInvocation(
|
|
7021
|
+
{
|
|
7022
|
+
parentRunId: req.runId,
|
|
7023
|
+
key: normalizedKey,
|
|
7024
|
+
invocationScope,
|
|
7025
|
+
},
|
|
7026
|
+
async (childInvocationId) => {
|
|
6968
7027
|
// The Governor owns the play-call lineage: forkChild does the cycle
|
|
6969
7028
|
// guard, depth/per-parent/playCall/descendant budget charges, and
|
|
6970
7029
|
// returns the snapshot to thread into the child so budgets accumulate
|
|
6971
|
-
// across isolates.
|
|
6972
|
-
|
|
6973
|
-
|
|
6974
|
-
|
|
6975
|
-
|
|
6976
|
-
|
|
6977
|
-
|
|
7030
|
+
// across isolates. Every ctx.runPlay call is a fresh child invocation.
|
|
7031
|
+
const childRunId = `${req.runId}:child:${childInvocationId}`;
|
|
7032
|
+
// Checkpoint governance admission separately from the child result.
|
|
7033
|
+
// Workflow replay reuses this admission and the coordinator's stable
|
|
7034
|
+
// child launch identity, but ctx.runPlay never caches child output.
|
|
7035
|
+
const forkChild = () =>
|
|
7036
|
+
governor.forkChild({
|
|
7037
|
+
childPlayName: resolvedName,
|
|
7038
|
+
childRunId,
|
|
7039
|
+
});
|
|
7040
|
+
const childGovernance = workflowStep
|
|
7041
|
+
? await (
|
|
7042
|
+
workflowStep.do as unknown as <T>(
|
|
7043
|
+
name: string,
|
|
7044
|
+
callback: () => Promise<T>,
|
|
7045
|
+
) => Promise<T>
|
|
7046
|
+
)(
|
|
7047
|
+
`runPlay-governance:${sha256Hex(childInvocationId).slice(0, 24)}`,
|
|
7048
|
+
forkChild,
|
|
7049
|
+
)
|
|
7050
|
+
: await forkChild();
|
|
6978
7051
|
const nextDepth = childGovernance.callDepth;
|
|
6979
7052
|
const nextParentCalls =
|
|
6980
7053
|
governor.snapshot().parentChildCalls[req.playName] ?? 0;
|
|
@@ -7047,11 +7120,7 @@ function createMinimalWorkerCtx(
|
|
|
7047
7120
|
options?.timeoutMs == null && !childNeedsWorkflowScheduler,
|
|
7048
7121
|
body: {
|
|
7049
7122
|
name: resolvedName,
|
|
7050
|
-
childIdempotencyKey:
|
|
7051
|
-
receiptKey,
|
|
7052
|
-
wasFailed,
|
|
7053
|
-
leaseId: receiptContext.leaseId,
|
|
7054
|
-
}),
|
|
7123
|
+
childIdempotencyKey: childInvocationId,
|
|
7055
7124
|
input: isRecord(input) ? input : {},
|
|
7056
7125
|
orgId: req.orgId,
|
|
7057
7126
|
callbackUrl: req.callbackUrl,
|
|
@@ -7329,12 +7398,6 @@ function createMinimalWorkerCtx(
|
|
|
7329
7398
|
childPlaySlot?.release();
|
|
7330
7399
|
}
|
|
7331
7400
|
},
|
|
7332
|
-
{
|
|
7333
|
-
forceFailedRefresh: true,
|
|
7334
|
-
repairRunningReceiptForSameRunAfterWaitTimeout: true,
|
|
7335
|
-
runningReceiptWaitMaxAttempts:
|
|
7336
|
-
resolveRuntimeToolReceiptWaitMaxAttempts(input),
|
|
7337
|
-
},
|
|
7338
7401
|
);
|
|
7339
7402
|
},
|
|
7340
7403
|
async fetch(
|
|
@@ -7615,13 +7678,6 @@ async function handleRunInline(
|
|
|
7615
7678
|
const probeStartedAt = nowMs();
|
|
7616
7679
|
await probeHarnessOnce(env, runPrefix);
|
|
7617
7680
|
traceInline('inline.probe_harness', probeStartedAt);
|
|
7618
|
-
if (!req.inlineChildRunRegistered) {
|
|
7619
|
-
const registerStartedAt = nowMs();
|
|
7620
|
-
await registerInlineChildRun(req);
|
|
7621
|
-
traceInline('inline.register_child_run', registerStartedAt);
|
|
7622
|
-
} else {
|
|
7623
|
-
traceInline('inline.register_child_run', nowMs(), { skipped: true });
|
|
7624
|
-
}
|
|
7625
7681
|
const executeStartedAt = nowMs();
|
|
7626
7682
|
const output = await executeRunRequest(
|
|
7627
7683
|
req,
|
|
@@ -7667,46 +7723,6 @@ async function handleRunInline(
|
|
|
7667
7723
|
}
|
|
7668
7724
|
}
|
|
7669
7725
|
|
|
7670
|
-
async function registerInlineChildRun(req: RunRequest): Promise<void> {
|
|
7671
|
-
const snapshot = isRecord(req.contractSnapshot) ? req.contractSnapshot : {};
|
|
7672
|
-
const artifactMetadata = isRecord(snapshot.artifactMetadata)
|
|
7673
|
-
? snapshot.artifactMetadata
|
|
7674
|
-
: {};
|
|
7675
|
-
const governance = req.playCallGovernance;
|
|
7676
|
-
await postRuntimeApi(req.baseUrl, req.executorToken, {
|
|
7677
|
-
action: 'start_inline_child_run',
|
|
7678
|
-
playName: req.playName,
|
|
7679
|
-
runId: req.runId,
|
|
7680
|
-
parentRunId: governance?.parentRunId,
|
|
7681
|
-
rootRunId: governance?.rootRunId,
|
|
7682
|
-
workflowFamilyKey:
|
|
7683
|
-
governance?.rootRunId ?? governance?.parentRunId ?? req.runId,
|
|
7684
|
-
artifactStorageKey:
|
|
7685
|
-
typeof artifactMetadata.storageKey === 'string'
|
|
7686
|
-
? artifactMetadata.storageKey
|
|
7687
|
-
: undefined,
|
|
7688
|
-
artifactHash:
|
|
7689
|
-
typeof artifactMetadata.artifactHash === 'string'
|
|
7690
|
-
? artifactMetadata.artifactHash
|
|
7691
|
-
: undefined,
|
|
7692
|
-
graphHash:
|
|
7693
|
-
typeof artifactMetadata.graphHash === 'string'
|
|
7694
|
-
? artifactMetadata.graphHash
|
|
7695
|
-
: undefined,
|
|
7696
|
-
runtimeBackend: 'workers_edge',
|
|
7697
|
-
schedulerBackend: 'inline_child',
|
|
7698
|
-
executionProfile: 'workers_edge',
|
|
7699
|
-
maxCreditsPerRun: extractMaxCreditsPerRun(req.contractSnapshot),
|
|
7700
|
-
staticPipeline: snapshot.staticPipeline ?? null,
|
|
7701
|
-
source:
|
|
7702
|
-
snapshot.source === 'published' ||
|
|
7703
|
-
snapshot.source === 'ad_hoc' ||
|
|
7704
|
-
snapshot.source === 'draft'
|
|
7705
|
-
? snapshot.source
|
|
7706
|
-
: 'published',
|
|
7707
|
-
});
|
|
7708
|
-
}
|
|
7709
|
-
|
|
7710
7726
|
/** Cap on run log lines retained in the terminal output compatibility shape. */
|
|
7711
7727
|
const RUN_LOG_BUFFER_LIMIT = 500;
|
|
7712
7728
|
/** Min wall-clock interval between live run-ledger flushes during a run. */
|
|
@@ -337,6 +337,21 @@ function countToolSubstep(substep: PlayStaticSubstep): MapToolStats {
|
|
|
337
337
|
minProviderBranchCoalescedCount(branchStats),
|
|
338
338
|
];
|
|
339
339
|
}
|
|
340
|
+
if (substep.kind === 'loop') {
|
|
341
|
+
// The static extractor records every switch arm in `steps` when a loop
|
|
342
|
+
// walks a fixed provider list. Each arm can execute on a different
|
|
343
|
+
// iteration, so using the conditional's max-one-branch estimate would
|
|
344
|
+
// budget a seven-provider waterfall as one provider call per row.
|
|
345
|
+
return substep.steps.reduce<MapToolStats>((stats, step) => {
|
|
346
|
+
const stepStats =
|
|
347
|
+
step.type === 'control_flow' &&
|
|
348
|
+
step.kind === 'conditional' &&
|
|
349
|
+
step.steps.length > 0
|
|
350
|
+
? countToolSubsteps(step.steps)
|
|
351
|
+
: countToolSubstep(step);
|
|
352
|
+
return addStats(stats, stepStats);
|
|
353
|
+
}, [0, 0, 0, 0, 0]);
|
|
354
|
+
}
|
|
340
355
|
return countToolSubsteps(substep.steps);
|
|
341
356
|
}
|
|
342
357
|
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
type ToolTrace = {
|
|
2
|
+
phase: string;
|
|
3
|
+
ms?: number;
|
|
4
|
+
extra?: Record<string, unknown>;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
type Totals = Record<string, number>;
|
|
8
|
+
|
|
9
|
+
function add(totals: Totals, key: string, ms: number | undefined): void {
|
|
10
|
+
if (typeof ms !== 'number' || !Number.isFinite(ms) || ms < 0) return;
|
|
11
|
+
totals[key] = (totals[key] ?? 0) + ms;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Opt-in map profiler. It aggregates in memory and produces one terminal
|
|
16
|
+
* trace, so normal runs do not pay per-row/per-tool telemetry cost.
|
|
17
|
+
*/
|
|
18
|
+
export class MapLatencyProfile {
|
|
19
|
+
private readonly phaseWorkMs: Totals = {};
|
|
20
|
+
private readonly toolWorkMs: Totals = {};
|
|
21
|
+
private readonly counts: Totals = {};
|
|
22
|
+
|
|
23
|
+
constructor(
|
|
24
|
+
readonly enabled: boolean,
|
|
25
|
+
private readonly mapName: string,
|
|
26
|
+
private readonly startedAtMs: number,
|
|
27
|
+
) {}
|
|
28
|
+
|
|
29
|
+
recordPhase(phase: string, ms: number, count = 1): void {
|
|
30
|
+
if (!this.enabled) return;
|
|
31
|
+
add(this.phaseWorkMs, phase, ms);
|
|
32
|
+
this.counts[`${phase}_count`] =
|
|
33
|
+
(this.counts[`${phase}_count`] ?? 0) + count;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
recordRowQueue(ms: number): void {
|
|
37
|
+
this.recordPhase('row_slot_queue', ms);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
recordRowExecution(ms: number): void {
|
|
41
|
+
this.recordPhase('row_execution', ms);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
recordToolTrace(trace: ToolTrace): void {
|
|
45
|
+
if (!this.enabled) return;
|
|
46
|
+
switch (trace.phase) {
|
|
47
|
+
case 'runner.tool.request':
|
|
48
|
+
add(this.toolWorkMs, 'request_end_to_end', trace.ms);
|
|
49
|
+
this.counts.tool_requests = (this.counts.tool_requests ?? 0) + 1;
|
|
50
|
+
break;
|
|
51
|
+
case 'runner.tool.drain':
|
|
52
|
+
add(this.toolWorkMs, 'drain', trace.ms);
|
|
53
|
+
this.counts.tool_drains = (this.counts.tool_drains ?? 0) + 1;
|
|
54
|
+
break;
|
|
55
|
+
case 'runner.tool.group':
|
|
56
|
+
add(this.toolWorkMs, 'group', trace.ms);
|
|
57
|
+
this.counts.tool_groups = (this.counts.tool_groups ?? 0) + 1;
|
|
58
|
+
break;
|
|
59
|
+
case 'runner.tool.receipt_prepare':
|
|
60
|
+
add(this.toolWorkMs, 'receipt_prepare', trace.ms);
|
|
61
|
+
break;
|
|
62
|
+
case 'runner.tool.admission':
|
|
63
|
+
add(this.toolWorkMs, 'admission_wait', trace.ms);
|
|
64
|
+
break;
|
|
65
|
+
case 'runner.tool.provider':
|
|
66
|
+
add(this.toolWorkMs, 'provider_execute', trace.ms);
|
|
67
|
+
break;
|
|
68
|
+
case 'runner.tool.receipt_complete':
|
|
69
|
+
add(this.toolWorkMs, 'receipt_complete', trace.ms);
|
|
70
|
+
break;
|
|
71
|
+
default:
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
summary(endedAtMs: number, input: { chunks: number; rows: number }) {
|
|
77
|
+
return {
|
|
78
|
+
mapName: this.mapName,
|
|
79
|
+
mapWallMs: Math.max(0, endedAtMs - this.startedAtMs),
|
|
80
|
+
chunks: input.chunks,
|
|
81
|
+
rows: input.rows,
|
|
82
|
+
// These are summed work durations. They can exceed mapWallMs when rows
|
|
83
|
+
// or provider calls overlap; the terminal trace must not mislabel them
|
|
84
|
+
// as a wall-clock decomposition.
|
|
85
|
+
phaseWorkMs: this.phaseWorkMs,
|
|
86
|
+
toolWorkMs: this.toolWorkMs,
|
|
87
|
+
counts: this.counts,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|