deepline 0.3.409 → 0.3.411
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/agent-runtime.ts +18 -1
- package/dist/bundling-sources/sdk/src/client.ts +206 -333
- package/dist/bundling-sources/sdk/src/compat.ts +45 -2
- package/dist/bundling-sources/sdk/src/db/query.ts +9 -10
- package/dist/bundling-sources/sdk/src/http.ts +38 -20
- package/dist/bundling-sources/sdk/src/index.ts +4 -5
- package/dist/bundling-sources/sdk/src/play.ts +10 -10
- package/dist/bundling-sources/sdk/src/plays/bundle-play-file.ts +6 -4
- package/dist/bundling-sources/sdk/src/plays/check-local-play-graph.ts +114 -0
- package/dist/bundling-sources/sdk/src/plays/client.ts +431 -0
- package/dist/bundling-sources/sdk/src/plays/local-play-execution.ts +2 -2
- package/dist/bundling-sources/sdk/src/plays/run-request.ts +106 -16
- package/dist/bundling-sources/sdk/src/release.ts +13 -7
- package/dist/bundling-sources/sdk/src/runs/read-errors.ts +8 -0
- package/dist/bundling-sources/sdk/src/runs/watch-polling.ts +124 -13
- package/dist/bundling-sources/sdk/src/tool-calls.ts +108 -19
- package/dist/bundling-sources/sdk/src/types.ts +18 -0
- package/dist/bundling-sources/shared_libs/integration-contracts/execute-retry-contract.ts +37 -0
- package/dist/bundling-sources/shared_libs/integration-contracts/package.json +3 -0
- package/dist/bundling-sources/shared_libs/monitors/package.json +1 -1
- package/dist/bundling-sources/shared_libs/play-data-plane/r2.ts +3 -1
- package/dist/bundling-sources/shared_libs/play-runtime/async-operation.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/context.ts +277 -76
- package/dist/bundling-sources/shared_libs/play-runtime/ctx-types.ts +6 -0
- package/dist/bundling-sources/shared_libs/play-runtime/dataset-row-input.ts +124 -0
- package/dist/bundling-sources/shared_libs/play-runtime/durable-call-cache.ts +6 -62
- package/dist/bundling-sources/shared_libs/play-runtime/durable-receipt-execution.ts +1 -0
- package/dist/bundling-sources/shared_libs/play-runtime/durable-tool-identity.ts +67 -0
- package/dist/bundling-sources/shared_libs/play-runtime/execute-server-timing.ts +64 -6
- package/dist/bundling-sources/shared_libs/play-runtime/freshness-receipt-execution.ts +1 -5
- package/dist/bundling-sources/shared_libs/play-runtime/ledger-safe-payload.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/play-artifact-runtime-contract.ts +3 -0
- package/dist/bundling-sources/shared_libs/play-runtime/play-http-request.ts +10 -0
- package/dist/bundling-sources/shared_libs/play-runtime/query-result-dataset.ts +3 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/egress-probe.ts +3 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/index.ts +26 -16
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-heartbeat.ts +36 -11
- package/dist/bundling-sources/shared_libs/play-runtime/runner-app/runtime-terminal-push.ts +35 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-launch-transport.ts +21 -0
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-payload-transport.ts +21 -6
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona-session-execution.ts +11 -2
- package/dist/bundling-sources/shared_libs/play-runtime/runner-backends/backends/daytona.ts +85 -20
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +71 -13
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-execution-queries.ts +100 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-pool.ts +9 -5
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +337 -146
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-shared.ts +26 -12
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-rate-state.ts +3 -1
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +425 -102
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-dispatch-authority.ts +4 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-outbox-recovery.ts +4 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-event-search.ts +9 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-sandbox-capacity.ts +181 -124
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-worker-wake.ts +152 -0
- package/dist/bundling-sources/shared_libs/play-runtime/test-runtime-seams.ts +5 -3
- package/dist/bundling-sources/shared_libs/play-runtime/tool-cache-policy.ts +31 -0
- package/dist/bundling-sources/shared_libs/play-runtime/transient-service-error.ts +10 -0
- package/dist/bundling-sources/shared_libs/plays/ambiguous-write-error.ts +25 -0
- package/dist/bundling-sources/shared_libs/plays/artifact-types.ts +4 -0
- package/dist/bundling-sources/shared_libs/plays/authoring-contract.ts +63 -68
- package/dist/bundling-sources/shared_libs/plays/bundling/index.ts +129 -63
- package/dist/bundling-sources/shared_libs/plays/contracts.ts +14 -0
- package/dist/bundling-sources/shared_libs/plays/enrich-play-compiler.ts +58 -16
- package/dist/bundling-sources/shared_libs/plays/fetch-http-error.ts +50 -0
- package/dist/bundling-sources/shared_libs/plays/source-authoring-edition.ts +351 -0
- package/dist/bundling-sources/shared_libs/plays/tool-list-getter-mode.ts +9 -0
- package/dist/bundling-sources/shared_libs/plays/tool-result-types.ts +1 -1
- package/dist/cli/auth-M7TBLW55.js +40 -0
- package/dist/cli/{auth-5HIIACF7.mjs → auth-YD6ZTMB2.mjs} +6 -6
- package/dist/cli/{billing-4275N7FL.js → billing-2L3MOB42.js} +84 -84
- package/dist/cli/{billing-EVZ3ZWKC.mjs → billing-ZT46GV4C.mjs} +8 -8
- package/dist/cli/{chunk-ZAAKSJAS.js → chunk-27GJKC5Q.js} +17 -10
- package/dist/cli/{chunk-UHNDVD3P.js → chunk-2H4EY7KH.js} +100 -41
- package/dist/cli/{chunk-GAICVLKL.js → chunk-2NI6DHN7.js} +2 -2
- package/dist/cli/{chunk-JGHG4NBA.js → chunk-2WUY3VNK.js} +19 -4
- package/dist/cli/{chunk-FHPCKULR.mjs → chunk-4BA6ATHA.mjs} +2 -2
- package/dist/cli/{chunk-RTCDW2GU.js → chunk-4O4WNFFC.js} +170 -49
- package/dist/cli/{chunk-OSDXE27V.mjs → chunk-4PG4ARL2.mjs} +17 -10
- package/dist/cli/{chunk-AU4OFDFX.js → chunk-5IGDNBG7.js} +26 -26
- package/dist/cli/{chunk-WYQO2CBS.mjs → chunk-5LRWWMRV.mjs} +149 -28
- package/dist/cli/{chunk-PMVFAYL7.mjs → chunk-63ILLN5H.mjs} +2 -2
- package/dist/cli/chunk-6AUE6JXY.js +35 -0
- package/dist/cli/chunk-7DSMMCXP.js +501 -0
- package/dist/cli/{chunk-6BJK4EJ3.mjs → chunk-AARWVK4C.mjs} +2132 -65
- package/dist/cli/{chunk-FERRDNMO.js → chunk-AD47BXN2.js} +5 -5
- package/dist/cli/{chunk-J6DCKJNM.mjs → chunk-BJV3VSKE.mjs} +16 -1
- package/dist/cli/{chunk-S6R3OX7B.js → chunk-E4CABWXL.js} +25 -2
- package/dist/cli/{chunk-NXGCO4JB.mjs → chunk-E4IXDAZI.mjs} +5 -0
- package/dist/cli/{chunk-BEVLCKXG.mjs → chunk-E4KBNNNB.mjs} +1 -1
- package/dist/cli/{chunk-2PRO2JTX.mjs → chunk-E52TKKVI.mjs} +36 -284
- package/dist/cli/chunk-FR2ILQ4G.mjs +8 -0
- package/dist/cli/{chunk-2GI3QD3L.js → chunk-FRVPOXGB.js} +644 -330
- package/dist/cli/chunk-G43JLBDE.mjs +501 -0
- package/dist/cli/{chunk-BZAMOCPA.mjs → chunk-IMZ56EOH.mjs} +3 -3
- package/dist/cli/chunk-IPGV6VFA.mjs +6084 -0
- package/dist/cli/{chunk-IT3XBJQR.mjs → chunk-IR3AKJAY.mjs} +330 -625
- package/dist/cli/chunk-J33TSWO5.js +8 -0
- package/dist/cli/chunk-JQMZUWNM.mjs +35 -0
- package/dist/cli/chunk-JYHSEGRM.js +6084 -0
- package/dist/cli/{chunk-JI2B4RZP.mjs → chunk-KCC3FKIW.mjs} +71 -12
- package/dist/cli/{chunk-6IKARAYD.mjs → chunk-L2VKAASU.mjs} +23 -0
- package/dist/cli/{chunk-O3VSXP2F.js → chunk-LWBM5FFL.js} +50 -50
- package/dist/cli/{chunk-VWBTTJYQ.mjs → chunk-M6OASCVL.mjs} +6 -3
- package/dist/cli/{chunk-YHPYUZZX.mjs → chunk-MAMVGOSC.mjs} +1 -1
- package/dist/cli/{chunk-Q2E4E4FJ.js → chunk-NPBJI7RE.js} +8 -8
- package/dist/cli/chunk-NQWIZ5PZ.js +313 -0
- package/dist/cli/{chunk-HQXL5526.mjs → chunk-NUX2QHNC.mjs} +1 -1
- package/dist/cli/{chunk-TQNHMWUR.mjs → chunk-OGSXENOF.mjs} +5 -2
- package/dist/cli/{chunk-SEFMGO3Z.js → chunk-OQQOXSYA.js} +2184 -117
- package/dist/cli/{chunk-FJCIUF34.js → chunk-OZSC6CEW.js} +128 -376
- package/dist/cli/{chunk-NZSF57UO.mjs → chunk-PO2VU6WV.mjs} +2 -2
- package/dist/cli/{chunk-7P5AA3SN.js → chunk-PPDBRJRW.js} +6 -1
- package/dist/cli/{chunk-ILHRA7AD.js → chunk-QADCFSGH.js} +7 -7
- package/dist/cli/{chunk-N44JHMKY.mjs → chunk-RFES6Q2J.mjs} +452 -138
- package/dist/cli/{chunk-DEC3JECC.js → chunk-RMINBDYY.js} +5 -2
- package/dist/cli/{chunk-WLOCMJWV.js → chunk-TPFD4F5S.js} +426 -721
- package/dist/cli/{chunk-V76R6HMV.js → chunk-U5AQKE3T.js} +1029 -806
- package/dist/cli/{chunk-PBZYY7VZ.mjs → chunk-UAEVKAUR.mjs} +734 -511
- package/dist/cli/{chunk-WHG43Z67.js → chunk-VGHWJL4W.js} +11 -8
- package/dist/cli/chunk-VKKVSFRD.js +62 -0
- package/dist/cli/{chunk-GSK6NHVM.js → chunk-WU4U6VSB.js} +5 -5
- package/dist/cli/chunk-XAB47ZRV.mjs +313 -0
- package/dist/cli/{chunk-JRAVVJ3T.mjs → chunk-XJD6LZCO.mjs} +2 -2
- package/dist/cli/chunk-ZCALLYF6.mjs +62 -0
- package/dist/cli/{chunk-YD7B53RW.js → chunk-ZHWBU36H.js} +12 -12
- package/dist/cli/{csv-A2MP6EFV.mjs → csv-BKNRRW7D.mjs} +5 -5
- package/dist/cli/{csv-BBOTCGQY.js → csv-SVDP2EU7.js} +14 -14
- package/dist/cli/{db-3W5DMTUX.mjs → db-LU4KLRM6.mjs} +15 -20
- package/dist/cli/{db-G4CODDCA.js → db-OQ6S7TTZ.js} +42 -47
- package/dist/cli/{describe-PQTQ5B6F.js → describe-45TGETKR.js} +27 -22
- package/dist/cli/{describe-XYJ2ZT4M.mjs → describe-U4KOGDRA.mjs} +20 -15
- package/dist/cli/describe-core.d.mts +2 -2
- package/dist/cli/describe-core.d.ts +2 -2
- package/dist/cli/describe-core.js +6 -6
- package/dist/cli/describe-core.mjs +5 -5
- package/dist/cli/{executions-UR67CA5H.mjs → executions-2GAAUXLA.mjs} +8 -8
- package/dist/cli/{executions-TLANVR7Y.js → executions-VZN56VRC.js} +10 -10
- package/dist/cli/{feedback-6C2YTRJL.js → feedback-NS76B5GU.js} +13 -9
- package/dist/cli/{feedback-WHCMGEIL.mjs → feedback-XW5IWA5R.mjs} +11 -7
- package/dist/cli/{git-GWLB6VSA.mjs → git-CLI66XP6.mjs} +6 -6
- package/dist/cli/git-VGYRGFEN.js +24 -0
- package/dist/cli/index.js +236 -348
- package/dist/cli/index.mjs +162 -274
- package/dist/cli/{legacy-noops-ZUFA7RWI.js → legacy-noops-HCFB3ZOV.js} +9 -9
- package/dist/cli/{legacy-noops-KF4XIFEF.mjs → legacy-noops-ODDOMLBL.mjs} +6 -6
- package/dist/cli/{monitors-TB3K2IVE.js → monitors-7WXQ7JFT.js} +94 -94
- package/dist/cli/{monitors-6UOIDIMB.mjs → monitors-ZXX456TE.mjs} +8 -8
- package/dist/cli/{org-CKWMBPIR.js → org-YLX5PHBQ.js} +68 -68
- package/dist/cli/{org-WGHHMVDZ.mjs → org-YUN3TLNP.mjs} +8 -8
- package/dist/cli/{play-LYPAXCLD.mjs → play-LL73A7EP.mjs} +533 -98
- package/dist/cli/{play-N2B3KAVS.js → play-YGOXL52D.js} +1067 -632
- package/dist/cli/{providers-6DI5BVZJ.mjs → providers-35QSAUHL.mjs} +8 -8
- package/dist/cli/{providers-UR42MD6Z.js → providers-RHCIU2PX.js} +11 -11
- package/dist/cli/{quickstart-MNA2S6PO.mjs → quickstart-6BN3LCZH.mjs} +5 -5
- package/dist/cli/{quickstart-FCJG4XGB.js → quickstart-ORMM4NRK.js} +7 -7
- package/dist/cli/search-EWDMUPHR.js +30 -0
- package/dist/cli/{search-VPPYUJ2M.mjs → search-GAERWLSE.mjs} +9 -9
- package/dist/cli/{secrets-QOSMVO36.js → secrets-3AFCTGT7.js} +17 -17
- package/dist/cli/{secrets-DRI4W7Z5.mjs → secrets-FCL5PALY.mjs} +8 -8
- package/dist/cli/sessions-3OEHEQG7.js +16 -0
- package/dist/cli/{sessions-DQNUKP43.mjs → sessions-RSSL7I7O.mjs} +6 -6
- package/dist/cli/{settings-DWDK3Y2R.mjs → settings-GE4NRE7Y.mjs} +12 -12
- package/dist/cli/{settings-JUGGCOPS.js → settings-RX5K4I7H.js} +79 -79
- package/dist/cli/{setup-AWBHNYXK.js → setup-N3ZNAEL5.js} +45 -44
- package/dist/cli/{setup-D5DWVNY4.mjs → setup-X3RXGG4F.mjs} +11 -10
- package/dist/cli/{skills-YV2XR35J.mjs → skills-5JEAJBDE.mjs} +7 -7
- package/dist/cli/skills-VAAQVEQC.js +29 -0
- package/dist/cli/tools-BYYOT2DU.js +44 -0
- package/dist/cli/{tools-VFJYHNV2.mjs → tools-JOKUWEBZ.mjs} +19 -14
- package/dist/cli/update-36G4ZD7B.js +31 -0
- package/dist/cli/{update-IM6VOTGL.mjs → update-UBHEVFR3.mjs} +11 -9
- package/dist/cli/{workflow-26URBWPV.mjs → workflow-FR6EXAXF.mjs} +44 -20
- package/dist/cli/{workflow-3BS6U6SL.js → workflow-SZAVOHN6.js} +54 -30
- package/dist/{client-BfInrZPB.d.mts → client-74k4IPh6.d.mts} +135 -54
- package/dist/{client-BMjJFpan.d.ts → client-C1IK1f8c.d.ts} +135 -54
- package/dist/{compiler-manifest-Ycx-hoAr.d.mts → compiler-manifest-lzWpbV3w.d.mts} +83 -66
- package/dist/{compiler-manifest-Ycx-hoAr.d.ts → compiler-manifest-lzWpbV3w.d.ts} +83 -66
- package/dist/{index-CZXgiN3E.d.mts → index-C8Cy-YTm.d.ts} +5 -1
- package/dist/{index-NPG5pqxQ.d.ts → index-CtNK-0nI.d.mts} +5 -1
- package/dist/index.d.mts +47 -9
- package/dist/index.d.ts +47 -9
- package/dist/index.js +17 -14
- package/dist/index.mjs +13 -10
- package/dist/install-integrity.json +118 -102
- package/dist/plays/bundle-play-file.d.mts +3 -3
- package/dist/plays/bundle-play-file.d.ts +3 -3
- package/dist/plays/bundle-play-file.mjs +5 -4
- package/dist/plays/csv-data-input.js +3 -3
- package/dist/plays/csv-data-input.mjs +2 -2
- package/dist/plays/play-description.d.mts +2 -2
- package/dist/plays/play-description.d.ts +2 -2
- package/dist/plays/run-request.d.mts +2 -2
- package/dist/plays/run-request.d.ts +2 -2
- package/dist/plays/run-request.js +11 -3
- package/dist/plays/run-request.mjs +10 -2
- package/dist/release.d.mts +15 -6
- package/dist/release.d.ts +15 -6
- package/dist/release.js +2 -2
- package/dist/release.mjs +1 -1
- package/package.json +2 -2
- package/dist/cli/auth-F6BX32XZ.js +0 -40
- package/dist/cli/chunk-264PC2RN.mjs +0 -83
- package/dist/cli/chunk-44ZTYHMQ.mjs +0 -155
- package/dist/cli/chunk-53HN7WZN.js +0 -392
- package/dist/cli/chunk-7AALNGTA.mjs +0 -392
- package/dist/cli/chunk-ALD4COBH.js +0 -155
- package/dist/cli/chunk-CLJGSOVM.mjs +0 -1716
- package/dist/cli/chunk-WNUR6VP5.js +0 -83
- package/dist/cli/chunk-Z4VNJOF7.js +0 -1716
- package/dist/cli/git-VQFF6D7C.js +0 -24
- package/dist/cli/search-NCEEONMQ.js +0 -30
- package/dist/cli/sessions-3WYKQABW.js +0 -16
- package/dist/cli/skills-AKPAJVSO.js +0 -29
- package/dist/cli/tools-RBKEK6PM.js +0 -39
- package/dist/cli/update-VFNUBLDA.js +0 -29
|
@@ -289,6 +289,7 @@ const POSTGRES_SCHEDULER_SCHEMA_INIT_ADVISORY_LOCK_NAMESPACE = 0x44505349;
|
|
|
289
289
|
const POSTGRES_SCHEDULER_SCHEMA_INIT_ADVISORY_LOCK_SEED =
|
|
290
290
|
'deepline:runtime-scheduler:schema-init:v1';
|
|
291
291
|
const POSTGRES_SCHEDULER_RELEASE_ADMISSION_LOCK_NAMESPACE = 0x44505241;
|
|
292
|
+
const POSTGRES_SCHEDULER_ADMISSION_LOCK_TIMEOUT_MS = 5_000;
|
|
292
293
|
const POSTGRES_SCHEDULER_SCHEMA_INIT_STATEMENT_TIMEOUT_MS = 60_000;
|
|
293
294
|
/**
|
|
294
295
|
* Every new scheduler DDL migration must bump this version. Runtime callers
|
|
@@ -4707,6 +4708,7 @@ function absurdSchemaInitAdvisoryLockKey(): readonly [number, number] {
|
|
|
4707
4708
|
*/
|
|
4708
4709
|
export async function ensureAbsurdSchema(
|
|
4709
4710
|
client: PostgresSchedulerQueryClient,
|
|
4711
|
+
options: { refreshClaimBody?: boolean } = {},
|
|
4710
4712
|
): Promise<void> {
|
|
4711
4713
|
const [lockClassId, lockObjectId] = absurdSchemaInitAdvisoryLockKey();
|
|
4712
4714
|
let stage = 'begin transaction';
|
|
@@ -4760,9 +4762,28 @@ export async function ensureAbsurdSchema(
|
|
|
4760
4762
|
`SELECT absurd.deepline_no_scheduler_org_cap_compatibility_version() AS v`,
|
|
4761
4763
|
)
|
|
4762
4764
|
: null;
|
|
4765
|
+
// Only the explicit deployment migration reconciles equivalent bodies.
|
|
4766
|
+
// Runtime readiness keeps the same ABI marker and remains read-only.
|
|
4767
|
+
let claimBodyCurrent = true;
|
|
4768
|
+
if (options.refreshClaimBody) {
|
|
4769
|
+
stage = 'compare Absurd claim function body';
|
|
4770
|
+
const sql = readAbsurdSchemaNoSchedulerOrgCapCompatibilitySql();
|
|
4771
|
+
const start = sql.indexOf('as $$');
|
|
4772
|
+
const end = sql.lastIndexOf('$$');
|
|
4773
|
+
if (start < 0 || end <= start) {
|
|
4774
|
+
throw new Error('Absurd claim body delimiters are malformed.');
|
|
4775
|
+
}
|
|
4776
|
+
const body = await client.query<{ current: boolean }>(
|
|
4777
|
+
`SELECT prosrc = $1::text AS current FROM pg_proc
|
|
4778
|
+
WHERE oid = to_regprocedure('absurd.claim_task(text,text,integer,integer)')`,
|
|
4779
|
+
[sql.slice(start + 'as $$'.length, end)],
|
|
4780
|
+
);
|
|
4781
|
+
claimBodyCurrent = body.rows[0]?.current === true;
|
|
4782
|
+
}
|
|
4763
4783
|
if (
|
|
4784
|
+
!claimBodyCurrent ||
|
|
4764
4785
|
markerVersion?.rows[0]?.v !==
|
|
4765
|
-
|
|
4786
|
+
ABSURD_NO_SCHEDULER_ORG_CAP_COMPATIBILITY_VERSION
|
|
4766
4787
|
) {
|
|
4767
4788
|
stage = 'apply Absurd no-org-cap compatibility function patch';
|
|
4768
4789
|
await client.query(
|
|
@@ -5147,7 +5168,17 @@ async function submitPostgresSchedulerRunTransaction(
|
|
|
5147
5168
|
existing_launch_json: unknown | null;
|
|
5148
5169
|
}>(
|
|
5149
5170
|
`
|
|
5150
|
-
WITH
|
|
5171
|
+
WITH admission_lock_timeout AS MATERIALIZED (
|
|
5172
|
+
-- This single-statement admission can wait on run, release, or row
|
|
5173
|
+
-- locks. Bound that wait inside the same implicit transaction; the
|
|
5174
|
+
-- dependency below applies it before acquiring the first lock, and
|
|
5175
|
+
-- transaction-local scope cannot leak through PgBouncer.
|
|
5176
|
+
SELECT set_config(
|
|
5177
|
+
'lock_timeout',
|
|
5178
|
+
'${POSTGRES_SCHEDULER_ADMISSION_LOCK_TIMEOUT_MS}ms',
|
|
5179
|
+
true
|
|
5180
|
+
)
|
|
5181
|
+
), run_lock AS MATERIALIZED (
|
|
5151
5182
|
-- A run id is a global job key, not a release-local key. Serialize it
|
|
5152
5183
|
-- before inspecting the runs table so two app releases cannot each
|
|
5153
5184
|
-- spawn the
|
|
@@ -5158,6 +5189,7 @@ async function submitPostgresSchedulerRunTransaction(
|
|
|
5158
5189
|
'run:' || $1::text
|
|
5159
5190
|
)
|
|
5160
5191
|
)
|
|
5192
|
+
FROM admission_lock_timeout
|
|
5161
5193
|
), admission_lock AS (
|
|
5162
5194
|
SELECT pg_advisory_xact_lock_shared(
|
|
5163
5195
|
${POSTGRES_SCHEDULER_RELEASE_ADMISSION_LOCK_NAMESPACE},
|
|
@@ -7082,33 +7114,23 @@ export type PostgresSchedulerRunLaneState = {
|
|
|
7082
7114
|
laneClaiming: boolean;
|
|
7083
7115
|
};
|
|
7084
7116
|
|
|
7085
|
-
|
|
7086
|
-
|
|
7087
|
-
|
|
7088
|
-
|
|
7089
|
-
|
|
7090
|
-
|
|
7091
|
-
|
|
7092
|
-
|
|
7093
|
-
|
|
7094
|
-
|
|
7095
|
-
|
|
7096
|
-
input: { runId: string },
|
|
7117
|
+
type RunLaneStateRow = {
|
|
7118
|
+
release_id: string | null;
|
|
7119
|
+
environment: string;
|
|
7120
|
+
status: string;
|
|
7121
|
+
wait_kind: string | null;
|
|
7122
|
+
parked: boolean;
|
|
7123
|
+
lane_claiming: boolean | null;
|
|
7124
|
+
};
|
|
7125
|
+
|
|
7126
|
+
/** The lane prefix is bound as $2 by both readers of this projection. */
|
|
7127
|
+
function runLaneStateSelectionSql(
|
|
7097
7128
|
options?: Pick<PostgresSchedulerOptions, 'schema'>,
|
|
7098
|
-
):
|
|
7129
|
+
): string {
|
|
7099
7130
|
const adoptableKinds = POSTGRES_SCHEDULER_ADOPTABLE_WAIT_KINDS.map(
|
|
7100
7131
|
(kind) => `'${kind}'`,
|
|
7101
7132
|
).join(', ');
|
|
7102
|
-
|
|
7103
|
-
release_id: string | null;
|
|
7104
|
-
environment: string;
|
|
7105
|
-
status: string;
|
|
7106
|
-
wait_kind: string | null;
|
|
7107
|
-
parked: boolean;
|
|
7108
|
-
lane_claiming: boolean | null;
|
|
7109
|
-
}>(
|
|
7110
|
-
`
|
|
7111
|
-
SELECT
|
|
7133
|
+
return `
|
|
7112
7134
|
nullif(btrim(runs.launch_json ->> 'absurdReleaseId'), '') AS release_id,
|
|
7113
7135
|
coalesce(
|
|
7114
7136
|
nullif(btrim(runs.launch_json ->> 'absurdReleaseEnvironment'), ''),
|
|
@@ -7141,14 +7163,12 @@ export async function readPostgresSchedulerRunLaneState(
|
|
|
7141
7163
|
)
|
|
7142
7164
|
|| ':'
|
|
7143
7165
|
|| nullif(btrim(runs.launch_json ->> 'absurdReleaseId'), '')
|
|
7144
|
-
) AS lane_claiming
|
|
7145
|
-
|
|
7146
|
-
|
|
7147
|
-
|
|
7148
|
-
|
|
7149
|
-
|
|
7150
|
-
const row = result.rows[0];
|
|
7151
|
-
if (!row) return null;
|
|
7166
|
+
) AS lane_claiming`;
|
|
7167
|
+
}
|
|
7168
|
+
|
|
7169
|
+
function runLaneStateFromRow(
|
|
7170
|
+
row: RunLaneStateRow,
|
|
7171
|
+
): PostgresSchedulerRunLaneState {
|
|
7152
7172
|
return {
|
|
7153
7173
|
releaseId: row.release_id,
|
|
7154
7174
|
environment: row.environment === 'preview' ? 'preview' : 'production',
|
|
@@ -7159,6 +7179,32 @@ export async function readPostgresSchedulerRunLaneState(
|
|
|
7159
7179
|
};
|
|
7160
7180
|
}
|
|
7161
7181
|
|
|
7182
|
+
/**
|
|
7183
|
+
* One transactional read of everything the lane guard needs about a claimed
|
|
7184
|
+
* run: which lane owns it, whether that lane still claims, and whether the run
|
|
7185
|
+
* is parked in a wait a newer lane may adopt.
|
|
7186
|
+
*
|
|
7187
|
+
* The scheduler run row — not the engine task row — is the authority on "parked
|
|
7188
|
+
* in a durable wait". The engine cannot tell a durable suspension from a retry
|
|
7189
|
+
* backoff or a capacity `DeferTask`, all of which sit in `sleeping`.
|
|
7190
|
+
*/
|
|
7191
|
+
export async function readPostgresSchedulerRunLaneState(
|
|
7192
|
+
client: PostgresSchedulerQueryClient,
|
|
7193
|
+
input: { runId: string },
|
|
7194
|
+
options?: Pick<PostgresSchedulerOptions, 'schema'>,
|
|
7195
|
+
): Promise<PostgresSchedulerRunLaneState | null> {
|
|
7196
|
+
const result = await client.query<RunLaneStateRow>(
|
|
7197
|
+
`
|
|
7198
|
+
SELECT ${runLaneStateSelectionSql(options)}
|
|
7199
|
+
FROM ${tableName('runs', options)} AS runs
|
|
7200
|
+
WHERE runs.run_id = $1
|
|
7201
|
+
`,
|
|
7202
|
+
[input.runId, POSTGRES_SCHEDULER_RELEASE_CLAIMING_CONTROL_PREFIX],
|
|
7203
|
+
);
|
|
7204
|
+
const row = result.rows[0];
|
|
7205
|
+
return row ? runLaneStateFromRow(row) : null;
|
|
7206
|
+
}
|
|
7207
|
+
|
|
7162
7208
|
/**
|
|
7163
7209
|
* Discover the lanes whose parked durable waits the caller may adopt: lanes
|
|
7164
7210
|
* that have explicitly stopped claiming AND still hold at least one adoptable
|
|
@@ -7259,21 +7305,30 @@ export async function assignPostgresSchedulerRunAttempt(
|
|
|
7259
7305
|
runId: string;
|
|
7260
7306
|
attempt: number;
|
|
7261
7307
|
taskToken: string;
|
|
7308
|
+
/** Persist cleanup ownership in the same fenced write as a fresh claim. */
|
|
7309
|
+
initialRuntimeResource?: unknown;
|
|
7262
7310
|
},
|
|
7263
7311
|
options?: Pick<PostgresSchedulerOptions, 'schema'>,
|
|
7264
7312
|
): Promise<{
|
|
7265
7313
|
checkpoint?: unknown;
|
|
7266
7314
|
suspension?: unknown;
|
|
7267
7315
|
firstClaimLatencyMs?: number;
|
|
7316
|
+
initialRuntimeResourcePersisted: boolean;
|
|
7268
7317
|
} | null> {
|
|
7269
7318
|
const assigned = await client.query<{
|
|
7270
7319
|
checkpoint_json: unknown;
|
|
7271
7320
|
suspension_json: unknown;
|
|
7272
7321
|
first_claim_latency_ms: string | null;
|
|
7322
|
+
initial_runtime_resource_persisted: boolean;
|
|
7273
7323
|
}>(
|
|
7274
7324
|
`
|
|
7275
7325
|
WITH locked_run AS MATERIALIZED (
|
|
7276
|
-
SELECT
|
|
7326
|
+
SELECT
|
|
7327
|
+
runs.run_id,
|
|
7328
|
+
runs.started_at,
|
|
7329
|
+
runs.status,
|
|
7330
|
+
runs.checkpoint_json,
|
|
7331
|
+
runs.suspension_json
|
|
7277
7332
|
FROM ${tableName('runs', options)} AS runs
|
|
7278
7333
|
WHERE runs.run_id = $1
|
|
7279
7334
|
AND runs.status IN ('queued', 'running', 'waiting')
|
|
@@ -7282,6 +7337,8 @@ export async function assignPostgresSchedulerRunAttempt(
|
|
|
7282
7337
|
SELECT
|
|
7283
7338
|
runs.run_id,
|
|
7284
7339
|
runs.started_at,
|
|
7340
|
+
runs.checkpoint_json,
|
|
7341
|
+
runs.suspension_json,
|
|
7285
7342
|
max(attempts.attempt) FILTER (
|
|
7286
7343
|
WHERE attempts.status IN ('claimed', 'running', 'waiting')
|
|
7287
7344
|
) AS active_attempt
|
|
@@ -7290,7 +7347,11 @@ export async function assignPostgresSchedulerRunAttempt(
|
|
|
7290
7347
|
ON attempts.run_id = runs.run_id
|
|
7291
7348
|
WHERE runs.run_id = $1
|
|
7292
7349
|
AND runs.status IN ('queued', 'running', 'waiting')
|
|
7293
|
-
GROUP BY
|
|
7350
|
+
GROUP BY
|
|
7351
|
+
runs.run_id,
|
|
7352
|
+
runs.started_at,
|
|
7353
|
+
runs.checkpoint_json,
|
|
7354
|
+
runs.suspension_json
|
|
7294
7355
|
HAVING max(attempts.attempt) FILTER (
|
|
7295
7356
|
WHERE attempts.status IN ('claimed', 'running', 'waiting')
|
|
7296
7357
|
) IS NULL
|
|
@@ -7306,7 +7367,8 @@ export async function assignPostgresSchedulerRunAttempt(
|
|
|
7306
7367
|
lease_owner,
|
|
7307
7368
|
lease_token,
|
|
7308
7369
|
lease_expires_at,
|
|
7309
|
-
heartbeat_at
|
|
7370
|
+
heartbeat_at,
|
|
7371
|
+
resource_json
|
|
7310
7372
|
)
|
|
7311
7373
|
SELECT
|
|
7312
7374
|
run_id,
|
|
@@ -7315,10 +7377,17 @@ export async function assignPostgresSchedulerRunAttempt(
|
|
|
7315
7377
|
$3,
|
|
7316
7378
|
$4,
|
|
7317
7379
|
NULL,
|
|
7318
|
-
now()
|
|
7380
|
+
now(),
|
|
7381
|
+
CASE
|
|
7382
|
+
WHEN $5::jsonb IS NOT NULL
|
|
7383
|
+
AND checkpoint_json IS NULL
|
|
7384
|
+
AND suspension_json IS NULL
|
|
7385
|
+
THEN jsonb_build_array($5::jsonb)
|
|
7386
|
+
ELSE NULL
|
|
7387
|
+
END
|
|
7319
7388
|
FROM target_run
|
|
7320
7389
|
ON CONFLICT (run_id, attempt) DO NOTHING
|
|
7321
|
-
RETURNING run_id
|
|
7390
|
+
RETURNING run_id, resource_json IS NOT NULL AS initial_runtime_resource_persisted
|
|
7322
7391
|
),
|
|
7323
7392
|
retired_attempts AS (
|
|
7324
7393
|
UPDATE ${tableName('attempts', options)}
|
|
@@ -7396,16 +7465,20 @@ export async function assignPostgresSchedulerRunAttempt(
|
|
|
7396
7465
|
WHERE run_started.run_id = runs.run_id
|
|
7397
7466
|
)
|
|
7398
7467
|
ELSE NULL
|
|
7399
|
-
END AS first_claim_latency_ms
|
|
7468
|
+
END AS first_claim_latency_ms,
|
|
7469
|
+
assigned.initial_runtime_resource_persisted
|
|
7400
7470
|
FROM ${tableName('runs', options)}
|
|
7401
7471
|
AS runs
|
|
7402
|
-
|
|
7472
|
+
JOIN assigned USING (run_id)
|
|
7403
7473
|
`,
|
|
7404
7474
|
[
|
|
7405
7475
|
input.runId,
|
|
7406
7476
|
input.attempt,
|
|
7407
7477
|
POSTGRES_SCHEDULER_ATTEMPT_OWNER,
|
|
7408
7478
|
input.taskToken,
|
|
7479
|
+
input.initialRuntimeResource === undefined
|
|
7480
|
+
? null
|
|
7481
|
+
: stringifyPostgresJson(input.initialRuntimeResource),
|
|
7409
7482
|
],
|
|
7410
7483
|
);
|
|
7411
7484
|
const row = assigned.rows[0] ?? null;
|
|
@@ -7416,6 +7489,8 @@ export async function assignPostgresSchedulerRunAttempt(
|
|
|
7416
7489
|
...(row.first_claim_latency_ms == null
|
|
7417
7490
|
? {}
|
|
7418
7491
|
: { firstClaimLatencyMs: Number(row.first_claim_latency_ms) }),
|
|
7492
|
+
initialRuntimeResourcePersisted:
|
|
7493
|
+
row.initial_runtime_resource_persisted === true,
|
|
7419
7494
|
};
|
|
7420
7495
|
}
|
|
7421
7496
|
|
|
@@ -9157,12 +9232,11 @@ export async function readPostgresSchedulerLaunchRouting(
|
|
|
9157
9232
|
}
|
|
9158
9233
|
}
|
|
9159
9234
|
|
|
9160
|
-
|
|
9161
|
-
client: PostgresSchedulerQueryClient,
|
|
9162
|
-
runId: string,
|
|
9235
|
+
async function observeSchedulerLaunchRead<T>(
|
|
9163
9236
|
options: Pick<PostgresSchedulerOptions, 'schema'> | undefined,
|
|
9164
9237
|
telemetry: { caller: SchedulerLaunchReadCaller },
|
|
9165
|
-
|
|
9238
|
+
read: () => Promise<{ launch: PlaySchedulerSubmitInput | null; value: T }>,
|
|
9239
|
+
): Promise<T> {
|
|
9166
9240
|
const caller = telemetry.caller;
|
|
9167
9241
|
const startedAt = performance.now();
|
|
9168
9242
|
try {
|
|
@@ -9176,21 +9250,7 @@ export async function readPostgresSchedulerLaunch(
|
|
|
9176
9250
|
},
|
|
9177
9251
|
},
|
|
9178
9252
|
async (span) => {
|
|
9179
|
-
const
|
|
9180
|
-
`
|
|
9181
|
-
-- admission_json is the first-writer trusted projection. New rows
|
|
9182
|
-
-- retain non-secret lane/callback routing there while legacy rows
|
|
9183
|
-
-- fall back to launch_json. Merge it last so descendants never
|
|
9184
|
-
-- follow transport metadata changed by a later operational repair.
|
|
9185
|
-
SELECT launch_json || coalesce(admission_json, '{}'::jsonb)
|
|
9186
|
-
AS launch_json
|
|
9187
|
-
FROM ${tableName('runs', options)}
|
|
9188
|
-
WHERE run_id = $1
|
|
9189
|
-
`,
|
|
9190
|
-
[runId],
|
|
9191
|
-
);
|
|
9192
|
-
const row = result.rows[0] ?? null;
|
|
9193
|
-
const launch = row ? parseLaunchJson(row.launch_json) : null;
|
|
9253
|
+
const { launch, value } = await read();
|
|
9194
9254
|
const durationMs = performance.now() - startedAt;
|
|
9195
9255
|
recordSchedulerLaunchRead({
|
|
9196
9256
|
caller,
|
|
@@ -9204,7 +9264,7 @@ export async function readPostgresSchedulerLaunch(
|
|
|
9204
9264
|
'runtime.scheduler.release_id':
|
|
9205
9265
|
launch?.absurdReleaseId?.trim() || 'unassigned',
|
|
9206
9266
|
});
|
|
9207
|
-
return
|
|
9267
|
+
return value;
|
|
9208
9268
|
},
|
|
9209
9269
|
);
|
|
9210
9270
|
} catch (error) {
|
|
@@ -9218,6 +9278,108 @@ export async function readPostgresSchedulerLaunch(
|
|
|
9218
9278
|
}
|
|
9219
9279
|
}
|
|
9220
9280
|
|
|
9281
|
+
export async function readPostgresSchedulerLaunch(
|
|
9282
|
+
client: PostgresSchedulerQueryClient,
|
|
9283
|
+
runId: string,
|
|
9284
|
+
options: Pick<PostgresSchedulerOptions, 'schema'> | undefined,
|
|
9285
|
+
telemetry: { caller: SchedulerLaunchReadCaller },
|
|
9286
|
+
): Promise<PlaySchedulerSubmitInput | null> {
|
|
9287
|
+
return observeSchedulerLaunchRead(options, telemetry, async () => {
|
|
9288
|
+
const result = await client.query<{ launch_json: unknown }>(
|
|
9289
|
+
`
|
|
9290
|
+
-- admission_json is the first-writer trusted projection. New rows
|
|
9291
|
+
-- retain non-secret lane/callback routing there while legacy rows
|
|
9292
|
+
-- fall back to launch_json. Merge it last so descendants never
|
|
9293
|
+
-- follow transport metadata changed by a later operational repair.
|
|
9294
|
+
SELECT launch_json || coalesce(admission_json, '{}'::jsonb)
|
|
9295
|
+
AS launch_json
|
|
9296
|
+
FROM ${tableName('runs', options)}
|
|
9297
|
+
WHERE run_id = $1
|
|
9298
|
+
`,
|
|
9299
|
+
[runId],
|
|
9300
|
+
);
|
|
9301
|
+
const row = result.rows[0];
|
|
9302
|
+
const launch = row ? parseLaunchJson(row.launch_json) : null;
|
|
9303
|
+
return { launch, value: launch };
|
|
9304
|
+
});
|
|
9305
|
+
}
|
|
9306
|
+
|
|
9307
|
+
export type PostgresSchedulerAttemptPreparation = {
|
|
9308
|
+
launch: PlaySchedulerSubmitInput;
|
|
9309
|
+
existing: PlaySchedulerResultEnvelope | null;
|
|
9310
|
+
laneState: PostgresSchedulerRunLaneState;
|
|
9311
|
+
createdProjection: PostgresSchedulerOutboxDeliveryStatus;
|
|
9312
|
+
/** Candidate only; the assignment fence admits at most one racing reader. */
|
|
9313
|
+
nextAttempt: number;
|
|
9314
|
+
};
|
|
9315
|
+
|
|
9316
|
+
/**
|
|
9317
|
+
* Read attempt ingress facts in one database snapshot. Assignment and detached
|
|
9318
|
+
* recovery still perform their own fenced writes; this read cannot claim work.
|
|
9319
|
+
*/
|
|
9320
|
+
export async function readPostgresSchedulerAttemptPreparation(
|
|
9321
|
+
client: PostgresSchedulerQueryClient,
|
|
9322
|
+
runId: string,
|
|
9323
|
+
options?: Pick<PostgresSchedulerOptions, 'schema'>,
|
|
9324
|
+
): Promise<PostgresSchedulerAttemptPreparation | null> {
|
|
9325
|
+
return observeSchedulerLaunchRead(
|
|
9326
|
+
options,
|
|
9327
|
+
{ caller: 'runtime_worker_execute' },
|
|
9328
|
+
async () => {
|
|
9329
|
+
const result = await client.query<
|
|
9330
|
+
RunRow &
|
|
9331
|
+
RunLaneStateRow & {
|
|
9332
|
+
launch_json: unknown;
|
|
9333
|
+
projection_exists: boolean;
|
|
9334
|
+
projection_delivered: boolean;
|
|
9335
|
+
projection_blocked: boolean;
|
|
9336
|
+
next_attempt: number | string;
|
|
9337
|
+
}
|
|
9338
|
+
>(
|
|
9339
|
+
`
|
|
9340
|
+
SELECT runs.run_id, runs.terminal_result_json, runs.terminal_error_json,
|
|
9341
|
+
runs.runtime_timing_json, runs.created_at, runs.started_at, runs.finished_at,
|
|
9342
|
+
runs.launch_json || coalesce(runs.admission_json, '{}'::jsonb) AS launch_json,
|
|
9343
|
+
(SELECT coalesce(max(attempt), 0) + 1
|
|
9344
|
+
FROM ${tableName('attempts', options)}
|
|
9345
|
+
WHERE run_id = runs.run_id) AS next_attempt,
|
|
9346
|
+
${runLaneStateSelectionSql(options)},
|
|
9347
|
+
created.event_id IS NOT NULL AS projection_exists,
|
|
9348
|
+
created.delivered_at IS NOT NULL AS projection_delivered,
|
|
9349
|
+
CASE WHEN created.event_id IS NULL THEN false
|
|
9350
|
+
ELSE ${outboxDeliveryBlockedSql('created', options)}
|
|
9351
|
+
END AS projection_blocked
|
|
9352
|
+
FROM ${tableName('runs', options)} AS runs
|
|
9353
|
+
LEFT JOIN ${tableName('outbox', options)} AS created
|
|
9354
|
+
ON created.run_id = runs.run_id
|
|
9355
|
+
AND created.event_id = 'run-created:' || runs.run_id
|
|
9356
|
+
AND (runs.launch_json || coalesce(runs.admission_json, '{}'::jsonb))
|
|
9357
|
+
->> 'requiresRunCreatedProjection' = 'true'
|
|
9358
|
+
WHERE runs.run_id = $1
|
|
9359
|
+
`,
|
|
9360
|
+
[runId, POSTGRES_SCHEDULER_RELEASE_CLAIMING_CONTROL_PREFIX],
|
|
9361
|
+
);
|
|
9362
|
+
const row = result.rows[0];
|
|
9363
|
+
const launch = row ? parseLaunchJson(row.launch_json) : null;
|
|
9364
|
+
const value: PostgresSchedulerAttemptPreparation | null =
|
|
9365
|
+
row && launch
|
|
9366
|
+
? {
|
|
9367
|
+
launch,
|
|
9368
|
+
existing: schedulerResultFromRow(row),
|
|
9369
|
+
laneState: runLaneStateFromRow(row),
|
|
9370
|
+
nextAttempt: Number(row.next_attempt),
|
|
9371
|
+
createdProjection: {
|
|
9372
|
+
exists: row.projection_exists === true,
|
|
9373
|
+
delivered: row.projection_delivered === true,
|
|
9374
|
+
blocked: row.projection_blocked === true,
|
|
9375
|
+
},
|
|
9376
|
+
}
|
|
9377
|
+
: null;
|
|
9378
|
+
return { launch, value };
|
|
9379
|
+
},
|
|
9380
|
+
);
|
|
9381
|
+
}
|
|
9382
|
+
|
|
9221
9383
|
/**
|
|
9222
9384
|
* One round-trip replay inspection for externally retried admissions. The
|
|
9223
9385
|
* caller uses this only to return an already-committed Run without rebuilding
|
|
@@ -9316,7 +9478,7 @@ const POSTGRES_SCHEDULER_ATTEMPT_AUTHORITY_FIELDS = [
|
|
|
9316
9478
|
export type PostgresSchedulerAttemptAuthority = Pick<
|
|
9317
9479
|
PlaySchedulerSubmitInput,
|
|
9318
9480
|
(typeof POSTGRES_SCHEDULER_ATTEMPT_AUTHORITY_FIELDS)[number]
|
|
9319
|
-
|
|
9481
|
+
> & { computeSessionIntentPersisted?: boolean };
|
|
9320
9482
|
|
|
9321
9483
|
type PostgresSchedulerAuthorityRow = PostgresSchedulerAttemptAuthority & {
|
|
9322
9484
|
launch_required_fields_valid: boolean;
|
|
@@ -9362,7 +9524,17 @@ export async function readPostgresSchedulerAttemptAuthorityForLease(
|
|
|
9362
9524
|
): Promise<PostgresSchedulerAttemptAuthority | null> {
|
|
9363
9525
|
const result = await client.query<PostgresSchedulerAuthorityRow>(
|
|
9364
9526
|
`
|
|
9365
|
-
SELECT ${POSTGRES_SCHEDULER_AUTHORITY_SELECT}
|
|
9527
|
+
SELECT ${POSTGRES_SCHEDULER_AUTHORITY_SELECT},
|
|
9528
|
+
EXISTS (
|
|
9529
|
+
SELECT 1 FROM jsonb_array_elements(
|
|
9530
|
+
CASE
|
|
9531
|
+
WHEN jsonb_typeof(attempts.resource_json) = 'array' THEN attempts.resource_json
|
|
9532
|
+
WHEN attempts.resource_json IS NULL THEN '[]'::jsonb
|
|
9533
|
+
ELSE jsonb_build_array(attempts.resource_json)
|
|
9534
|
+
END
|
|
9535
|
+
) AS resource
|
|
9536
|
+
WHERE resource->>'kind' = 'compute_session'
|
|
9537
|
+
) AS "computeSessionIntentPersisted"
|
|
9366
9538
|
FROM ${tableName('runs', options)} AS runs
|
|
9367
9539
|
JOIN ${tableName('attempts', options)} AS attempts
|
|
9368
9540
|
ON attempts.run_id = runs.run_id
|
|
@@ -13215,14 +13387,10 @@ export async function readPostgresSchedulerRunnerLiveness(
|
|
|
13215
13387
|
* and no newer attempt to exist. Gateway replicas must never infer this fence
|
|
13216
13388
|
* from process memory.
|
|
13217
13389
|
*/
|
|
13218
|
-
|
|
13219
|
-
client: PostgresSchedulerQueryClient,
|
|
13220
|
-
input: { runId: string; attempt: number },
|
|
13390
|
+
function runnerProgressAttemptCurrentCondition(
|
|
13221
13391
|
options?: Pick<PostgresSchedulerOptions, 'schema'>,
|
|
13222
|
-
):
|
|
13223
|
-
|
|
13224
|
-
`
|
|
13225
|
-
SELECT EXISTS (
|
|
13392
|
+
): string {
|
|
13393
|
+
return `EXISTS (
|
|
13226
13394
|
SELECT 1
|
|
13227
13395
|
FROM ${tableName('attempts', options)} AS current_attempt
|
|
13228
13396
|
JOIN ${tableName('runs', options)} AS run
|
|
@@ -13237,13 +13405,50 @@ export async function isPostgresSchedulerRunnerProgressAttemptCurrent(
|
|
|
13237
13405
|
WHERE newer_attempt.run_id = current_attempt.run_id
|
|
13238
13406
|
AND newer_attempt.attempt > current_attempt.attempt
|
|
13239
13407
|
)
|
|
13240
|
-
)
|
|
13241
|
-
|
|
13408
|
+
)`;
|
|
13409
|
+
}
|
|
13410
|
+
|
|
13411
|
+
export async function isPostgresSchedulerRunnerProgressAttemptCurrent(
|
|
13412
|
+
client: PostgresSchedulerQueryClient,
|
|
13413
|
+
input: { runId: string; attempt: number },
|
|
13414
|
+
options?: Pick<PostgresSchedulerOptions, 'schema'>,
|
|
13415
|
+
): Promise<boolean> {
|
|
13416
|
+
const result = await client.query<{ current: boolean }>(
|
|
13417
|
+
`SELECT ${runnerProgressAttemptCurrentCondition(options)} AS current`,
|
|
13242
13418
|
[input.runId, input.attempt],
|
|
13243
13419
|
);
|
|
13244
13420
|
return result.rows[0]?.current === true;
|
|
13245
13421
|
}
|
|
13246
13422
|
|
|
13423
|
+
/** Observe terminal ingress authority without loading the stored result. */
|
|
13424
|
+
export async function readPostgresSchedulerRunnerAttemptAuthority(
|
|
13425
|
+
client: PostgresSchedulerQueryClient,
|
|
13426
|
+
input: { runId: string; attempt: number },
|
|
13427
|
+
options?: Pick<PostgresSchedulerOptions, 'schema'>,
|
|
13428
|
+
): Promise<{ current: boolean; terminalRecorded: boolean }> {
|
|
13429
|
+
const result = await client.query<{
|
|
13430
|
+
current: boolean;
|
|
13431
|
+
terminal_recorded: boolean;
|
|
13432
|
+
}>(
|
|
13433
|
+
`
|
|
13434
|
+
SELECT ${runnerProgressAttemptCurrentCondition(options)} AS current,
|
|
13435
|
+
EXISTS (
|
|
13436
|
+
SELECT 1
|
|
13437
|
+
FROM ${tableName('attempts', options)}
|
|
13438
|
+
WHERE run_id = $1
|
|
13439
|
+
AND attempt = $2
|
|
13440
|
+
AND runner_result_json IS NOT NULL
|
|
13441
|
+
AND runner_result_json <> 'null'::jsonb
|
|
13442
|
+
) AS terminal_recorded
|
|
13443
|
+
`,
|
|
13444
|
+
[input.runId, input.attempt],
|
|
13445
|
+
);
|
|
13446
|
+
return {
|
|
13447
|
+
current: result.rows[0]?.current === true,
|
|
13448
|
+
terminalRecorded: result.rows[0]?.terminal_recorded === true,
|
|
13449
|
+
};
|
|
13450
|
+
}
|
|
13451
|
+
|
|
13247
13452
|
/**
|
|
13248
13453
|
* Push execution (B2-final): the detached runner's liveness/cancellation poll.
|
|
13249
13454
|
* Bumps `heartbeat_at` on the runner's attempt row (the same liveness column
|
|
@@ -17667,6 +17872,13 @@ export async function readPostgresSchedulerResult(
|
|
|
17667
17872
|
);
|
|
17668
17873
|
const row = result.rows[0] ?? null;
|
|
17669
17874
|
if (!row) return null;
|
|
17875
|
+
return schedulerResultFromRow(row, options?.includeCancelledOutput);
|
|
17876
|
+
}
|
|
17877
|
+
|
|
17878
|
+
function schedulerResultFromRow(
|
|
17879
|
+
row: RunRow,
|
|
17880
|
+
includeCancelledOutput = false,
|
|
17881
|
+
): PlaySchedulerResultEnvelope | null {
|
|
17670
17882
|
if (
|
|
17671
17883
|
row.status !== 'completed' &&
|
|
17672
17884
|
row.status !== 'failed' &&
|
|
@@ -17684,7 +17896,7 @@ export async function readPostgresSchedulerResult(
|
|
|
17684
17896
|
status: row.status,
|
|
17685
17897
|
...(row.status === 'completed' ||
|
|
17686
17898
|
((row.status === 'failed' ||
|
|
17687
|
-
(row.status === 'cancelled' &&
|
|
17899
|
+
(row.status === 'cancelled' && includeCancelledOutput)) &&
|
|
17688
17900
|
row.terminal_result_json !== null)
|
|
17689
17901
|
? { output: row.terminal_result_json }
|
|
17690
17902
|
: {}),
|
|
@@ -18590,7 +18802,13 @@ function runLedgerOutboxPrefixClaimSql(
|
|
|
18590
18802
|
Parameters<typeof readPendingPostgresSchedulerOutboxEvents>[1]
|
|
18591
18803
|
>,
|
|
18592
18804
|
options: Pick<PostgresSchedulerOptions, 'schema'> | undefined,
|
|
18593
|
-
acknowledgement:
|
|
18805
|
+
acknowledgement:
|
|
18806
|
+
| {
|
|
18807
|
+
eventIds: string[];
|
|
18808
|
+
targetEventId: string;
|
|
18809
|
+
createdProjectionWake?: RunCreatedProjectionWake;
|
|
18810
|
+
}
|
|
18811
|
+
| undefined,
|
|
18594
18812
|
supportsTerminalBatchMarker: boolean,
|
|
18595
18813
|
fence?: { runId: string; expectedHeadEventId?: string },
|
|
18596
18814
|
): string {
|
|
@@ -19020,12 +19238,7 @@ function runLedgerOutboxPrefixClaimSql(
|
|
|
19020
19238
|
${
|
|
19021
19239
|
acknowledgement
|
|
19022
19240
|
? `, notified AS MATERIALIZED (
|
|
19023
|
-
|
|
19024
|
-
pg_notify(
|
|
19025
|
-
$7,
|
|
19026
|
-
json_build_object('eventId', event_id, 'kind', 'outbox_delivered')::text
|
|
19027
|
-
) AS notification
|
|
19028
|
-
FROM delivered
|
|
19241
|
+
${runLedgerDeliveredNotificationsSql('$7', acknowledgement.createdProjectionWake ? { queue: '$8', event: '$9' } : undefined)}
|
|
19029
19242
|
)`
|
|
19030
19243
|
: ''
|
|
19031
19244
|
}
|
|
@@ -19156,7 +19369,11 @@ async function claimRunLedgerOutboxPrefixInBatch(
|
|
|
19156
19369
|
recoverTransportDelivery?: boolean;
|
|
19157
19370
|
},
|
|
19158
19371
|
options?: Pick<PostgresSchedulerOptions, 'schema'>,
|
|
19159
|
-
acknowledgement?: {
|
|
19372
|
+
acknowledgement?: {
|
|
19373
|
+
eventIds: string[];
|
|
19374
|
+
targetEventId: string;
|
|
19375
|
+
createdProjectionWake?: RunCreatedProjectionWake;
|
|
19376
|
+
},
|
|
19160
19377
|
): Promise<{
|
|
19161
19378
|
events: PostgresSchedulerOutboxEvent[];
|
|
19162
19379
|
deliveredRows: RunLedgerOutboxDeliveredRow[];
|
|
@@ -19184,6 +19401,12 @@ async function claimRunLedgerOutboxPrefixInBatch(
|
|
|
19184
19401
|
acknowledgement.eventIds,
|
|
19185
19402
|
acknowledgement.targetEventId,
|
|
19186
19403
|
postgresSchedulerNotifyChannel('terminal', options),
|
|
19404
|
+
...(acknowledgement.createdProjectionWake
|
|
19405
|
+
? [
|
|
19406
|
+
acknowledgement.createdProjectionWake.queueName,
|
|
19407
|
+
acknowledgement.createdProjectionWake.eventName,
|
|
19408
|
+
]
|
|
19409
|
+
: []),
|
|
19187
19410
|
]
|
|
19188
19411
|
: input.extendOwnedHead
|
|
19189
19412
|
? [input.extendOwnedHead]
|
|
@@ -19395,7 +19618,11 @@ async function claimPostgresSchedulerOutboxPrefix(
|
|
|
19395
19618
|
Parameters<typeof readPendingPostgresSchedulerOutboxEvents>[1]
|
|
19396
19619
|
>,
|
|
19397
19620
|
options?: Pick<PostgresSchedulerOptions, 'schema'>,
|
|
19398
|
-
acknowledgement?: {
|
|
19621
|
+
acknowledgement?: {
|
|
19622
|
+
eventIds: string[];
|
|
19623
|
+
targetEventId: string;
|
|
19624
|
+
createdProjectionWake?: RunCreatedProjectionWake;
|
|
19625
|
+
},
|
|
19399
19626
|
): Promise<{
|
|
19400
19627
|
events: PostgresSchedulerOutboxEvent[];
|
|
19401
19628
|
deliveredRows: RunLedgerOutboxDeliveredRow[];
|
|
@@ -19426,6 +19653,12 @@ async function claimPostgresSchedulerOutboxPrefix(
|
|
|
19426
19653
|
acknowledgement.eventIds,
|
|
19427
19654
|
acknowledgement.targetEventId,
|
|
19428
19655
|
postgresSchedulerNotifyChannel('terminal', options),
|
|
19656
|
+
...(acknowledgement.createdProjectionWake
|
|
19657
|
+
? [
|
|
19658
|
+
acknowledgement.createdProjectionWake.queueName,
|
|
19659
|
+
acknowledgement.createdProjectionWake.eventName,
|
|
19660
|
+
]
|
|
19661
|
+
: []),
|
|
19429
19662
|
]
|
|
19430
19663
|
: input.extendOwnedHead
|
|
19431
19664
|
? [input.extendOwnedHead]
|
|
@@ -19654,13 +19887,7 @@ export async function readPostgresSchedulerOutboxDeliveryStatus(
|
|
|
19654
19887
|
${
|
|
19655
19888
|
options?.includeBlocked === false
|
|
19656
19889
|
? 'false'
|
|
19657
|
-
:
|
|
19658
|
-
SELECT 1
|
|
19659
|
-
FROM ${tableName('outbox', options)} predecessor
|
|
19660
|
-
WHERE predecessor.run_id = target.run_id
|
|
19661
|
-
AND predecessor.failed_at IS NOT NULL
|
|
19662
|
-
AND ${runLedgerPrecedesSql('predecessor', 'target', true)}
|
|
19663
|
-
)`
|
|
19890
|
+
: outboxDeliveryBlockedSql('target', options)
|
|
19664
19891
|
} AS blocked
|
|
19665
19892
|
FROM ${tableName('outbox', options)} target
|
|
19666
19893
|
WHERE target.run_id = $1 AND target.event_id = $2`,
|
|
@@ -19674,6 +19901,19 @@ export async function readPostgresSchedulerOutboxDeliveryStatus(
|
|
|
19674
19901
|
};
|
|
19675
19902
|
}
|
|
19676
19903
|
|
|
19904
|
+
function outboxDeliveryBlockedSql(
|
|
19905
|
+
target: string,
|
|
19906
|
+
options?: Pick<PostgresSchedulerOptions, 'schema'>,
|
|
19907
|
+
): string {
|
|
19908
|
+
return `${target}.failed_at IS NOT NULL OR EXISTS (
|
|
19909
|
+
SELECT 1
|
|
19910
|
+
FROM ${tableName('outbox', options)} predecessor
|
|
19911
|
+
WHERE predecessor.run_id = ${target}.run_id
|
|
19912
|
+
AND predecessor.failed_at IS NOT NULL
|
|
19913
|
+
AND ${runLedgerPrecedesSql('predecessor', target, true)}
|
|
19914
|
+
)`;
|
|
19915
|
+
}
|
|
19916
|
+
|
|
19677
19917
|
/**
|
|
19678
19918
|
* Read the age of one oldest pending outbox row through the partial
|
|
19679
19919
|
* `(created_at, event_id)` index. This deliberately avoids the historical
|
|
@@ -20156,6 +20396,31 @@ function runLedgerAcknowledgeSql(
|
|
|
20156
20396
|
AS lag_ms`;
|
|
20157
20397
|
}
|
|
20158
20398
|
|
|
20399
|
+
type RunCreatedProjectionWake = { queueName: string; eventName: string };
|
|
20400
|
+
|
|
20401
|
+
/** Both standalone and continuation ACKs publish the same atomic wake. */
|
|
20402
|
+
function runLedgerDeliveredNotificationsSql(
|
|
20403
|
+
terminalChannel: string,
|
|
20404
|
+
wake?: { queue: string; event: string },
|
|
20405
|
+
): string {
|
|
20406
|
+
return `SELECT delivered.*,
|
|
20407
|
+
pg_notify(${terminalChannel},
|
|
20408
|
+
json_build_object('eventId', event_id, 'kind', 'outbox_delivered')::text
|
|
20409
|
+
) AS notification
|
|
20410
|
+
${
|
|
20411
|
+
wake
|
|
20412
|
+
? `,
|
|
20413
|
+
CASE WHEN event_type = ${RUN_EVENT_KIND_SQL_LITERAL.runCreated}
|
|
20414
|
+
THEN absurd.emit_event(${wake.queue}, ${wake.event}, 'true'::jsonb)
|
|
20415
|
+
END AS engine_wake,
|
|
20416
|
+
CASE WHEN event_type = ${RUN_EVENT_KIND_SQL_LITERAL.runCreated}
|
|
20417
|
+
THEN pg_notify('absurd_wake', ${wake.queue})
|
|
20418
|
+
END AS engine_notification`
|
|
20419
|
+
: ''
|
|
20420
|
+
}
|
|
20421
|
+
FROM delivered`;
|
|
20422
|
+
}
|
|
20423
|
+
|
|
20159
20424
|
/**
|
|
20160
20425
|
* Lease-fenced acknowledgement that also reports each row's event type and
|
|
20161
20426
|
* commit-to-acknowledgement lag on the database clock, so lag metrics never
|
|
@@ -20166,6 +20431,7 @@ export async function markPostgresSchedulerOutboxDeliveredRows(
|
|
|
20166
20431
|
eventIds: string[],
|
|
20167
20432
|
options?: Pick<PostgresSchedulerOptions, 'schema'> & {
|
|
20168
20433
|
leaseOwner?: string | null;
|
|
20434
|
+
createdProjectionWake?: RunCreatedProjectionWake;
|
|
20169
20435
|
},
|
|
20170
20436
|
): Promise<RunLedgerOutboxDeliveredRow[]> {
|
|
20171
20437
|
if (eventIds.length === 0) return [];
|
|
@@ -20177,20 +20443,21 @@ export async function markPostgresSchedulerOutboxDeliveredRows(
|
|
|
20177
20443
|
`
|
|
20178
20444
|
WITH delivered AS (
|
|
20179
20445
|
${runLedgerAcknowledgeSql(options, '$1', '$2')}
|
|
20446
|
+
), notified AS MATERIALIZED (
|
|
20447
|
+
${runLedgerDeliveredNotificationsSql('$3', options?.createdProjectionWake ? { queue: '$4', event: '$5' } : undefined)}
|
|
20180
20448
|
)
|
|
20181
|
-
SELECT event_id,
|
|
20182
|
-
event_type,
|
|
20183
|
-
lag_ms,
|
|
20184
|
-
pg_notify(
|
|
20185
|
-
$3,
|
|
20186
|
-
json_build_object('eventId', event_id, 'kind', 'outbox_delivered')::text
|
|
20187
|
-
)
|
|
20188
|
-
FROM delivered
|
|
20449
|
+
SELECT event_id, event_type, lag_ms FROM notified
|
|
20189
20450
|
`,
|
|
20190
20451
|
[
|
|
20191
20452
|
eventIds,
|
|
20192
20453
|
options?.leaseOwner?.trim() || null,
|
|
20193
20454
|
postgresSchedulerNotifyChannel('terminal', options),
|
|
20455
|
+
...(options?.createdProjectionWake
|
|
20456
|
+
? [
|
|
20457
|
+
options.createdProjectionWake.queueName,
|
|
20458
|
+
options.createdProjectionWake.eventName,
|
|
20459
|
+
]
|
|
20460
|
+
: []),
|
|
20194
20461
|
],
|
|
20195
20462
|
);
|
|
20196
20463
|
return result.rows.map((row) => {
|
|
@@ -20705,6 +20972,8 @@ export function postgresSchedulerCancellationOutboxLease(runId: string): {
|
|
|
20705
20972
|
}
|
|
20706
20973
|
|
|
20707
20974
|
export type RunLedgerOutboxDispatchInput = {
|
|
20975
|
+
/** App-owned transport; launch authority and routing still come from the lease. */
|
|
20976
|
+
appRuntimeFetch?: typeof fetch;
|
|
20708
20977
|
/** Dedicated bounded checkout for indexing; claims/ACKs use withClient. */
|
|
20709
20978
|
withObservabilityClient?: RunLedgerOutboxWithClient;
|
|
20710
20979
|
|
|
@@ -21054,10 +21323,14 @@ async function dispatchRunLedgerOutboxBatchWithScope(
|
|
|
21054
21323
|
// A committed terminal is running-work control traffic. Use the existing
|
|
21055
21324
|
// alternating critical admission lane so its short lease operations do not
|
|
21056
21325
|
// sit behind a full ordinary-work backlog; capacity is unchanged.
|
|
21057
|
-
|
|
21326
|
+
// Only a caller that explicitly targets this run's terminal may reuse the
|
|
21327
|
+
// claim's first-HTTP lease proof. Background discovery can still prioritize
|
|
21328
|
+
// a terminal after claiming it, but must renew before its first append.
|
|
21329
|
+
const targetedTerminalRunId =
|
|
21058
21330
|
scope && scope.targetEventId === `run-terminal:${scope.runId}`
|
|
21059
21331
|
? scope.runId
|
|
21060
21332
|
: null;
|
|
21333
|
+
let terminalRunId = targetedTerminalRunId;
|
|
21061
21334
|
const withClient: RunLedgerOutboxWithClient = (operation, trace) =>
|
|
21062
21335
|
acquireClient(
|
|
21063
21336
|
operation,
|
|
@@ -21092,7 +21365,11 @@ async function dispatchRunLedgerOutboxBatchWithScope(
|
|
|
21092
21365
|
WHEN ${runLedgerSearchOnlyOutboxFactSql('head')} THEN NULL::jsonb
|
|
21093
21366
|
ELSE ${runLedgerDispatchLaunchSql('runs')}
|
|
21094
21367
|
END`
|
|
21095
|
-
:
|
|
21368
|
+
: input.searchOnly
|
|
21369
|
+
? 'NULL::jsonb'
|
|
21370
|
+
: `CASE WHEN head.event_type = ${RUN_EVENT_KIND_SQL_LITERAL.runCreated}
|
|
21371
|
+
THEN ${runLedgerDispatchLaunchSql('runs')}
|
|
21372
|
+
ELSE NULL::jsonb END`;
|
|
21096
21373
|
const transportHeadSelection =
|
|
21097
21374
|
tokenAuthority === 'gateway' &&
|
|
21098
21375
|
!input.searchOnly &&
|
|
@@ -21439,7 +21716,7 @@ async function dispatchRunLedgerOutboxBatchWithScope(
|
|
|
21439
21716
|
dispatch_launch_json: unknown;
|
|
21440
21717
|
}>(
|
|
21441
21718
|
`SELECT runs.run_id,
|
|
21442
|
-
${
|
|
21719
|
+
${!input.searchOnly ? runLedgerDispatchLaunchSql('runs') : 'NULL::jsonb'} AS dispatch_launch_json
|
|
21443
21720
|
FROM ${tableName('runs', options)} AS runs
|
|
21444
21721
|
WHERE runs.run_id = $1 FOR UPDATE`,
|
|
21445
21722
|
[targetRunId],
|
|
@@ -21582,6 +21859,21 @@ async function dispatchRunLedgerOutboxBatchWithScope(
|
|
|
21582
21859
|
});
|
|
21583
21860
|
}
|
|
21584
21861
|
|
|
21862
|
+
// Background discovery cannot classify its head before claiming it. Once
|
|
21863
|
+
// the owned prefix contains a terminal, its renewal and acknowledgement
|
|
21864
|
+
// are the same critical running-work control as a targeted worker drain.
|
|
21865
|
+
const prioritizeClaimedTerminal = () => {
|
|
21866
|
+
if (
|
|
21867
|
+
!input.searchOnly &&
|
|
21868
|
+
events.some((event) =>
|
|
21869
|
+
RUN_SCHEDULER_OUTBOX_TERMINAL_EVENT_TYPES.includes(event.eventType),
|
|
21870
|
+
)
|
|
21871
|
+
) {
|
|
21872
|
+
terminalRunId = events[0]!.runId;
|
|
21873
|
+
}
|
|
21874
|
+
};
|
|
21875
|
+
prioritizeClaimedTerminal();
|
|
21876
|
+
|
|
21585
21877
|
const claimedAtMs = Date.now();
|
|
21586
21878
|
let authorityReadyAtMs: number | null = null;
|
|
21587
21879
|
let appendFinishedAtMs: number | null = null;
|
|
@@ -21948,6 +22240,9 @@ async function dispatchRunLedgerOutboxBatchWithScope(
|
|
|
21948
22240
|
gatewayRuntimeApi ?? input.runtimeApi ?? (await resolveRunRuntimeApi());
|
|
21949
22241
|
runtimeApi = {
|
|
21950
22242
|
...resolvedRuntimeApi,
|
|
22243
|
+
...(tokenAuthority === 'local_mint' && input.appRuntimeFetch
|
|
22244
|
+
? { fetch: input.appRuntimeFetch }
|
|
22245
|
+
: {}),
|
|
21951
22246
|
...(gatewayRuntimeApi && input.runtimeApi
|
|
21952
22247
|
? {
|
|
21953
22248
|
...(input.runtimeApi.fetch
|
|
@@ -22082,6 +22377,7 @@ async function dispatchRunLedgerOutboxBatchWithScope(
|
|
|
22082
22377
|
);
|
|
22083
22378
|
}
|
|
22084
22379
|
events = widened;
|
|
22380
|
+
prioritizeClaimedTerminal();
|
|
22085
22381
|
}
|
|
22086
22382
|
// Widening can add deferred facts to the lease. Project the complete
|
|
22087
22383
|
// frozen prefix before any HTTP append, including its newly claimed rows.
|
|
@@ -22137,7 +22433,7 @@ async function dispatchRunLedgerOutboxBatchWithScope(
|
|
|
22137
22433
|
}
|
|
22138
22434
|
if (
|
|
22139
22435
|
firstRenewal &&
|
|
22140
|
-
|
|
22436
|
+
targetedTerminalRunId === first.runId &&
|
|
22141
22437
|
tokenAuthority === 'gateway' &&
|
|
22142
22438
|
runtimeApi?.runLedgerIngressPrefixBatching === true &&
|
|
22143
22439
|
ledgerEvents !== null &&
|
|
@@ -22267,12 +22563,30 @@ async function dispatchRunLedgerOutboxBatchWithScope(
|
|
|
22267
22563
|
await renewDelivery();
|
|
22268
22564
|
}
|
|
22269
22565
|
appendFinishedAtMs = Date.now();
|
|
22566
|
+
let createdProjectionWake: RunCreatedProjectionWake | undefined;
|
|
22567
|
+
if (
|
|
22568
|
+
events.some((event) => event.eventType === RUN_EVENT_KIND.runCreated) &&
|
|
22569
|
+
launchJson
|
|
22570
|
+
) {
|
|
22571
|
+
const routing = parseRunLedgerDispatchLaunch(launchJson);
|
|
22572
|
+
if (routing.requiresRunCreatedProjection) {
|
|
22573
|
+
const {
|
|
22574
|
+
absurdQueueNameForLaunch,
|
|
22575
|
+
absurdRunCreatedProjectionEventName,
|
|
22576
|
+
} = await import('./absurd-shared');
|
|
22577
|
+
createdProjectionWake = {
|
|
22578
|
+
queueName: absurdQueueNameForLaunch(routing),
|
|
22579
|
+
eventName: absurdRunCreatedProjectionEventName(first.runId),
|
|
22580
|
+
};
|
|
22581
|
+
}
|
|
22582
|
+
}
|
|
22270
22583
|
const acknowledgement = await acknowledgeRunLedgerPrefixWithContinuation(
|
|
22271
22584
|
withClient,
|
|
22272
22585
|
{
|
|
22273
22586
|
input,
|
|
22274
22587
|
events,
|
|
22275
22588
|
leaseOwner,
|
|
22589
|
+
createdProjectionWake,
|
|
22276
22590
|
runtimeApi,
|
|
22277
22591
|
scope,
|
|
22278
22592
|
continuation,
|
|
@@ -22667,6 +22981,7 @@ async function acknowledgeRunLedgerPrefixWithContinuation(
|
|
|
22667
22981
|
input: RunLedgerOutboxDispatchInput;
|
|
22668
22982
|
events: PostgresSchedulerOutboxEvent[];
|
|
22669
22983
|
leaseOwner: string;
|
|
22984
|
+
createdProjectionWake?: RunCreatedProjectionWake;
|
|
22670
22985
|
runtimeApi: WorkerRuntimeApiContext | null;
|
|
22671
22986
|
scope?: RunLedgerOutboxDrainScope;
|
|
22672
22987
|
continuation: { current: RunLedgerOutboxDrainScope | null };
|
|
@@ -22769,13 +23084,21 @@ async function acknowledgeRunLedgerPrefixWithContinuation(
|
|
|
22769
23084
|
input.runtimeApi?.runLedgerIngressPrefixBatching === true,
|
|
22770
23085
|
},
|
|
22771
23086
|
options,
|
|
22772
|
-
{
|
|
23087
|
+
{
|
|
23088
|
+
eventIds,
|
|
23089
|
+
targetEventId,
|
|
23090
|
+
createdProjectionWake: input.createdProjectionWake,
|
|
23091
|
+
},
|
|
22773
23092
|
)
|
|
22774
23093
|
: {
|
|
22775
23094
|
deliveredRows: await markPostgresSchedulerOutboxDeliveredRows(
|
|
22776
23095
|
client,
|
|
22777
23096
|
eventIds,
|
|
22778
|
-
{
|
|
23097
|
+
{
|
|
23098
|
+
...options,
|
|
23099
|
+
leaseOwner: input.leaseOwner,
|
|
23100
|
+
createdProjectionWake: input.createdProjectionWake,
|
|
23101
|
+
},
|
|
22779
23102
|
),
|
|
22780
23103
|
events: [],
|
|
22781
23104
|
};
|