deepline 0.1.168 → 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 +229 -75
- 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,15 +3962,23 @@ async function persistCompletedMapRows(input: {
|
|
|
3869
3962
|
const retry = await harnessPersistCompletedSheetRows(persistRequest);
|
|
3870
3963
|
retryWritten = retry.rowsWritten;
|
|
3871
3964
|
retryVisible = await readVisibleRowCount();
|
|
3872
|
-
if (retryVisible
|
|
3873
|
-
|
|
3874
|
-
|
|
3875
|
-
|
|
3965
|
+
if (retryVisible >= expectedVisibleRows) {
|
|
3966
|
+
return {
|
|
3967
|
+
rows: rows.length,
|
|
3968
|
+
written: result.rowsWritten,
|
|
3969
|
+
visible: visibleRows,
|
|
3970
|
+
retryWritten,
|
|
3971
|
+
retryVisible,
|
|
3972
|
+
};
|
|
3973
|
+
}
|
|
3974
|
+
throw new Error(
|
|
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}.`,
|
|
3976
|
+
);
|
|
3876
3977
|
}
|
|
3877
3978
|
}
|
|
3878
|
-
if (result.rowsWritten !== rows.length && visibleRows <
|
|
3979
|
+
if (result.rowsWritten !== rows.length && visibleRows < expectedVisibleRows) {
|
|
3879
3980
|
throw new Error(
|
|
3880
|
-
`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}.`,
|
|
3881
3982
|
);
|
|
3882
3983
|
}
|
|
3883
3984
|
return {
|
|
@@ -4932,7 +5033,7 @@ function createMinimalWorkerCtx(
|
|
|
4932
5033
|
let persistFailure: unknown = null;
|
|
4933
5034
|
let scheduledLiveUpdateTimer: ReturnType<typeof setTimeout> | null = null;
|
|
4934
5035
|
let liveUpdateFlushChain: Promise<void> = Promise.resolve();
|
|
4935
|
-
let
|
|
5036
|
+
let liveUpdateFailureCount = 0;
|
|
4936
5037
|
|
|
4937
5038
|
const clearScheduledPersistTimer = () => {
|
|
4938
5039
|
if (scheduledPersistTimer) {
|
|
@@ -5070,25 +5171,35 @@ function createMinimalWorkerCtx(
|
|
|
5070
5171
|
const updates = pendingLiveRowUpdates.splice(0);
|
|
5071
5172
|
const extraOutputFields = Array.from(generatedOutputFields);
|
|
5072
5173
|
const task = liveUpdateFlushChain.then(async () => {
|
|
5073
|
-
|
|
5074
|
-
|
|
5075
|
-
|
|
5076
|
-
|
|
5077
|
-
|
|
5078
|
-
|
|
5079
|
-
|
|
5080
|
-
|
|
5081
|
-
|
|
5082
|
-
|
|
5083
|
-
|
|
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
|
+
}
|
|
5084
5195
|
});
|
|
5196
|
+
liveUpdateFlushChain = task.catch(() => undefined);
|
|
5085
5197
|
return task;
|
|
5086
5198
|
};
|
|
5087
5199
|
|
|
5088
5200
|
const scheduleLiveRowUpdates = () => {
|
|
5089
|
-
if (liveUpdateFailure) return;
|
|
5090
5201
|
if (
|
|
5091
|
-
pendingLiveRowUpdates.length >=
|
|
5202
|
+
pendingLiveRowUpdates.length >= MAP_LIVE_UPDATE_FLUSH_CHUNK_ROWS
|
|
5092
5203
|
) {
|
|
5093
5204
|
void flushLiveRowUpdates().catch(() => undefined);
|
|
5094
5205
|
return;
|
|
@@ -5103,14 +5214,12 @@ function createMinimalWorkerCtx(
|
|
|
5103
5214
|
const enqueueLiveRowUpdate = (
|
|
5104
5215
|
update: Omit<PlayRowUpdate, 'rowId'> & { runId?: string },
|
|
5105
5216
|
): Promise<void> => {
|
|
5106
|
-
if (liveUpdateFailure) {
|
|
5107
|
-
return Promise.reject(liveUpdateFailure);
|
|
5108
|
-
}
|
|
5109
5217
|
pendingLiveRowUpdates.push(update);
|
|
5110
5218
|
if (
|
|
5111
|
-
pendingLiveRowUpdates.length >=
|
|
5219
|
+
pendingLiveRowUpdates.length >= MAP_LIVE_UPDATE_FLUSH_CHUNK_ROWS
|
|
5112
5220
|
) {
|
|
5113
|
-
|
|
5221
|
+
void flushLiveRowUpdates().catch(() => undefined);
|
|
5222
|
+
return Promise.resolve();
|
|
5114
5223
|
}
|
|
5115
5224
|
scheduleLiveRowUpdates();
|
|
5116
5225
|
return Promise.resolve();
|
|
@@ -5293,7 +5402,7 @@ function createMinimalWorkerCtx(
|
|
|
5293
5402
|
} catch (rowError) {
|
|
5294
5403
|
// Abort/budget errors stay run-fatal and leave no partial
|
|
5295
5404
|
// state: rethrow immediately without recording the row.
|
|
5296
|
-
if (
|
|
5405
|
+
if (isRunFatalWorkerRowError(rowError)) {
|
|
5297
5406
|
throw rowError;
|
|
5298
5407
|
}
|
|
5299
5408
|
const message = formatWorkerRowFailureMessage(rowError);
|
|
@@ -5393,6 +5502,43 @@ function createMinimalWorkerCtx(
|
|
|
5393
5502
|
concurrency,
|
|
5394
5503
|
},
|
|
5395
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
|
+
});
|
|
5396
5542
|
const persistRowsStartedAt = nowMs();
|
|
5397
5543
|
recordRunnerPerfTrace({
|
|
5398
5544
|
req,
|
|
@@ -5407,7 +5553,6 @@ function createMinimalWorkerCtx(
|
|
|
5407
5553
|
try {
|
|
5408
5554
|
await flushLiveRowUpdates();
|
|
5409
5555
|
await liveUpdateFlushChain;
|
|
5410
|
-
if (liveUpdateFailure) throw liveUpdateFailure;
|
|
5411
5556
|
await enqueuePersistExecutedRows();
|
|
5412
5557
|
await persistFlushChain;
|
|
5413
5558
|
if (persistFailure) throw persistFailure;
|
|
@@ -5433,13 +5578,16 @@ function createMinimalWorkerCtx(
|
|
|
5433
5578
|
error: error instanceof Error ? error.message : String(error),
|
|
5434
5579
|
},
|
|
5435
5580
|
});
|
|
5436
|
-
|
|
5581
|
+
return await fatalMapChunkSummary(error);
|
|
5437
5582
|
}
|
|
5438
5583
|
const rejectedWorker = workerResults.find(
|
|
5439
5584
|
(result): result is PromiseRejectedResult =>
|
|
5440
5585
|
result.status === 'rejected',
|
|
5441
5586
|
);
|
|
5442
5587
|
if (rejectedWorker) {
|
|
5588
|
+
if (isRuntimeReceiptPersistenceError(rejectedWorker.reason)) {
|
|
5589
|
+
return await fatalMapChunkSummary(rejectedWorker.reason);
|
|
5590
|
+
}
|
|
5443
5591
|
throw rejectedWorker.reason;
|
|
5444
5592
|
}
|
|
5445
5593
|
const resultByKey = new Map<string, T & Record<string, unknown>>();
|
|
@@ -5494,20 +5642,7 @@ function createMinimalWorkerCtx(
|
|
|
5494
5642
|
0,
|
|
5495
5643
|
executedRows.length - failedExecutedRows,
|
|
5496
5644
|
);
|
|
5497
|
-
const rowFailureSamples =
|
|
5498
|
-
.map((failure, executedIndex) =>
|
|
5499
|
-
failure
|
|
5500
|
-
? {
|
|
5501
|
-
rowKey: uniqueRowsToExecuteEntries[executedIndex]!.rowKey,
|
|
5502
|
-
error: failure.error,
|
|
5503
|
-
}
|
|
5504
|
-
: null,
|
|
5505
|
-
)
|
|
5506
|
-
.filter(
|
|
5507
|
-
(sample): sample is { rowKey: string; error: string } =>
|
|
5508
|
-
sample !== null,
|
|
5509
|
-
)
|
|
5510
|
-
.slice(0, MAP_ROW_FAILURE_SAMPLE_LIMIT);
|
|
5645
|
+
const rowFailureSamples = buildRowFailureSamples();
|
|
5511
5646
|
const publicOut = out.map((row) => publicCsvOutputRow(row));
|
|
5512
5647
|
const keyedOut = outEntries.map(({ key, inputIndex, row }) => ({
|
|
5513
5648
|
...row,
|
|
@@ -5756,6 +5891,15 @@ function createMinimalWorkerCtx(
|
|
|
5756
5891
|
continue;
|
|
5757
5892
|
}
|
|
5758
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
|
+
}
|
|
5759
5903
|
totalRowsWritten += chunkResult.rowsWritten;
|
|
5760
5904
|
totalRowsExecuted += chunkResult.rowsExecuted;
|
|
5761
5905
|
totalRowsCached += chunkResult.rowsCached;
|
|
@@ -6274,6 +6418,7 @@ function createMinimalWorkerCtx(
|
|
|
6274
6418
|
orgId: req.orgId,
|
|
6275
6419
|
callbackBaseUrl: req.callbackUrl,
|
|
6276
6420
|
baseUrl: req.baseUrl,
|
|
6421
|
+
integrationMode: req.integrationMode ?? null,
|
|
6277
6422
|
parentExecutorToken: req.executorToken,
|
|
6278
6423
|
userEmail: req.userEmail ?? '',
|
|
6279
6424
|
profile: 'workers_edge',
|
|
@@ -7652,11 +7797,18 @@ function extractMaxCreditsPerRun(contractSnapshot: unknown): number | null {
|
|
|
7652
7797
|
: null;
|
|
7653
7798
|
}
|
|
7654
7799
|
|
|
7800
|
+
function shouldSkipWorkerComputeBilling(req: RunRequest): boolean {
|
|
7801
|
+
return req.integrationMode === 'fixture' || req.integrationMode === 'eval_stub';
|
|
7802
|
+
}
|
|
7803
|
+
|
|
7655
7804
|
async function finalizeWorkerComputeBilling(input: {
|
|
7656
7805
|
req: RunRequest;
|
|
7657
7806
|
success: boolean;
|
|
7658
7807
|
actionEstimate: number;
|
|
7659
7808
|
}): Promise<void> {
|
|
7809
|
+
if (shouldSkipWorkerComputeBilling(input.req)) {
|
|
7810
|
+
return;
|
|
7811
|
+
}
|
|
7660
7812
|
const maxCreditsPerRun = extractMaxCreditsPerRun(input.req.contractSnapshot);
|
|
7661
7813
|
await postRuntimeApi(input.req.baseUrl, input.req.executorToken, {
|
|
7662
7814
|
action: 'compute_billing_finalize',
|
|
@@ -7712,6 +7864,7 @@ function runRequestFromWorkflowParams(
|
|
|
7712
7864
|
callbackUrl: String(params.baseUrl ?? ''),
|
|
7713
7865
|
executorToken: String(params.executorToken ?? ''),
|
|
7714
7866
|
baseUrl: String(params.baseUrl ?? ''),
|
|
7867
|
+
integrationMode: normalizeIntegrationMode(params.integrationMode),
|
|
7715
7868
|
orgId: String(params.orgId ?? ''),
|
|
7716
7869
|
playName: String(params.playName ?? ''),
|
|
7717
7870
|
userEmail: typeof params.userEmail === 'string' ? params.userEmail : null,
|
|
@@ -8051,7 +8204,7 @@ export class TenantWorkflow extends WorkflowEntrypoint<
|
|
|
8051
8204
|
// somewhere inside executeRunRequest. If it doesn't appear, the
|
|
8052
8205
|
// throw is in the framework wrapper between the loader and run().
|
|
8053
8206
|
console.log(
|
|
8054
|
-
`${runPrefix} TenantWorkflow.run entered baseUrl=${req.baseUrl}`,
|
|
8207
|
+
`${runPrefix} TenantWorkflow.run entered baseUrl=${req.baseUrl} integrationMode=${req.integrationMode ?? 'default'}`,
|
|
8055
8208
|
);
|
|
8056
8209
|
captureCoordinatorBinding(this.env);
|
|
8057
8210
|
captureRuntimeApiBinding(this.env);
|
|
@@ -8065,6 +8218,7 @@ export class TenantWorkflow extends WorkflowEntrypoint<
|
|
|
8065
8218
|
ms: 0,
|
|
8066
8219
|
extra: {
|
|
8067
8220
|
hasWorkflowStep: true,
|
|
8221
|
+
integrationMode: req.integrationMode ?? null,
|
|
8068
8222
|
},
|
|
8069
8223
|
});
|
|
8070
8224
|
// Fire the one-time wiring probe (deduplicated across runs in the
|