deepline 0.3.314 → 0.3.316
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundling-sources/sdk/src/client.ts +12 -0
- package/dist/bundling-sources/sdk/src/release.ts +1 -1
- package/dist/bundling-sources/sdk/src/runs/overview.ts +17 -10
- package/dist/bundling-sources/sdk/src/types.ts +16 -5
- package/dist/bundling-sources/shared_libs/play-runtime/context.ts +217 -488
- package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +15 -0
- package/dist/bundling-sources/shared_libs/play-runtime/execution-capabilities.ts +4 -1
- package/dist/bundling-sources/shared_libs/play-runtime/internal-bootstrap-token.ts +13 -4
- package/dist/bundling-sources/shared_libs/play-runtime/launch-identity.ts +1 -0
- package/dist/bundling-sources/shared_libs/play-runtime/live-events.ts +31 -0
- package/dist/bundling-sources/shared_libs/play-runtime/map-execution-frame.ts +444 -51
- package/dist/bundling-sources/shared_libs/play-runtime/run-snapshot-stream.ts +22 -43
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/index.ts +4 -3
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +136 -87
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-authority.ts +24 -6
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-operation-contract.ts +56 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-sheet-errors.ts +94 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backend.ts +2 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-shared.ts +5 -2
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd.ts +20 -11
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-progress.ts +18 -12
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +140 -9
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-dispatch-authority.ts +2 -0
- package/dist/bundling-sources/shared_libs/play-runtime/work-receipt-storage-contract.ts +13 -0
- package/dist/bundling-sources/shared_libs/play-runtime/workflow-executor-auth.ts +2 -0
- package/dist/bundling-sources/shared_libs/plays/authoring-contract.ts +3 -2
- package/dist/bundling-sources/shared_libs/plays/docflow-binding-owner.ts +61 -11
- package/dist/cli/{auth-GWF55S3N.mjs → auth-JP7ZJ4OI.mjs} +4 -4
- package/dist/cli/auth-SPUJ4EXC.js +31 -0
- package/dist/cli/{billing-WWOJN7GV.mjs → billing-KG6MC2BC.mjs} +4 -4
- package/dist/cli/{billing-2YU6E2IF.js → billing-WZGS32ME.js} +70 -70
- package/dist/cli/{chunk-OJ243ZA5.js → chunk-2HKPAZVJ.js} +1 -1
- package/dist/cli/{chunk-YVMJTXEG.js → chunk-35YXDTOB.js} +26 -26
- package/dist/cli/{chunk-QB5MAFCU.mjs → chunk-46ZOD4PQ.mjs} +1 -1
- package/dist/cli/{chunk-CPN2N6EZ.mjs → chunk-6R5ACEWN.mjs} +43 -17
- package/dist/cli/{chunk-US4S3E4Y.mjs → chunk-7PZFGB7L.mjs} +1 -1
- package/dist/cli/{chunk-3CKNUJVZ.mjs → chunk-AXAPMVUC.mjs} +4 -4
- package/dist/cli/{chunk-ENQZV7NR.js → chunk-B6OOVO3A.js} +562 -536
- package/dist/cli/{chunk-WDPRE6DU.js → chunk-BOKHMPCZ.js} +48 -48
- package/dist/cli/{chunk-VFRZG4OW.js → chunk-C6QGM72M.js} +1 -1
- package/dist/cli/{chunk-IZTIBG7A.mjs → chunk-D3NMIACS.mjs} +29 -15
- package/dist/cli/{chunk-DR3S76BG.mjs → chunk-DAFGPNVW.mjs} +1 -1
- package/dist/cli/{chunk-3K6QD7Z3.mjs → chunk-F2T5UENG.mjs} +1 -1
- package/dist/cli/{chunk-VWW6VHQX.js → chunk-G2G67D3L.js} +60 -60
- package/dist/cli/{chunk-ODEWOXWW.js → chunk-GHLWDXUB.js} +6 -6
- package/dist/cli/{chunk-25SPKKF2.mjs → chunk-IDSDRGKF.mjs} +1 -1
- package/dist/cli/{chunk-OUHCJL5B.mjs → chunk-J3ZPMADG.mjs} +1 -1
- package/dist/cli/{chunk-MLEJ2FYH.js → chunk-K3BIRBT3.js} +248 -234
- package/dist/cli/{chunk-N5V2SBB2.mjs → chunk-KP7W5NO6.mjs} +1 -1
- package/dist/cli/{chunk-B5LUKLKH.js → chunk-MCPHK7AF.js} +4 -4
- package/dist/cli/{chunk-2Q2IKUL5.mjs → chunk-OB3SYJGU.mjs} +3 -3
- package/dist/cli/{chunk-UZTTPEG2.js → chunk-PJERS5VW.js} +6 -6
- package/dist/cli/{chunk-VBRO5QCI.js → chunk-RBBSRB56.js} +15 -15
- package/dist/cli/{chunk-NG4WDOGN.js → chunk-SRUWVQ66.js} +6 -6
- package/dist/cli/{chunk-WTO3ITBC.mjs → chunk-TYSAKSX7.mjs} +2 -2
- package/dist/cli/{chunk-HTXZLCSP.mjs → chunk-VC25WFXV.mjs} +2 -2
- package/dist/cli/{chunk-3A4LJUX6.mjs → chunk-VDPBQCRQ.mjs} +2 -2
- package/dist/cli/{chunk-IALPYID6.js → chunk-XSEMQ4II.js} +3 -3
- package/dist/cli/{chunk-JNUHGWB2.js → chunk-YEMOOWZI.js} +50 -50
- package/dist/cli/{chunk-JZZT4GAY.mjs → chunk-YNSAVFWL.mjs} +5 -5
- package/dist/cli/{chunk-GSRDZD7R.js → chunk-ZNHGAWYI.js} +2 -2
- package/dist/cli/client-GMMPQT7B.js +20 -0
- package/dist/cli/{client-EYGNDORT.mjs → client-MNPM4ME3.mjs} +3 -3
- package/dist/cli/{csv-YOW5JMOH.js → csv-G72FIQWI.js} +12 -12
- package/dist/cli/{csv-NZCN7SVV.mjs → csv-ZME7HAPR.mjs} +3 -3
- package/dist/cli/{db-HALJV3KY.mjs → db-K2DS4PEY.mjs} +4 -4
- package/dist/cli/{db-6BIYLZ6F.js → db-KRBWHSMA.js} +20 -20
- package/dist/cli/{describe-KY2ZYGBR.mjs → describe-LXBJP6OP.mjs} +10 -10
- package/dist/cli/{describe-WA6R2JSH.js → describe-UKFV376D.js} +17 -17
- package/dist/cli/{executions-CBOAN6KI.mjs → executions-2V3AROY6.mjs} +4 -4
- package/dist/cli/{executions-NMCTN7XM.js → executions-E66AM4JU.js} +6 -6
- package/dist/cli/{feedback-ZZFDSCWS.js → feedback-7C2N7M37.js} +6 -6
- package/dist/cli/{feedback-FOMPE3DJ.mjs → feedback-IEPZ2XKZ.mjs} +3 -3
- package/dist/cli/{git-YQR2NBCO.mjs → git-AR5KGN4O.mjs} +4 -4
- package/dist/cli/git-EXYB66IH.js +23 -0
- package/dist/cli/index.js +171 -98
- package/dist/cli/index.mjs +114 -41
- package/dist/cli/{legacy-noops-XH2TFFI6.js → legacy-noops-A2SH45P4.js} +7 -7
- package/dist/cli/{legacy-noops-KMU6P3K4.mjs → legacy-noops-LC2EGAZU.mjs} +4 -4
- package/dist/cli/{monitors-2ONK5L3I.mjs → monitors-5YPW3IZQ.mjs} +4 -4
- package/dist/cli/{monitors-5M3BZ5OR.js → monitors-IZBUPKPW.js} +85 -85
- package/dist/cli/{org-LR5BMCGL.mjs → org-2OMYI5KJ.mjs} +4 -4
- package/dist/cli/{org-6MKULUZI.js → org-L42SQ65U.js} +60 -60
- package/dist/cli/play-CQI3IDDN.js +152 -0
- package/dist/cli/{play-4NOSD7DW.mjs → play-UPCBLAOH.mjs} +9 -9
- package/dist/cli/{providers-UFJD3VKF.js → providers-GGNDWUKB.js} +7 -7
- package/dist/cli/{providers-UBGIKGCA.mjs → providers-VE2RM56M.mjs} +4 -4
- package/dist/cli/{quickstart-KQZHZE6C.js → quickstart-4CZHURUX.js} +5 -5
- package/dist/cli/{quickstart-KDUKQRUH.mjs → quickstart-HSJ7FU7Z.mjs} +3 -3
- package/dist/cli/{search-4BVOOS5Q.mjs → search-MWBM3I2L.mjs} +5 -5
- package/dist/cli/search-PD5FBCUN.js +26 -0
- package/dist/cli/{secrets-TVXZ3WJ3.js → secrets-CWBPGDZV.js} +13 -13
- package/dist/cli/{secrets-YGV23N3N.mjs → secrets-W5DQYKGU.mjs} +4 -4
- package/dist/cli/{sessions-RWIQWDFD.js → sessions-EDCFU6P2.js} +5 -5
- package/dist/cli/{sessions-G7ROUW35.mjs → sessions-Q42GUYTF.mjs} +4 -4
- package/dist/cli/{settings-TG3E2NR7.js → settings-OKRENZGX.js} +74 -74
- package/dist/cli/{settings-QZEVGCXE.mjs → settings-SO56AJPQ.mjs} +7 -7
- package/dist/cli/{setup-3KDUNEEE.js → setup-7PLHLNLS.js} +41 -41
- package/dist/cli/{setup-HUXINKOH.mjs → setup-OTYMF5CZ.mjs} +6 -6
- package/dist/cli/{skills-LHU3DB7J.mjs → skills-4UFS4FXP.mjs} +4 -4
- package/dist/cli/skills-IP7IW7EQ.js +28 -0
- package/dist/cli/{tools-J5WQ33BB.mjs → tools-6FV543YV.mjs} +6 -6
- package/dist/cli/tools-A2YNR6PI.js +38 -0
- package/dist/cli/{update-T6744RM7.mjs → update-6POGDXYW.mjs} +6 -6
- package/dist/cli/update-QXSGKLJG.js +28 -0
- package/dist/cli/{workflow-CG2B65HD.mjs → workflow-HVZSFWYR.mjs} +5 -5
- package/dist/cli/{workflow-YF5SQJLG.js → workflow-RB4POZP5.js} +15 -15
- package/dist/{client-OBwghxPC.d.ts → client-BV68GMPo.d.ts} +19 -6
- package/dist/{client-CtVdLZux.d.mts → client-D9ACjiRC.d.mts} +19 -6
- package/dist/{compiler-manifest-wOKNiXpa.d.mts → compiler-manifest-BXcZ4P4W.d.mts} +2 -2
- package/dist/{compiler-manifest-wOKNiXpa.d.ts → compiler-manifest-BXcZ4P4W.d.ts} +2 -2
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +7 -7
- package/dist/index.mjs +4 -4
- package/dist/install-integrity.json +82 -82
- package/dist/plays/bundle-play-file.d.mts +2 -2
- package/dist/plays/bundle-play-file.d.ts +2 -2
- package/dist/plays/bundle-play-file.mjs +2 -2
- package/dist/plays/run-request.d.mts +2 -2
- package/dist/plays/run-request.d.ts +2 -2
- package/dist/release.d.mts +1 -1
- package/dist/release.d.ts +1 -1
- package/dist/release.js +2 -2
- package/dist/release.mjs +1 -1
- package/package.json +1 -1
- package/dist/cli/auth-QX2L4LPM.js +0 -31
- package/dist/cli/client-Z4VFNTUB.js +0 -20
- package/dist/cli/git-AC2ATBDK.js +0 -23
- package/dist/cli/play-U3CZ4F2W.js +0 -152
- package/dist/cli/search-Y7OTFRCI.js +0 -26
- package/dist/cli/skills-CO5YUWBK.js +0 -28
- package/dist/cli/tools-MWPT5X47.js +0 -38
- package/dist/cli/update-VVIJW7ZJ.js +0 -28
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
import {
|
|
2
|
+
RuntimeSheetAttemptSupersededError,
|
|
3
|
+
RuntimeSheetWriteIntentUnavailableError,
|
|
4
|
+
type RuntimeMapRowsStaleReason,
|
|
5
|
+
type RuntimeMapRowsStaleRow,
|
|
6
|
+
} from './runtime-sheet-errors';
|
|
7
|
+
export {
|
|
8
|
+
RuntimeSheetAttemptSupersededError,
|
|
9
|
+
RuntimeSheetWriteIntentUnavailableError,
|
|
10
|
+
type RuntimeMapRowsStaleReason,
|
|
11
|
+
type RuntimeMapRowsStaleRow,
|
|
12
|
+
} from './runtime-sheet-errors';
|
|
1
13
|
import {
|
|
2
14
|
prepareRetainedPlayPipelinesForTransport,
|
|
3
15
|
hydrateRetainedPlayPipelines,
|
|
@@ -74,6 +86,7 @@ import {
|
|
|
74
86
|
} from './db-session-crypto';
|
|
75
87
|
import { createRuntimeDatasetId } from './dataset-id';
|
|
76
88
|
import {
|
|
89
|
+
buildScopedWorkReceiptKey,
|
|
77
90
|
scopedWorkReceiptKeyPrefix,
|
|
78
91
|
isReusableWorkReceipt,
|
|
79
92
|
type WorkReceipt,
|
|
@@ -88,7 +101,10 @@ import {
|
|
|
88
101
|
stringifyPostgresJson,
|
|
89
102
|
} from './postgres-json';
|
|
90
103
|
import { RECEIPT_STATUS_CODE, receiptStatusFromCode } from './receipt-status';
|
|
91
|
-
import {
|
|
104
|
+
import {
|
|
105
|
+
WORK_RECEIPT_EXECUTION_LOCK_TABLE,
|
|
106
|
+
RUNTIME_SHEET_WRITE_INTENT_RECEIPT_KIND,
|
|
107
|
+
} from './work-receipt-storage-contract';
|
|
92
108
|
import {
|
|
93
109
|
workReceiptClaimableStatusCodes,
|
|
94
110
|
workReceiptActiveOwnerPredicateSql,
|
|
@@ -103,6 +119,7 @@ import {
|
|
|
103
119
|
} from './sheet-attempt-sql';
|
|
104
120
|
import type { MapRowOutcome } from './durability-store';
|
|
105
121
|
import { RUNTIME_CAPACITY_POLICY } from './runtime-capacity-policy';
|
|
122
|
+
import type { RUNTIME_SHEET_ADMISSION_CAPABILITIES } from './runtime-operation-contract';
|
|
106
123
|
import {
|
|
107
124
|
normalizeRuntimeMapInputIndex,
|
|
108
125
|
prepareRuntimeSheetRowsForJsonTransport,
|
|
@@ -562,7 +579,7 @@ type RuntimeApiActionRequest =
|
|
|
562
579
|
runId?: string | null;
|
|
563
580
|
}
|
|
564
581
|
| {
|
|
565
|
-
action:
|
|
582
|
+
action: keyof typeof RUNTIME_SHEET_ADMISSION_CAPABILITIES;
|
|
566
583
|
input: Parameters<typeof startRuntimeSheetDataset>[1];
|
|
567
584
|
}
|
|
568
585
|
| {
|
|
@@ -960,6 +977,17 @@ async function postRuntimeApi<TResponse>(
|
|
|
960
977
|
]
|
|
961
978
|
.filter((value): value is string => Boolean(value))
|
|
962
979
|
.join(', ');
|
|
980
|
+
if (
|
|
981
|
+
body.action === 'runtime_sheet_start_with_intent' &&
|
|
982
|
+
(response.status === 400 || response.status === 403) &&
|
|
983
|
+
(errorMessage === 'Unsupported runtime action capability scope.' ||
|
|
984
|
+
errorMessage === 'Unsupported runtime data-plane action.' ||
|
|
985
|
+
errorMessage === `Unsupported action: ${body.action}`)
|
|
986
|
+
) {
|
|
987
|
+
throw new RuntimeSheetWriteIntentUnavailableError(
|
|
988
|
+
new Error(`${errorMessage} (${diagnosticContext}).`),
|
|
989
|
+
);
|
|
990
|
+
}
|
|
963
991
|
throw new Error(
|
|
964
992
|
details
|
|
965
993
|
? `${errorMessage} (${diagnosticContext}): ${details}`
|
|
@@ -989,7 +1017,8 @@ function runtimeApiRequestTimeoutMs(
|
|
|
989
1017
|
if (action === 'runtime_sheet_complete_map_rows') {
|
|
990
1018
|
return RUNTIME_SHEET_COMPLETION_REQUEST_TIMEOUT_MS;
|
|
991
1019
|
}
|
|
992
|
-
return action === 'runtime_sheet_start'
|
|
1020
|
+
return action === 'runtime_sheet_start' ||
|
|
1021
|
+
action === 'runtime_sheet_start_with_intent'
|
|
993
1022
|
? RUNTIME_SHEET_ADMISSION_REQUEST_TIMEOUT_MS
|
|
994
1023
|
: RUNTIME_API_REQUEST_TIMEOUT_MS;
|
|
995
1024
|
}
|
|
@@ -3073,6 +3102,92 @@ async function mintRuntimeSheetWriteVersion(
|
|
|
3073
3102
|
return value;
|
|
3074
3103
|
}
|
|
3075
3104
|
|
|
3105
|
+
/**
|
|
3106
|
+
* One run/table admits one write intent, independently of runner attempts and
|
|
3107
|
+
* source pages. Publish its immutable scalar in the row-admission transaction:
|
|
3108
|
+
* a lost response or checkpoint cannot turn a wake into newer customer intent.
|
|
3109
|
+
* Older callers without the opt-in retain the existing allocation behavior.
|
|
3110
|
+
*/
|
|
3111
|
+
async function resolveRuntimeSheetWriteVersion(
|
|
3112
|
+
client: RuntimeQueryClient,
|
|
3113
|
+
session: RuntimePostgresSession,
|
|
3114
|
+
input: Pick<
|
|
3115
|
+
Parameters<typeof startRuntimeSheetDataset>[1],
|
|
3116
|
+
'runId' | 'tableNamespace' | 'writeVersion' | 'stableWriteIntent'
|
|
3117
|
+
>,
|
|
3118
|
+
): Promise<number> {
|
|
3119
|
+
if (input.stableWriteIntent !== true) {
|
|
3120
|
+
return await mintRuntimeSheetWriteVersion(
|
|
3121
|
+
client,
|
|
3122
|
+
session,
|
|
3123
|
+
input.writeVersion,
|
|
3124
|
+
);
|
|
3125
|
+
}
|
|
3126
|
+
const key = buildScopedWorkReceiptKey({
|
|
3127
|
+
orgId: session.target.orgId,
|
|
3128
|
+
playName: session.playName,
|
|
3129
|
+
key: JSON.stringify([
|
|
3130
|
+
RUNTIME_SHEET_WRITE_INTENT_RECEIPT_KIND,
|
|
3131
|
+
input.runId,
|
|
3132
|
+
normalizeTableNamespace(input.tableNamespace),
|
|
3133
|
+
]),
|
|
3134
|
+
});
|
|
3135
|
+
const keyHex = workReceiptKeyHex(key);
|
|
3136
|
+
type WriteIntentReceipt = {
|
|
3137
|
+
status: number;
|
|
3138
|
+
run_id: string;
|
|
3139
|
+
output: { writeVersion?: unknown } | null;
|
|
3140
|
+
};
|
|
3141
|
+
const read = async () => {
|
|
3142
|
+
const { rows } = await client.query<WriteIntentReceipt>(
|
|
3143
|
+
`SELECT status, run_id, output FROM ${workReceiptTable(session)} WHERE k = decode($1, 'hex')`,
|
|
3144
|
+
[keyHex],
|
|
3145
|
+
);
|
|
3146
|
+
return rows[0];
|
|
3147
|
+
};
|
|
3148
|
+
let receipt = await read();
|
|
3149
|
+
if (!receipt) {
|
|
3150
|
+
const candidate = await mintRuntimeSheetWriteVersion(
|
|
3151
|
+
client,
|
|
3152
|
+
session,
|
|
3153
|
+
input.writeVersion,
|
|
3154
|
+
);
|
|
3155
|
+
const { rows } = await client.query<WriteIntentReceipt>(
|
|
3156
|
+
`INSERT INTO ${workReceiptTable(session)} (k, status, output, run_id)
|
|
3157
|
+
VALUES (decode($1, 'hex'), $2::smallint, $3::jsonb, $4)
|
|
3158
|
+
ON CONFLICT (k) DO NOTHING
|
|
3159
|
+
RETURNING status, run_id, output`,
|
|
3160
|
+
[
|
|
3161
|
+
keyHex,
|
|
3162
|
+
RECEIPT_STATUS_COMPLETED,
|
|
3163
|
+
stringifyPostgresJson({ writeVersion: candidate }),
|
|
3164
|
+
input.runId,
|
|
3165
|
+
],
|
|
3166
|
+
);
|
|
3167
|
+
// A conflicting INSERT may wait for its winner. A new statement is needed
|
|
3168
|
+
// to see that commit under READ COMMITTED; never use the losing candidate.
|
|
3169
|
+
receipt = rows[0] ?? (await read());
|
|
3170
|
+
}
|
|
3171
|
+
const version = receipt?.output?.writeVersion;
|
|
3172
|
+
if (
|
|
3173
|
+
receipt?.status !== RECEIPT_STATUS_COMPLETED ||
|
|
3174
|
+
receipt.run_id !== input.runId ||
|
|
3175
|
+
typeof version !== 'number' ||
|
|
3176
|
+
!Number.isSafeInteger(version) ||
|
|
3177
|
+
version <= 0
|
|
3178
|
+
) {
|
|
3179
|
+
throw new Error(
|
|
3180
|
+
'Runtime sheet write intent did not contain its admitted version.',
|
|
3181
|
+
);
|
|
3182
|
+
}
|
|
3183
|
+
if (input.writeVersion != null && input.writeVersion !== version) {
|
|
3184
|
+
throw new Error(
|
|
3185
|
+
'Runtime sheet writeVersion disagrees with its admitted write intent.',
|
|
3186
|
+
);
|
|
3187
|
+
}
|
|
3188
|
+
return version;
|
|
3189
|
+
}
|
|
3190
|
+
|
|
3076
3191
|
function parseRuntimeCellMeta(value: unknown): Record<string, unknown> {
|
|
3077
3192
|
if (value && typeof value === 'object' && !Array.isArray(value)) {
|
|
3078
3193
|
return value as Record<string, unknown>;
|
|
@@ -6558,6 +6673,14 @@ export async function skipRuntimeWorkReceipt(
|
|
|
6558
6673
|
);
|
|
6559
6674
|
}
|
|
6560
6675
|
|
|
6676
|
+
/**
|
|
6677
|
+
* Prepare one dataset page and return its row dispositions and write version.
|
|
6678
|
+
* With stableWriteIntent, the first admission for a run/table is durable in
|
|
6679
|
+
* the same transaction as its rows; subsequent pages and wakes reuse it even
|
|
6680
|
+
* after losing all runner-local state. A new run admits a newer intent.
|
|
6681
|
+
* Gateway transport uses a named operation; an older receiver cannot silently
|
|
6682
|
+
* ignore this opt-in or trigger unsafe legacy admission.
|
|
6683
|
+
*/
|
|
6561
6684
|
export async function startRuntimeSheetDataset(
|
|
6562
6685
|
context: RuntimeApiContext,
|
|
6563
6686
|
input: {
|
|
@@ -6573,6 +6696,8 @@ export async function startRuntimeSheetDataset(
|
|
|
6573
6696
|
attemptSeq?: number | null;
|
|
6574
6697
|
attemptLeaseTtlMs?: number | null;
|
|
6575
6698
|
writeVersion?: number | null;
|
|
6699
|
+
/** Retain this run/table's first admission across pages, retries and wakes. Absence keeps legacy allocation. */
|
|
6700
|
+
stableWriteIntent?: boolean;
|
|
6576
6701
|
inputOffset?: number;
|
|
6577
6702
|
force?: boolean;
|
|
6578
6703
|
mode?: RuntimeSheetDatasetMode;
|
|
@@ -6582,7 +6707,12 @@ export async function startRuntimeSheetDataset(
|
|
|
6582
6707
|
): Promise<PrepareRuntimeSheetResult> {
|
|
6583
6708
|
if (context.dbSessionStrategy === 'gateway_only') {
|
|
6584
6709
|
return await postRuntimeApi<PrepareRuntimeSheetResult>(context, {
|
|
6585
|
-
|
|
6710
|
+
// A named operation prevents an old gateway from silently ignoring the
|
|
6711
|
+
// intent opt-in and re-admitting this run under a new version.
|
|
6712
|
+
action:
|
|
6713
|
+
input.stableWriteIntent === true
|
|
6714
|
+
? 'runtime_sheet_start_with_intent'
|
|
6715
|
+
: 'runtime_sheet_start',
|
|
6586
6716
|
input: { ...input, pendingRerunAdmission: true },
|
|
6587
6717
|
});
|
|
6588
6718
|
}
|
|
@@ -6738,10 +6868,10 @@ export async function startRuntimeSheetDataset(
|
|
|
6738
6868
|
client,
|
|
6739
6869
|
input.attemptLeaseTtlMs,
|
|
6740
6870
|
);
|
|
6741
|
-
const writeVersion = await
|
|
6871
|
+
const writeVersion = await resolveRuntimeSheetWriteVersion(
|
|
6742
6872
|
client,
|
|
6743
6873
|
session,
|
|
6744
|
-
input
|
|
6874
|
+
input,
|
|
6745
6875
|
);
|
|
6746
6876
|
const columnTypes = await RuntimeSheetColumns.prepareWrite(client, {
|
|
6747
6877
|
schema: session.postgres.schema,
|
|
@@ -7258,35 +7388,6 @@ type CompleteRuntimeMapRowChunksInput = {
|
|
|
7258
7388
|
outputFields: string[];
|
|
7259
7389
|
};
|
|
7260
7390
|
|
|
7261
|
-
/**
|
|
7262
|
-
* Why a terminal row write was rejected as stale. Runtime Sheet rows are fenced
|
|
7263
|
-
* by their schedule-time `_write_version` alone (the legacy attempt-lease
|
|
7264
|
-
* predicates are stubbed to TRUE/FALSE in sheet-attempt-sql.ts), so a stale
|
|
7265
|
-
* versioned write always means the row is owned by a different admission than
|
|
7266
|
-
* the one the writer carries:
|
|
7267
|
-
* - `newer_write_version`: a later admission (rerun, resumed attempt, or a
|
|
7268
|
-
* concurrent run of the same play) re-admitted the row after this writer
|
|
7269
|
-
* admitted it.
|
|
7270
|
-
* - `older_write_version`: the row was admitted under an older version than
|
|
7271
|
-
* the writer sent; the writer's version never admitted this row.
|
|
7272
|
-
* - `already_terminal`: an unversioned writer hit an already-enriched row.
|
|
7273
|
-
* Nothing is being overwritten, so this is the one benign reason.
|
|
7274
|
-
* - `unreported`: the gateway returned stale keys without reasons (predates
|
|
7275
|
-
* this field). Treated as superseded: every stale versioned write is.
|
|
7276
|
-
*/
|
|
7277
|
-
export type RuntimeMapRowsStaleReason =
|
|
7278
|
-
| 'newer_write_version'
|
|
7279
|
-
| 'older_write_version'
|
|
7280
|
-
| 'already_terminal'
|
|
7281
|
-
| 'unreported';
|
|
7282
|
-
|
|
7283
|
-
export type RuntimeMapRowsStaleRow = {
|
|
7284
|
-
key: string;
|
|
7285
|
-
reason: RuntimeMapRowsStaleReason;
|
|
7286
|
-
/** The admission version currently stamped on the sheet row. */
|
|
7287
|
-
rowVersionStamp: number | null;
|
|
7288
|
-
};
|
|
7289
|
-
|
|
7290
7391
|
export type RuntimeMapRowsWriteResult = {
|
|
7291
7392
|
/** Submitted row identities durably accepted, including idempotent replays. */
|
|
7292
7393
|
committedKeys: string[];
|
|
@@ -7417,58 +7518,6 @@ export function supersededRuntimeMapRows(
|
|
|
7417
7518
|
return superseded;
|
|
7418
7519
|
}
|
|
7419
7520
|
|
|
7420
|
-
/**
|
|
7421
|
-
* A terminal write batch was explicitly marked as an attempt-wide
|
|
7422
|
-
* supersession. Retained for compatibility with older terminal-write handlers
|
|
7423
|
-
* and the Context's explicit `supersededKeys` stop signal. The current
|
|
7424
|
-
* runner-app writer reports ordinary stale latest-view rows without throwing
|
|
7425
|
-
* this error.
|
|
7426
|
-
*/
|
|
7427
|
-
export class RuntimeSheetAttemptSupersededError extends Error {
|
|
7428
|
-
readonly tableNamespace: string;
|
|
7429
|
-
readonly runId: string;
|
|
7430
|
-
readonly writeVersion: number | null;
|
|
7431
|
-
readonly submittedRows: number;
|
|
7432
|
-
readonly supersededRows: RuntimeMapRowsStaleRow[];
|
|
7433
|
-
|
|
7434
|
-
constructor(input: {
|
|
7435
|
-
tableNamespace: string;
|
|
7436
|
-
runId: string;
|
|
7437
|
-
writeVersionValue: number | null;
|
|
7438
|
-
submittedRows: number;
|
|
7439
|
-
supersededRows: RuntimeMapRowsStaleRow[];
|
|
7440
|
-
}) {
|
|
7441
|
-
const reasonCounts = new Map<RuntimeMapRowsStaleReason, number>();
|
|
7442
|
-
for (const row of input.supersededRows) {
|
|
7443
|
-
reasonCounts.set(row.reason, (reasonCounts.get(row.reason) ?? 0) + 1);
|
|
7444
|
-
}
|
|
7445
|
-
const reasons = [...reasonCounts.entries()]
|
|
7446
|
-
.map(([reason, count]) => `${reason}=${count}`)
|
|
7447
|
-
.join(', ');
|
|
7448
|
-
const samples = input.supersededRows
|
|
7449
|
-
.slice(0, 5)
|
|
7450
|
-
.map(
|
|
7451
|
-
(row) =>
|
|
7452
|
-
`key=${row.key} row_write_version=${row.rowVersionStamp ?? 'unknown'}`,
|
|
7453
|
-
)
|
|
7454
|
-
.join('; ');
|
|
7455
|
-
super(
|
|
7456
|
-
`RUNTIME_SHEET_ATTEMPT_SUPERSEDED: Runtime Sheet table "${input.tableNamespace}" ` +
|
|
7457
|
-
`rejected ${input.supersededRows.length} of ${input.submittedRows} terminal row write(s) ` +
|
|
7458
|
-
`from run ${input.runId} at write version ${input.writeVersionValue ?? 'none'} ` +
|
|
7459
|
-
`because the rows are owned by a different write version (${reasons || 'unreported'}). ` +
|
|
7460
|
-
`This attempt has been superseded by a newer admission of these rows and must stop ` +
|
|
7461
|
-
`executing: nothing it persists from here on can be accepted. Sample: ${samples}.`,
|
|
7462
|
-
);
|
|
7463
|
-
this.name = 'RuntimeSheetAttemptSupersededError';
|
|
7464
|
-
this.tableNamespace = input.tableNamespace;
|
|
7465
|
-
this.runId = input.runId;
|
|
7466
|
-
this.writeVersion = input.writeVersionValue;
|
|
7467
|
-
this.submittedRows = input.submittedRows;
|
|
7468
|
-
this.supersededRows = input.supersededRows;
|
|
7469
|
-
}
|
|
7470
|
-
}
|
|
7471
|
-
|
|
7472
7521
|
export function isRuntimeSheetAttemptSupersededError(
|
|
7473
7522
|
error: unknown,
|
|
7474
7523
|
): error is RuntimeSheetAttemptSupersededError {
|
|
@@ -11,6 +11,8 @@ import type { DirectCompletedTerminalContract } from './/scheduler-backends/term
|
|
|
11
11
|
|
|
12
12
|
export type RuntimeAuthority = {
|
|
13
13
|
executorToken: string;
|
|
14
|
+
/** Narrow credential for append-only Run Ledger projection from a leased outbox. */
|
|
15
|
+
runLedgerExecutorToken: string;
|
|
14
16
|
descriptor: RuntimeAuthorityDescriptor;
|
|
15
17
|
};
|
|
16
18
|
|
|
@@ -60,13 +62,25 @@ export function deriveAsyncChildRuntimeAuthority(input: {
|
|
|
60
62
|
export async function mintPlayRunRuntimeAuthorityDescriptor(input: {
|
|
61
63
|
descriptor: RuntimeAuthorityDescriptor;
|
|
62
64
|
runtimeOrigin?: string | null;
|
|
65
|
+
/** Current immutable app receiver; absent retains legacy delivery grouping. */
|
|
66
|
+
runLedgerIngressPrefixOrigin?: string | null;
|
|
63
67
|
}): Promise<RuntimeAuthority> {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
executorToken: await mintWorkflowExecutorToken({
|
|
68
|
+
const [executorToken, runLedgerExecutorToken] = await Promise.all([
|
|
69
|
+
mintWorkflowExecutorToken({
|
|
67
70
|
...runtimeAuthorityMintInput(input.descriptor),
|
|
68
71
|
runtimeOrigin: input.runtimeOrigin,
|
|
69
72
|
}),
|
|
73
|
+
mintPlayRunAttemptRuntimeToken({
|
|
74
|
+
descriptor: input.descriptor,
|
|
75
|
+
capabilities: ['run.ledger.project'],
|
|
76
|
+
runtimeOrigin: input.runtimeOrigin,
|
|
77
|
+
runLedgerIngressPrefixOrigin: input.runLedgerIngressPrefixOrigin,
|
|
78
|
+
}),
|
|
79
|
+
]);
|
|
80
|
+
return {
|
|
81
|
+
descriptor: input.descriptor,
|
|
82
|
+
executorToken,
|
|
83
|
+
runLedgerExecutorToken,
|
|
70
84
|
};
|
|
71
85
|
}
|
|
72
86
|
|
|
@@ -87,6 +101,7 @@ export async function mintPlayRunRuntimeAuthority(input: {
|
|
|
87
101
|
/** Docflow rollout answer for the launching actor, resolved by the caller. */
|
|
88
102
|
docflowEnabled?: boolean | null;
|
|
89
103
|
runtimeOrigin?: string | null;
|
|
104
|
+
runLedgerIngressPrefixOrigin?: string | null;
|
|
90
105
|
}): Promise<RuntimeAuthority> {
|
|
91
106
|
const descriptor: RuntimeAuthorityDescriptor = {
|
|
92
107
|
orgId: input.orgId,
|
|
@@ -110,6 +125,7 @@ export async function mintPlayRunRuntimeAuthority(input: {
|
|
|
110
125
|
return await mintPlayRunRuntimeAuthorityDescriptor({
|
|
111
126
|
descriptor,
|
|
112
127
|
runtimeOrigin: input.runtimeOrigin,
|
|
128
|
+
runLedgerIngressPrefixOrigin: input.runLedgerIngressPrefixOrigin,
|
|
113
129
|
});
|
|
114
130
|
}
|
|
115
131
|
|
|
@@ -152,10 +168,12 @@ export async function mintPlayRunAttemptRuntimeToken(input: {
|
|
|
152
168
|
terminalContract?: DirectCompletedTerminalContract | null;
|
|
153
169
|
capabilities?: readonly RuntimeExecutionCapability[];
|
|
154
170
|
runtimeOrigin?: string | null;
|
|
171
|
+
runLedgerIngressPrefixOrigin?: string | null;
|
|
155
172
|
}): Promise<string> {
|
|
156
|
-
return await mintWorkflowExecutorToken(
|
|
157
|
-
runtimeAuthorityMintInput(input.descriptor, input),
|
|
158
|
-
|
|
173
|
+
return await mintWorkflowExecutorToken({
|
|
174
|
+
...runtimeAuthorityMintInput(input.descriptor, input),
|
|
175
|
+
runLedgerIngressPrefixOrigin: input.runLedgerIngressPrefixOrigin,
|
|
176
|
+
});
|
|
159
177
|
}
|
|
160
178
|
|
|
161
179
|
/**
|
|
@@ -4,6 +4,26 @@ import {
|
|
|
4
4
|
} from '@deepline/deployed-contracts';
|
|
5
5
|
import type { RuntimeExecutionCapability } from './execution-capabilities';
|
|
6
6
|
|
|
7
|
+
/** Gateway sheet admission operations retain distinct old/new semantics. */
|
|
8
|
+
export const RUNTIME_SHEET_ADMISSION_CAPABILITIES = {
|
|
9
|
+
runtime_sheet_start: 'sheet.write',
|
|
10
|
+
runtime_sheet_start_with_intent: 'sheet.write',
|
|
11
|
+
} as const satisfies Readonly<Record<string, RuntimeExecutionCapability>>;
|
|
12
|
+
|
|
13
|
+
export const RUNTIME_SHEET_ADMISSION_OPERATION_CONTRACT: DeployedOperationContract =
|
|
14
|
+
deployed.operation({
|
|
15
|
+
id: 'runtime-sheet-admission-actions',
|
|
16
|
+
actions: RUNTIME_SHEET_ADMISSION_CAPABILITIES,
|
|
17
|
+
olderReceiver: {
|
|
18
|
+
// A legacy start would mint newer intent after a wake or lost response.
|
|
19
|
+
// Refuse unsupported receivers before any row admission instead.
|
|
20
|
+
runtime_sheet_start_with_intent: {
|
|
21
|
+
kind: 'feature-unavailable',
|
|
22
|
+
code: 'RUNTIME_SHEET_WRITE_INTENT_UNAVAILABLE',
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
|
|
7
27
|
/**
|
|
8
28
|
* One declarative owner for the runtime action → authority relationship. The
|
|
9
29
|
* route still owns authentication and execution; callers can add an action in
|
|
@@ -89,3 +109,39 @@ export function runtimeOperationCapability(
|
|
|
89
109
|
] ?? null
|
|
90
110
|
);
|
|
91
111
|
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Projection credentials permit only keyed outbox deliveries, never progress
|
|
115
|
+
* producers. Each accepted action still validates its key, run scope and live
|
|
116
|
+
* lease in the receiver before writing. Ordinary executor authority keeps the
|
|
117
|
+
* established action mapping. This policy is shared by preflight and dispatch,
|
|
118
|
+
* including every action in a batch.
|
|
119
|
+
*/
|
|
120
|
+
export function runtimeOperationCapabilityForRequest(
|
|
121
|
+
body: unknown,
|
|
122
|
+
capabilities: readonly string[] | null | undefined,
|
|
123
|
+
): RuntimeExecutionCapability | null {
|
|
124
|
+
if (!body || typeof body !== 'object' || Array.isArray(body)) return null;
|
|
125
|
+
const request = body as Record<string, unknown>;
|
|
126
|
+
const action = request.action;
|
|
127
|
+
if (typeof action !== 'string') return null;
|
|
128
|
+
if (capabilities?.includes('run.ledger.project')) {
|
|
129
|
+
if (
|
|
130
|
+
capabilities.length !== 1 ||
|
|
131
|
+
![
|
|
132
|
+
'project_run_events',
|
|
133
|
+
'project_run_created',
|
|
134
|
+
'append_run_events',
|
|
135
|
+
'start_run',
|
|
136
|
+
].includes(action) ||
|
|
137
|
+
typeof request.idempotencyKey !== 'string' ||
|
|
138
|
+
!request.idempotencyKey.trim() ||
|
|
139
|
+
typeof request.deliveryLeaseOwner !== 'string' ||
|
|
140
|
+
!request.deliveryLeaseOwner.trim()
|
|
141
|
+
) {
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
return 'run.ledger.project';
|
|
145
|
+
}
|
|
146
|
+
return runtimeOperationCapability(action);
|
|
147
|
+
}
|
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
import { resolveMapRowOutcomeKey } from './map-row-outcome';
|
|
2
2
|
|
|
3
|
+
/** An older gateway cannot safely translate durable intent to legacy start. */
|
|
4
|
+
export class RuntimeSheetWriteIntentUnavailableError extends Error {
|
|
5
|
+
readonly code = 'RUNTIME_SHEET_WRITE_INTENT_UNAVAILABLE';
|
|
6
|
+
|
|
7
|
+
constructor(cause: Error) {
|
|
8
|
+
super(
|
|
9
|
+
'Runtime Sheet write intent is unavailable on this gateway. Retry after the runtime rollout.',
|
|
10
|
+
{ cause },
|
|
11
|
+
);
|
|
12
|
+
this.name = 'RuntimeSheetWriteIntentUnavailableError';
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
3
16
|
export interface RuntimeSheetBlockedRowDetail {
|
|
4
17
|
rowKey: string | null;
|
|
5
18
|
attemptId: string | null;
|
|
@@ -86,3 +99,84 @@ export class RuntimeSheetRowsBlockedError extends Error {
|
|
|
86
99
|
this.blockedRowDetails = blockedRowDetails.slice(0, 20);
|
|
87
100
|
}
|
|
88
101
|
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Why a terminal row write was rejected as stale. Runtime Sheet rows are fenced
|
|
105
|
+
* by their schedule-time `_write_version` alone (the legacy attempt-lease
|
|
106
|
+
* predicates are stubbed to TRUE/FALSE in sheet-attempt-sql.ts), so a stale
|
|
107
|
+
* versioned write always means the row is owned by a different admission than
|
|
108
|
+
* the one the writer carries:
|
|
109
|
+
* - `newer_write_version`: a later admission (a new run, or a legacy caller
|
|
110
|
+
* that allocated again on resume) re-admitted the row after this writer
|
|
111
|
+
* admitted it. Stable-intent callers retain their version through wakes.
|
|
112
|
+
* - `older_write_version`: the row was admitted under an older version than
|
|
113
|
+
* the writer sent; the writer's version never admitted this row.
|
|
114
|
+
* - `already_terminal`: an unversioned writer hit an already-enriched row.
|
|
115
|
+
* Nothing is being overwritten, so this is the one benign reason.
|
|
116
|
+
* - `unreported`: the gateway returned stale keys without reasons (predates
|
|
117
|
+
* this field). Treated as superseded: every stale versioned write is.
|
|
118
|
+
*/
|
|
119
|
+
export type RuntimeMapRowsStaleReason =
|
|
120
|
+
| 'newer_write_version'
|
|
121
|
+
| 'older_write_version'
|
|
122
|
+
| 'already_terminal'
|
|
123
|
+
| 'unreported';
|
|
124
|
+
|
|
125
|
+
export type RuntimeMapRowsStaleRow = {
|
|
126
|
+
key: string;
|
|
127
|
+
reason: RuntimeMapRowsStaleReason;
|
|
128
|
+
/** The admission version currently stamped on the sheet row. */
|
|
129
|
+
rowVersionStamp: number | null;
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* A terminal write batch was explicitly marked as an attempt-wide
|
|
134
|
+
* supersession. Retained for compatibility with older terminal-write handlers
|
|
135
|
+
* and the Context's explicit `supersededKeys` stop signal. The current
|
|
136
|
+
* runner-app writer reports ordinary stale latest-view rows without throwing
|
|
137
|
+
* this error.
|
|
138
|
+
*/
|
|
139
|
+
export class RuntimeSheetAttemptSupersededError extends Error {
|
|
140
|
+
readonly tableNamespace: string;
|
|
141
|
+
readonly runId: string;
|
|
142
|
+
readonly writeVersion: number | null;
|
|
143
|
+
readonly submittedRows: number;
|
|
144
|
+
readonly supersededRows: RuntimeMapRowsStaleRow[];
|
|
145
|
+
|
|
146
|
+
constructor(input: {
|
|
147
|
+
tableNamespace: string;
|
|
148
|
+
runId: string;
|
|
149
|
+
writeVersionValue: number | null;
|
|
150
|
+
submittedRows: number;
|
|
151
|
+
supersededRows: RuntimeMapRowsStaleRow[];
|
|
152
|
+
}) {
|
|
153
|
+
const reasonCounts = new Map<RuntimeMapRowsStaleReason, number>();
|
|
154
|
+
for (const row of input.supersededRows) {
|
|
155
|
+
reasonCounts.set(row.reason, (reasonCounts.get(row.reason) ?? 0) + 1);
|
|
156
|
+
}
|
|
157
|
+
const reasons = [...reasonCounts.entries()]
|
|
158
|
+
.map(([reason, count]) => `${reason}=${count}`)
|
|
159
|
+
.join(', ');
|
|
160
|
+
const samples = input.supersededRows
|
|
161
|
+
.slice(0, 5)
|
|
162
|
+
.map(
|
|
163
|
+
(row) =>
|
|
164
|
+
`key=${row.key} row_write_version=${row.rowVersionStamp ?? 'unknown'}`,
|
|
165
|
+
)
|
|
166
|
+
.join('; ');
|
|
167
|
+
super(
|
|
168
|
+
`RUNTIME_SHEET_ATTEMPT_SUPERSEDED: Runtime Sheet table "${input.tableNamespace}" ` +
|
|
169
|
+
`rejected ${input.supersededRows.length} of ${input.submittedRows} terminal row write(s) ` +
|
|
170
|
+
`from run ${input.runId} at write version ${input.writeVersionValue ?? 'none'} ` +
|
|
171
|
+
`because the rows are owned by a different write version (${reasons || 'unreported'}). ` +
|
|
172
|
+
`This attempt has been superseded by a newer admission of these rows and must stop ` +
|
|
173
|
+
`executing: nothing it persists from here on can be accepted. Sample: ${samples}.`,
|
|
174
|
+
);
|
|
175
|
+
this.name = 'RuntimeSheetAttemptSupersededError';
|
|
176
|
+
this.tableNamespace = input.tableNamespace;
|
|
177
|
+
this.runId = input.runId;
|
|
178
|
+
this.writeVersion = input.writeVersionValue;
|
|
179
|
+
this.submittedRows = input.submittedRows;
|
|
180
|
+
this.supersededRows = input.supersededRows;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
@@ -149,6 +149,8 @@ export type PlaySchedulerSubmitInput = RetainedPipelineCarrier & {
|
|
|
149
149
|
*/
|
|
150
150
|
preloadedDbSessionUnwrapKey?: string | null;
|
|
151
151
|
executorToken: string;
|
|
152
|
+
/** Optional run.progress-only authority minted at admission for ledger projection. */
|
|
153
|
+
runLedgerExecutorToken?: string | null;
|
|
152
154
|
/** Immutable facts used by durable schedulers to mint a fresh leg token. */
|
|
153
155
|
runtimeAuthority: RuntimeAuthorityDescriptor;
|
|
154
156
|
/**
|
|
@@ -588,8 +588,11 @@ const absurdReadyPromises = new Map<string, Promise<void>>();
|
|
|
588
588
|
/**
|
|
589
589
|
* Verify, once per process (keyed by pool url + schema), the deployment-owned
|
|
590
590
|
* Absurd schema contract and provision the shared queue with its policies.
|
|
591
|
-
*
|
|
592
|
-
*
|
|
591
|
+
* Worker startup owns hosted release queues; ordinary Vercel admission never
|
|
592
|
+
* calls this maintenance path. Local callers may prepare a queue lazily, and
|
|
593
|
+
* historic task recovery may prepare the run's original lane.
|
|
594
|
+
* Schema DDL belongs exclusively to the migration gate: startup or recovery
|
|
595
|
+
* may read this contract, but may never take the global bootstrap
|
|
593
596
|
* lock. The memoized promise is shared; a failure evicts the cache so the next
|
|
594
597
|
* caller retries loudly.
|
|
595
598
|
*/
|
|
@@ -9,10 +9,9 @@
|
|
|
9
9
|
* modules.
|
|
10
10
|
*
|
|
11
11
|
* Lifecycle:
|
|
12
|
-
* submit →
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* on the run row so a later cancel can target it.
|
|
12
|
+
* submit → atomically insert launch row and spawn its absurd task on the
|
|
13
|
+
* release queue prepared by worker startup. Non-Vercel callers
|
|
14
|
+
* retain lazy queue setup for local app-before-worker startup.
|
|
16
15
|
* observe/result → reuse the postgres LISTEN/NOTIFY run handle.
|
|
17
16
|
* cancel → commit the Absurd stop and a durable cancellation request;
|
|
18
17
|
* the worker deletes sandboxes before the final run write.
|
|
@@ -419,13 +418,21 @@ export function createAbsurdSchedulerBackend(
|
|
|
419
418
|
queueDepth: permit.queueDepth,
|
|
420
419
|
waitMs: permit.waitMs,
|
|
421
420
|
});
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
421
|
+
// Vercel only admits work. The release worker prepares its Absurd
|
|
422
|
+
// queue before it reports ready; repeating schema checks, queue
|
|
423
|
+
// inventory, cutover cleanup, and queue-policy writes in each cold
|
|
424
|
+
// admission isolate adds database round trips to the user's launch
|
|
425
|
+
// path. If the worker has not prepared the queue, the atomic submit
|
|
426
|
+
// below fails loudly and a webhook receipt remains retryable.
|
|
427
|
+
if (!process.env.VERCEL?.trim()) {
|
|
428
|
+
await ensureAbsurdRuntimeReady(
|
|
429
|
+
poolOptions,
|
|
430
|
+
normalizedSchedulerOptions,
|
|
431
|
+
queueSuffix,
|
|
432
|
+
releaseId,
|
|
433
|
+
);
|
|
434
|
+
recordAbsurdSubmitPhase(input, 'schema_ready', submitStartedAt);
|
|
435
|
+
}
|
|
429
436
|
|
|
430
437
|
// Loud, structured submit log: the #1 way an absurd run silently hangs
|
|
431
438
|
// is an app→worker queue-name mismatch (the shared preview app
|
|
@@ -480,6 +487,8 @@ export function createAbsurdSchedulerBackend(
|
|
|
480
487
|
spawn = await withRuntimeSchedulerSubmitAdmission(
|
|
481
488
|
admissionParams,
|
|
482
489
|
async () => {
|
|
490
|
+
// Historic launches may outlive a physically reclaimed queue.
|
|
491
|
+
// Recovery retains its original-lane preparation on every host.
|
|
483
492
|
await ensureAbsurdRuntimeReady(
|
|
484
493
|
poolOptions,
|
|
485
494
|
normalizedSchedulerOptions,
|