deepline 0.1.167 → 0.1.169
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 +317 -26
- package/dist/bundling-sources/apps/play-runner-workers/src/dedup-do.ts +99 -6
- package/dist/bundling-sources/apps/play-runner-workers/src/entry.ts +219 -73
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/map-chunk-plan.ts +119 -33
- package/dist/bundling-sources/apps/play-runner-workers/src/runtime/tool-receipts.ts +2 -0
- package/dist/bundling-sources/apps/play-runner-workers/src/workflow-instance-create.ts +3 -0
- package/dist/bundling-sources/sdk/src/client.ts +29 -1
- package/dist/bundling-sources/sdk/src/release.ts +2 -2
- package/dist/bundling-sources/sdk/src/types.ts +3 -0
- package/dist/bundling-sources/shared_libs/play-data-plane/column-names.ts +50 -8
- package/dist/bundling-sources/shared_libs/play-data-plane/sheet-contract.ts +40 -1
- package/dist/bundling-sources/shared_libs/play-runtime/app-runtime-api.ts +1 -0
- package/dist/bundling-sources/shared_libs/play-runtime/context.ts +3 -0
- package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +2 -0
- package/dist/bundling-sources/shared_libs/play-runtime/protocol.ts +1 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +2 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backend.ts +2 -0
- package/dist/bundling-sources/shared_libs/play-runtime/work-receipts.ts +1 -0
- package/dist/bundling-sources/shared_libs/plays/static-pipeline.ts +202 -45
- package/dist/cli/index.js +70 -113
- package/dist/cli/index.mjs +70 -113
- package/dist/{compiler-manifest-VhtM9n24.d.mts → compiler-manifest-OwORQ07f.d.mts} +1 -0
- package/dist/{compiler-manifest-VhtM9n24.d.ts → compiler-manifest-OwORQ07f.d.ts} +1 -0
- package/dist/index.d.mts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +26 -5
- package/dist/index.mjs +26 -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
|
@@ -263,6 +263,7 @@ type RunRequest = {
|
|
|
263
263
|
callbackUrl: string;
|
|
264
264
|
executorToken: string;
|
|
265
265
|
baseUrl: string;
|
|
266
|
+
integrationMode?: 'live' | 'eval_stub' | 'fixture' | null;
|
|
266
267
|
orgId: string;
|
|
267
268
|
playName: string;
|
|
268
269
|
graphHash?: string | null;
|
|
@@ -325,6 +326,14 @@ function getStringField(value: unknown, key: string): string | null {
|
|
|
325
326
|
return typeof field === 'string' && field.trim() ? field : null;
|
|
326
327
|
}
|
|
327
328
|
|
|
329
|
+
function normalizeIntegrationMode(
|
|
330
|
+
value: unknown,
|
|
331
|
+
): 'live' | 'eval_stub' | 'fixture' | null {
|
|
332
|
+
return value === 'live' || value === 'eval_stub' || value === 'fixture'
|
|
333
|
+
? value
|
|
334
|
+
: null;
|
|
335
|
+
}
|
|
336
|
+
|
|
328
337
|
function getObjectField(
|
|
329
338
|
value: unknown,
|
|
330
339
|
key: string,
|
|
@@ -1472,6 +1481,9 @@ async function callToolDirect(
|
|
|
1472
1481
|
body: JSON.stringify({
|
|
1473
1482
|
payload: input,
|
|
1474
1483
|
metadata: { parent_run_id: req.runId },
|
|
1484
|
+
...(req.integrationMode
|
|
1485
|
+
? { integration_mode: req.integrationMode }
|
|
1486
|
+
: {}),
|
|
1475
1487
|
}),
|
|
1476
1488
|
},
|
|
1477
1489
|
{
|
|
@@ -1650,13 +1662,44 @@ const WORKER_TOOL_BATCH_GRACE_MS = 250;
|
|
|
1650
1662
|
const MAP_EXECUTION_HEARTBEAT_INTERVAL_MS = 5_000;
|
|
1651
1663
|
const MAP_INCREMENTAL_PERSIST_CHUNK_ROWS = 100;
|
|
1652
1664
|
const MAP_INCREMENTAL_PERSIST_CHUNK_BYTES = 1 * 1024 * 1024;
|
|
1653
|
-
const MAP_INCREMENTAL_PERSIST_INTERVAL_MS =
|
|
1665
|
+
const MAP_INCREMENTAL_PERSIST_INTERVAL_MS = 1_000;
|
|
1666
|
+
const MAP_LIVE_UPDATE_FLUSH_CHUNK_ROWS = 1_000;
|
|
1654
1667
|
/**
|
|
1655
1668
|
* Bounded number of per-row failure samples carried in chunk summaries and the
|
|
1656
1669
|
* map's terminal partial-failure log. Every failed row is persisted with its
|
|
1657
1670
|
* full error in the runtime sheet; the samples just keep run logs readable.
|
|
1658
1671
|
*/
|
|
1659
1672
|
const MAP_ROW_FAILURE_SAMPLE_LIMIT = 3;
|
|
1673
|
+
|
|
1674
|
+
class RuntimeReceiptPersistenceError extends Error {
|
|
1675
|
+
readonly errors: unknown[];
|
|
1676
|
+
|
|
1677
|
+
constructor(message: string, errors: unknown[] = []) {
|
|
1678
|
+
super(message);
|
|
1679
|
+
this.name = 'RuntimeReceiptPersistenceError';
|
|
1680
|
+
this.errors = errors;
|
|
1681
|
+
}
|
|
1682
|
+
}
|
|
1683
|
+
|
|
1684
|
+
function isRuntimeReceiptPersistenceError(error: unknown): boolean {
|
|
1685
|
+
if (!error || typeof error !== 'object') return false;
|
|
1686
|
+
if (error instanceof RuntimeReceiptPersistenceError) return true;
|
|
1687
|
+
if (error instanceof Error && error.name === 'RuntimeReceiptPersistenceError') {
|
|
1688
|
+
return true;
|
|
1689
|
+
}
|
|
1690
|
+
const nestedErrors = (error as { errors?: unknown }).errors;
|
|
1691
|
+
return (
|
|
1692
|
+
Array.isArray(nestedErrors) &&
|
|
1693
|
+
nestedErrors.some(isRuntimeReceiptPersistenceError)
|
|
1694
|
+
);
|
|
1695
|
+
}
|
|
1696
|
+
|
|
1697
|
+
function isRunFatalWorkerRowError(error: unknown): boolean {
|
|
1698
|
+
return (
|
|
1699
|
+
isRowIsolationExemptError(error) || isRuntimeReceiptPersistenceError(error)
|
|
1700
|
+
);
|
|
1701
|
+
}
|
|
1702
|
+
|
|
1660
1703
|
// Fallback batch-chunk parallelism when a tool declares no provider rate hints.
|
|
1661
1704
|
// Matches the prior hardcoded `Math.min(4, ...)` so undeclared providers keep
|
|
1662
1705
|
// their previous batching behavior; declared providers tighten via the
|
|
@@ -1982,6 +2025,7 @@ class WorkerToolBatchScheduler {
|
|
|
1982
2025
|
!canReclaimTimedOutWorkerToolReceipt({
|
|
1983
2026
|
ownerRunId: input.runningReceipt.runId,
|
|
1984
2027
|
currentRunId: this.req.runId,
|
|
2028
|
+
updatedAt: input.runningReceipt.updatedAt,
|
|
1985
2029
|
})
|
|
1986
2030
|
) {
|
|
1987
2031
|
this.rejectRawRequests(input.group, waitError);
|
|
@@ -2100,9 +2144,9 @@ class WorkerToolBatchScheduler {
|
|
|
2100
2144
|
await this.failDurableToolRequest(claimed, error);
|
|
2101
2145
|
return error;
|
|
2102
2146
|
} catch (receiptError) {
|
|
2103
|
-
return new
|
|
2104
|
-
[error, receiptError],
|
|
2147
|
+
return new RuntimeReceiptPersistenceError(
|
|
2105
2148
|
'Tool call failed and durable receipt could not be marked failed',
|
|
2149
|
+
[error, receiptError],
|
|
2106
2150
|
);
|
|
2107
2151
|
}
|
|
2108
2152
|
}
|
|
@@ -2459,25 +2503,38 @@ class WorkerToolBatchScheduler {
|
|
|
2459
2503
|
signal: this.abortSignal,
|
|
2460
2504
|
});
|
|
2461
2505
|
try {
|
|
2462
|
-
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2506
|
+
let result: unknown;
|
|
2507
|
+
try {
|
|
2508
|
+
result = await executeToolWithLifecycle(
|
|
2509
|
+
this.req,
|
|
2510
|
+
{ id: request.id, toolId, input: request.input },
|
|
2511
|
+
request.workflowStep,
|
|
2512
|
+
this.callbacks,
|
|
2513
|
+
(retryAfterMs) =>
|
|
2514
|
+
this.reportBackpressure(toolId, retryAfterMs),
|
|
2515
|
+
() => this.governor.chargeBudget('retry'),
|
|
2516
|
+
toolContract?.retrySafeTransientHttp === true,
|
|
2517
|
+
this.abortSignal,
|
|
2518
|
+
this.runtimeDeadlineMs,
|
|
2519
|
+
);
|
|
2520
|
+
} catch (error) {
|
|
2521
|
+
this.rejectRequests(
|
|
2522
|
+
claimed,
|
|
2523
|
+
await this.failureForRejectedToolRequest(claimed, error),
|
|
2524
|
+
);
|
|
2525
|
+
return;
|
|
2526
|
+
}
|
|
2473
2527
|
this.settleRequests(
|
|
2474
2528
|
claimed,
|
|
2475
2529
|
await this.completeDurableToolRequest(claimed, result),
|
|
2476
2530
|
);
|
|
2477
|
-
} catch (
|
|
2531
|
+
} catch (receiptError) {
|
|
2478
2532
|
this.rejectRequests(
|
|
2479
2533
|
claimed,
|
|
2480
|
-
|
|
2534
|
+
new RuntimeReceiptPersistenceError(
|
|
2535
|
+
'Tool call succeeded but durable receipt could not be marked completed',
|
|
2536
|
+
[receiptError],
|
|
2537
|
+
),
|
|
2481
2538
|
);
|
|
2482
2539
|
} finally {
|
|
2483
2540
|
slot.release();
|
|
@@ -2651,9 +2708,9 @@ async function executeBatchedWorkerToolGroup(input: {
|
|
|
2651
2708
|
try {
|
|
2652
2709
|
await input.failRequests(entry.request.memberRequests, entry.error);
|
|
2653
2710
|
} catch (receiptError) {
|
|
2654
|
-
rejection = new
|
|
2655
|
-
[entry.error, receiptError],
|
|
2711
|
+
rejection = new RuntimeReceiptPersistenceError(
|
|
2656
2712
|
'Tool call failed and durable receipts could not be marked failed',
|
|
2713
|
+
[entry.error, receiptError],
|
|
2657
2714
|
);
|
|
2658
2715
|
}
|
|
2659
2716
|
for (const claimed of entry.request.memberRequests) {
|
|
@@ -2668,16 +2725,28 @@ async function executeBatchedWorkerToolGroup(input: {
|
|
|
2668
2725
|
batchResult != null
|
|
2669
2726
|
? entry.request.splitResults(batchResult)
|
|
2670
2727
|
: entry.request.memberRequests.map(() => null);
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
claimed
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2728
|
+
let completedResults: unknown[];
|
|
2729
|
+
try {
|
|
2730
|
+
completedResults = await input.completeRequests(
|
|
2731
|
+
entry.request.memberRequests.map((claimed, index) => ({
|
|
2732
|
+
claimed,
|
|
2733
|
+
result: wrapWorkerToolResult(
|
|
2734
|
+
claimed.request.toolId,
|
|
2735
|
+
splitResults[index] ?? null,
|
|
2736
|
+
toolMetadataFallback(claimed.request.toolId),
|
|
2737
|
+
),
|
|
2738
|
+
})),
|
|
2739
|
+
);
|
|
2740
|
+
} catch (receiptError) {
|
|
2741
|
+
const rejection = new RuntimeReceiptPersistenceError(
|
|
2742
|
+
'Tool call succeeded but durable receipts could not be marked completed',
|
|
2743
|
+
[receiptError],
|
|
2744
|
+
);
|
|
2745
|
+
for (const claimed of entry.request.memberRequests) {
|
|
2746
|
+
input.rejectRequest(claimed, rejection);
|
|
2747
|
+
}
|
|
2748
|
+
continue;
|
|
2749
|
+
}
|
|
2681
2750
|
for (let index = 0; index < completedResults.length; index += 1) {
|
|
2682
2751
|
const claimed = entry.request.memberRequests[index]!;
|
|
2683
2752
|
const request = claimed.request;
|
|
@@ -2690,9 +2759,9 @@ async function executeBatchedWorkerToolGroup(input: {
|
|
|
2690
2759
|
try {
|
|
2691
2760
|
await input.failRequests(input.requests, error);
|
|
2692
2761
|
} catch (receiptError) {
|
|
2693
|
-
rejection = new
|
|
2694
|
-
[error, receiptError],
|
|
2762
|
+
rejection = new RuntimeReceiptPersistenceError(
|
|
2695
2763
|
'Tool call failed and durable receipts could not be marked failed',
|
|
2764
|
+
[error, receiptError],
|
|
2696
2765
|
);
|
|
2697
2766
|
}
|
|
2698
2767
|
for (const claimed of input.requests) {
|
|
@@ -2728,6 +2797,7 @@ type WorkerMapChunkSummary<T extends Record<string, unknown>> = {
|
|
|
2728
2797
|
stepCellsSkipped: number;
|
|
2729
2798
|
outputDatasetId: string;
|
|
2730
2799
|
hash: string;
|
|
2800
|
+
fatalError?: string;
|
|
2731
2801
|
preview: T[];
|
|
2732
2802
|
cachedRows?: T[];
|
|
2733
2803
|
};
|
|
@@ -3816,6 +3886,15 @@ async function persistCompletedMapRows(input: {
|
|
|
3816
3886
|
rows,
|
|
3817
3887
|
outputFields,
|
|
3818
3888
|
});
|
|
3889
|
+
console.warn('[play-runner.persist_completed_map_rows.start]', {
|
|
3890
|
+
runId: req.runId,
|
|
3891
|
+
playName: req.playName,
|
|
3892
|
+
tableNamespace,
|
|
3893
|
+
rows: rows.length,
|
|
3894
|
+
outputFields,
|
|
3895
|
+
extraOutputFields: input.extraOutputFields ?? [],
|
|
3896
|
+
contractColumnCount: sheetContract.columns.length,
|
|
3897
|
+
});
|
|
3819
3898
|
const persistRequest = {
|
|
3820
3899
|
...sessionScope,
|
|
3821
3900
|
tableNamespace,
|
|
@@ -3830,6 +3909,8 @@ async function persistCompletedMapRows(input: {
|
|
|
3830
3909
|
.filter((key): key is string => Boolean(key)),
|
|
3831
3910
|
),
|
|
3832
3911
|
];
|
|
3912
|
+
const expectedVisibleRows =
|
|
3913
|
+
expectedKeys.length > 0 ? expectedKeys.length : rows.length;
|
|
3833
3914
|
const readVisibleRowCount = async () => {
|
|
3834
3915
|
if (expectedKeys.length > 0) {
|
|
3835
3916
|
const result = await harnessReadSheetDatasetRowKeys({
|
|
@@ -3852,12 +3933,24 @@ async function persistCompletedMapRows(input: {
|
|
|
3852
3933
|
return result.rows.length;
|
|
3853
3934
|
};
|
|
3854
3935
|
const result = await harnessPersistCompletedSheetRows(persistRequest);
|
|
3936
|
+
console.warn('[play-runner.persist_completed_map_rows.result]', {
|
|
3937
|
+
runId: req.runId,
|
|
3938
|
+
playName: req.playName,
|
|
3939
|
+
tableNamespace,
|
|
3940
|
+
rows: rows.length,
|
|
3941
|
+
rowsWritten: result.rowsWritten,
|
|
3942
|
+
expectedVisibleRows,
|
|
3943
|
+
expectedKeyCount: expectedKeys.length,
|
|
3944
|
+
});
|
|
3855
3945
|
let visibleRows = -1;
|
|
3856
3946
|
let retryWritten: number | null = null;
|
|
3857
3947
|
let retryVisible: number | null = null;
|
|
3858
|
-
if (
|
|
3948
|
+
if (
|
|
3949
|
+
rows.length <= MAP_INCREMENTAL_PERSIST_CHUNK_ROWS ||
|
|
3950
|
+
result.rowsWritten !== rows.length
|
|
3951
|
+
) {
|
|
3859
3952
|
visibleRows = await readVisibleRowCount();
|
|
3860
|
-
if (visibleRows <
|
|
3953
|
+
if (visibleRows < expectedVisibleRows) {
|
|
3861
3954
|
await harnessStartSheetDataset({
|
|
3862
3955
|
...sessionScope,
|
|
3863
3956
|
tableNamespace,
|
|
@@ -3869,7 +3962,7 @@ async function persistCompletedMapRows(input: {
|
|
|
3869
3962
|
const retry = await harnessPersistCompletedSheetRows(persistRequest);
|
|
3870
3963
|
retryWritten = retry.rowsWritten;
|
|
3871
3964
|
retryVisible = await readVisibleRowCount();
|
|
3872
|
-
if (retryVisible >=
|
|
3965
|
+
if (retryVisible >= expectedVisibleRows) {
|
|
3873
3966
|
return {
|
|
3874
3967
|
rows: rows.length,
|
|
3875
3968
|
written: result.rowsWritten,
|
|
@@ -3879,13 +3972,13 @@ async function persistCompletedMapRows(input: {
|
|
|
3879
3972
|
};
|
|
3880
3973
|
}
|
|
3881
3974
|
throw new Error(
|
|
3882
|
-
`Runtime sheet persistence mismatch for ${tableNamespace}: wrote ${result.rowsWritten}/${rows.length}; visible ${visibleRows}; retry wrote ${retryWritten}/${rows.length}; retry visible ${retryVisible}; run ${req.runId}.`,
|
|
3975
|
+
`Runtime sheet persistence mismatch for ${tableNamespace}: wrote ${result.rowsWritten}/${rows.length}; visible ${visibleRows}/${expectedVisibleRows}; retry wrote ${retryWritten}/${rows.length}; retry visible ${retryVisible}/${expectedVisibleRows}; run ${req.runId}.`,
|
|
3883
3976
|
);
|
|
3884
3977
|
}
|
|
3885
3978
|
}
|
|
3886
|
-
if (result.rowsWritten !== rows.length) {
|
|
3979
|
+
if (result.rowsWritten !== rows.length && visibleRows < expectedVisibleRows) {
|
|
3887
3980
|
throw new Error(
|
|
3888
|
-
`Runtime sheet persistence mismatch for ${tableNamespace}: wrote ${result.rowsWritten}/${rows.length}; run ${req.runId}.`,
|
|
3981
|
+
`Runtime sheet persistence mismatch for ${tableNamespace}: wrote ${result.rowsWritten}/${rows.length}; visible ${visibleRows}/${expectedVisibleRows}; run ${req.runId}.`,
|
|
3889
3982
|
);
|
|
3890
3983
|
}
|
|
3891
3984
|
return {
|
|
@@ -4940,7 +5033,7 @@ function createMinimalWorkerCtx(
|
|
|
4940
5033
|
let persistFailure: unknown = null;
|
|
4941
5034
|
let scheduledLiveUpdateTimer: ReturnType<typeof setTimeout> | null = null;
|
|
4942
5035
|
let liveUpdateFlushChain: Promise<void> = Promise.resolve();
|
|
4943
|
-
let
|
|
5036
|
+
let liveUpdateFailureCount = 0;
|
|
4944
5037
|
|
|
4945
5038
|
const clearScheduledPersistTimer = () => {
|
|
4946
5039
|
if (scheduledPersistTimer) {
|
|
@@ -5078,25 +5171,35 @@ function createMinimalWorkerCtx(
|
|
|
5078
5171
|
const updates = pendingLiveRowUpdates.splice(0);
|
|
5079
5172
|
const extraOutputFields = Array.from(generatedOutputFields);
|
|
5080
5173
|
const task = liveUpdateFlushChain.then(async () => {
|
|
5081
|
-
|
|
5082
|
-
|
|
5083
|
-
|
|
5084
|
-
|
|
5085
|
-
|
|
5086
|
-
|
|
5087
|
-
|
|
5088
|
-
|
|
5089
|
-
|
|
5090
|
-
|
|
5091
|
-
|
|
5174
|
+
try {
|
|
5175
|
+
await applyLiveMapRowUpdates({
|
|
5176
|
+
req,
|
|
5177
|
+
tableNamespace: name,
|
|
5178
|
+
outputFields,
|
|
5179
|
+
extraOutputFields,
|
|
5180
|
+
updates,
|
|
5181
|
+
});
|
|
5182
|
+
} catch (error) {
|
|
5183
|
+
liveUpdateFailureCount += 1;
|
|
5184
|
+
if (liveUpdateFailureCount <= MAP_ROW_FAILURE_SAMPLE_LIMIT) {
|
|
5185
|
+
emitEvent({
|
|
5186
|
+
type: 'log',
|
|
5187
|
+
level: 'warn',
|
|
5188
|
+
message:
|
|
5189
|
+
`Live row update flush failed for ctx.dataset("${name}") ` +
|
|
5190
|
+
`(non-fatal; terminal rows still persist): ${formatWorkerRowFailureMessage(error)}`,
|
|
5191
|
+
ts: nowMs(),
|
|
5192
|
+
});
|
|
5193
|
+
}
|
|
5194
|
+
}
|
|
5092
5195
|
});
|
|
5196
|
+
liveUpdateFlushChain = task.catch(() => undefined);
|
|
5093
5197
|
return task;
|
|
5094
5198
|
};
|
|
5095
5199
|
|
|
5096
5200
|
const scheduleLiveRowUpdates = () => {
|
|
5097
|
-
if (liveUpdateFailure) return;
|
|
5098
5201
|
if (
|
|
5099
|
-
pendingLiveRowUpdates.length >=
|
|
5202
|
+
pendingLiveRowUpdates.length >= MAP_LIVE_UPDATE_FLUSH_CHUNK_ROWS
|
|
5100
5203
|
) {
|
|
5101
5204
|
void flushLiveRowUpdates().catch(() => undefined);
|
|
5102
5205
|
return;
|
|
@@ -5111,14 +5214,12 @@ function createMinimalWorkerCtx(
|
|
|
5111
5214
|
const enqueueLiveRowUpdate = (
|
|
5112
5215
|
update: Omit<PlayRowUpdate, 'rowId'> & { runId?: string },
|
|
5113
5216
|
): Promise<void> => {
|
|
5114
|
-
if (liveUpdateFailure) {
|
|
5115
|
-
return Promise.reject(liveUpdateFailure);
|
|
5116
|
-
}
|
|
5117
5217
|
pendingLiveRowUpdates.push(update);
|
|
5118
5218
|
if (
|
|
5119
|
-
pendingLiveRowUpdates.length >=
|
|
5219
|
+
pendingLiveRowUpdates.length >= MAP_LIVE_UPDATE_FLUSH_CHUNK_ROWS
|
|
5120
5220
|
) {
|
|
5121
|
-
|
|
5221
|
+
void flushLiveRowUpdates().catch(() => undefined);
|
|
5222
|
+
return Promise.resolve();
|
|
5122
5223
|
}
|
|
5123
5224
|
scheduleLiveRowUpdates();
|
|
5124
5225
|
return Promise.resolve();
|
|
@@ -5301,7 +5402,7 @@ function createMinimalWorkerCtx(
|
|
|
5301
5402
|
} catch (rowError) {
|
|
5302
5403
|
// Abort/budget errors stay run-fatal and leave no partial
|
|
5303
5404
|
// state: rethrow immediately without recording the row.
|
|
5304
|
-
if (
|
|
5405
|
+
if (isRunFatalWorkerRowError(rowError)) {
|
|
5305
5406
|
throw rowError;
|
|
5306
5407
|
}
|
|
5307
5408
|
const message = formatWorkerRowFailureMessage(rowError);
|
|
@@ -5401,6 +5502,43 @@ function createMinimalWorkerCtx(
|
|
|
5401
5502
|
concurrency,
|
|
5402
5503
|
},
|
|
5403
5504
|
});
|
|
5505
|
+
const buildRowFailureSamples = () =>
|
|
5506
|
+
failedRowEntries
|
|
5507
|
+
.map((failure, executedIndex) =>
|
|
5508
|
+
failure
|
|
5509
|
+
? {
|
|
5510
|
+
rowKey: uniqueRowsToExecuteEntries[executedIndex]!.rowKey,
|
|
5511
|
+
error: failure.error,
|
|
5512
|
+
}
|
|
5513
|
+
: null,
|
|
5514
|
+
)
|
|
5515
|
+
.filter(
|
|
5516
|
+
(sample): sample is { rowKey: string; error: string } =>
|
|
5517
|
+
sample !== null,
|
|
5518
|
+
)
|
|
5519
|
+
.slice(0, MAP_ROW_FAILURE_SAMPLE_LIMIT);
|
|
5520
|
+
const fatalMapChunkSummary = async (
|
|
5521
|
+
error: unknown,
|
|
5522
|
+
): Promise<WorkerMapChunkSummary<T & Record<string, unknown>>> => ({
|
|
5523
|
+
chunkIndex,
|
|
5524
|
+
rangeStart: baseOffset + chunkStart,
|
|
5525
|
+
rangeEnd: baseOffset + chunkStart,
|
|
5526
|
+
rowsRead: chunkRows.length,
|
|
5527
|
+
rowsWritten: 0,
|
|
5528
|
+
rowsExecuted: rowsToExecute.length,
|
|
5529
|
+
rowsCached: 0,
|
|
5530
|
+
rowsDuplicateReused: duplicateInputReuseCount,
|
|
5531
|
+
rowsInserted,
|
|
5532
|
+
rowsSkipped,
|
|
5533
|
+
rowsFailed: failedExecutedRows,
|
|
5534
|
+
rowFailureSamples: buildRowFailureSamples(),
|
|
5535
|
+
stepCellsCompleted,
|
|
5536
|
+
stepCellsSkipped,
|
|
5537
|
+
outputDatasetId: `map:${name}`,
|
|
5538
|
+
hash: await hashJson([]),
|
|
5539
|
+
fatalError: formatWorkerRowFailureMessage(error),
|
|
5540
|
+
preview: [],
|
|
5541
|
+
});
|
|
5404
5542
|
const persistRowsStartedAt = nowMs();
|
|
5405
5543
|
recordRunnerPerfTrace({
|
|
5406
5544
|
req,
|
|
@@ -5415,7 +5553,6 @@ function createMinimalWorkerCtx(
|
|
|
5415
5553
|
try {
|
|
5416
5554
|
await flushLiveRowUpdates();
|
|
5417
5555
|
await liveUpdateFlushChain;
|
|
5418
|
-
if (liveUpdateFailure) throw liveUpdateFailure;
|
|
5419
5556
|
await enqueuePersistExecutedRows();
|
|
5420
5557
|
await persistFlushChain;
|
|
5421
5558
|
if (persistFailure) throw persistFailure;
|
|
@@ -5441,13 +5578,16 @@ function createMinimalWorkerCtx(
|
|
|
5441
5578
|
error: error instanceof Error ? error.message : String(error),
|
|
5442
5579
|
},
|
|
5443
5580
|
});
|
|
5444
|
-
|
|
5581
|
+
return await fatalMapChunkSummary(error);
|
|
5445
5582
|
}
|
|
5446
5583
|
const rejectedWorker = workerResults.find(
|
|
5447
5584
|
(result): result is PromiseRejectedResult =>
|
|
5448
5585
|
result.status === 'rejected',
|
|
5449
5586
|
);
|
|
5450
5587
|
if (rejectedWorker) {
|
|
5588
|
+
if (isRuntimeReceiptPersistenceError(rejectedWorker.reason)) {
|
|
5589
|
+
return await fatalMapChunkSummary(rejectedWorker.reason);
|
|
5590
|
+
}
|
|
5451
5591
|
throw rejectedWorker.reason;
|
|
5452
5592
|
}
|
|
5453
5593
|
const resultByKey = new Map<string, T & Record<string, unknown>>();
|
|
@@ -5502,20 +5642,7 @@ function createMinimalWorkerCtx(
|
|
|
5502
5642
|
0,
|
|
5503
5643
|
executedRows.length - failedExecutedRows,
|
|
5504
5644
|
);
|
|
5505
|
-
const rowFailureSamples =
|
|
5506
|
-
.map((failure, executedIndex) =>
|
|
5507
|
-
failure
|
|
5508
|
-
? {
|
|
5509
|
-
rowKey: uniqueRowsToExecuteEntries[executedIndex]!.rowKey,
|
|
5510
|
-
error: failure.error,
|
|
5511
|
-
}
|
|
5512
|
-
: null,
|
|
5513
|
-
)
|
|
5514
|
-
.filter(
|
|
5515
|
-
(sample): sample is { rowKey: string; error: string } =>
|
|
5516
|
-
sample !== null,
|
|
5517
|
-
)
|
|
5518
|
-
.slice(0, MAP_ROW_FAILURE_SAMPLE_LIMIT);
|
|
5645
|
+
const rowFailureSamples = buildRowFailureSamples();
|
|
5519
5646
|
const publicOut = out.map((row) => publicCsvOutputRow(row));
|
|
5520
5647
|
const keyedOut = outEntries.map(({ key, inputIndex, row }) => ({
|
|
5521
5648
|
...row,
|
|
@@ -5764,6 +5891,15 @@ function createMinimalWorkerCtx(
|
|
|
5764
5891
|
continue;
|
|
5765
5892
|
}
|
|
5766
5893
|
const chunkResult = await runChunkStep(chunkRows, chunkStart, chunkIndex);
|
|
5894
|
+
if (chunkResult.fatalError) {
|
|
5895
|
+
throw new Error(
|
|
5896
|
+
`ctx.dataset("${name}") stopped after a runtime persistence failure ` +
|
|
5897
|
+
`outside the retryable chunk step. Provider calls already executed for ` +
|
|
5898
|
+
`${chunkResult.rowsExecuted} row(s), so the chunk was not retried. ` +
|
|
5899
|
+
`Fix the runtime persistence cause and re-run to resume. ` +
|
|
5900
|
+
`First error: ${chunkResult.fatalError}`,
|
|
5901
|
+
);
|
|
5902
|
+
}
|
|
5767
5903
|
totalRowsWritten += chunkResult.rowsWritten;
|
|
5768
5904
|
totalRowsExecuted += chunkResult.rowsExecuted;
|
|
5769
5905
|
totalRowsCached += chunkResult.rowsCached;
|
|
@@ -6282,6 +6418,7 @@ function createMinimalWorkerCtx(
|
|
|
6282
6418
|
orgId: req.orgId,
|
|
6283
6419
|
callbackBaseUrl: req.callbackUrl,
|
|
6284
6420
|
baseUrl: req.baseUrl,
|
|
6421
|
+
integrationMode: req.integrationMode ?? null,
|
|
6285
6422
|
parentExecutorToken: req.executorToken,
|
|
6286
6423
|
userEmail: req.userEmail ?? '',
|
|
6287
6424
|
profile: 'workers_edge',
|
|
@@ -7660,11 +7797,18 @@ function extractMaxCreditsPerRun(contractSnapshot: unknown): number | null {
|
|
|
7660
7797
|
: null;
|
|
7661
7798
|
}
|
|
7662
7799
|
|
|
7800
|
+
function shouldSkipWorkerComputeBilling(req: RunRequest): boolean {
|
|
7801
|
+
return req.integrationMode === 'fixture' || req.integrationMode === 'eval_stub';
|
|
7802
|
+
}
|
|
7803
|
+
|
|
7663
7804
|
async function finalizeWorkerComputeBilling(input: {
|
|
7664
7805
|
req: RunRequest;
|
|
7665
7806
|
success: boolean;
|
|
7666
7807
|
actionEstimate: number;
|
|
7667
7808
|
}): Promise<void> {
|
|
7809
|
+
if (shouldSkipWorkerComputeBilling(input.req)) {
|
|
7810
|
+
return;
|
|
7811
|
+
}
|
|
7668
7812
|
const maxCreditsPerRun = extractMaxCreditsPerRun(input.req.contractSnapshot);
|
|
7669
7813
|
await postRuntimeApi(input.req.baseUrl, input.req.executorToken, {
|
|
7670
7814
|
action: 'compute_billing_finalize',
|
|
@@ -7720,6 +7864,7 @@ function runRequestFromWorkflowParams(
|
|
|
7720
7864
|
callbackUrl: String(params.baseUrl ?? ''),
|
|
7721
7865
|
executorToken: String(params.executorToken ?? ''),
|
|
7722
7866
|
baseUrl: String(params.baseUrl ?? ''),
|
|
7867
|
+
integrationMode: normalizeIntegrationMode(params.integrationMode),
|
|
7723
7868
|
orgId: String(params.orgId ?? ''),
|
|
7724
7869
|
playName: String(params.playName ?? ''),
|
|
7725
7870
|
userEmail: typeof params.userEmail === 'string' ? params.userEmail : null,
|
|
@@ -8059,7 +8204,7 @@ export class TenantWorkflow extends WorkflowEntrypoint<
|
|
|
8059
8204
|
// somewhere inside executeRunRequest. If it doesn't appear, the
|
|
8060
8205
|
// throw is in the framework wrapper between the loader and run().
|
|
8061
8206
|
console.log(
|
|
8062
|
-
`${runPrefix} TenantWorkflow.run entered baseUrl=${req.baseUrl}`,
|
|
8207
|
+
`${runPrefix} TenantWorkflow.run entered baseUrl=${req.baseUrl} integrationMode=${req.integrationMode ?? 'default'}`,
|
|
8063
8208
|
);
|
|
8064
8209
|
captureCoordinatorBinding(this.env);
|
|
8065
8210
|
captureRuntimeApiBinding(this.env);
|
|
@@ -8073,6 +8218,7 @@ export class TenantWorkflow extends WorkflowEntrypoint<
|
|
|
8073
8218
|
ms: 0,
|
|
8074
8219
|
extra: {
|
|
8075
8220
|
hasWorkflowStep: true,
|
|
8221
|
+
integrationMode: req.integrationMode ?? null,
|
|
8076
8222
|
},
|
|
8077
8223
|
});
|
|
8078
8224
|
// Fire the one-time wiring probe (deduplicated across runs in the
|