deepline 0.3.296 → 0.3.298
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/release.ts +1 -1
- package/dist/bundling-sources/shared_libs/monitors/quickstart-prompts.ts +15 -0
- package/dist/bundling-sources/shared_libs/monitors/starter-templates.ts +9 -98
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-pool.ts +3 -1
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +80 -33
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/run-ledger-outbox-recovery.ts +136 -62
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-event-search.ts +15 -3
- package/dist/cli/auth-AQCORSG5.js +31 -0
- package/dist/cli/{auth-JCGIDVDF.mjs → auth-TJGQB4RK.mjs} +4 -4
- package/dist/cli/{billing-OQBSIXRG.mjs → billing-BUHGVESC.mjs} +4 -4
- package/dist/cli/{billing-YBK3J4WP.js → billing-HSBXETYG.js} +70 -70
- package/dist/cli/{chunk-6HPEDBSJ.js → chunk-2Q4LGPVP.js} +4 -4
- package/dist/cli/{chunk-A7427JJH.js → chunk-4TOJTO4S.js} +6 -6
- package/dist/cli/{chunk-QSIO4TX2.mjs → chunk-6IOQ43VG.mjs} +1 -1
- package/dist/cli/{chunk-2C3AVPTY.js → chunk-7ZA3OMYT.js} +6 -6
- package/dist/cli/{chunk-AQRTLPHZ.js → chunk-B5R4IGNU.js} +6 -6
- package/dist/cli/{chunk-LIKFCE7Z.js → chunk-BUKTFUM7.js} +1 -1
- package/dist/cli/{chunk-ZDOC4HFL.js → chunk-BXYKLY5T.js} +48 -48
- package/dist/cli/{chunk-4ZB3CJRD.js → chunk-CVNG2LB7.js} +15 -15
- package/dist/cli/{chunk-J2D3VDOU.mjs → chunk-FJTNI2TE.mjs} +1 -1
- package/dist/cli/{chunk-DYWHXO7O.mjs → chunk-FT4JXVAD.mjs} +1 -1
- package/dist/cli/{chunk-2MZ5EQZE.mjs → chunk-IZKS7OGL.mjs} +2 -2
- package/dist/cli/{chunk-GLKUGBTP.mjs → chunk-MJWD6SJR.mjs} +3 -3
- package/dist/cli/{chunk-4Y6CG4GE.js → chunk-NHNFNVLD.js} +58 -58
- package/dist/cli/{chunk-UC6GHEL4.js → chunk-OXCFNXS5.js} +26 -26
- package/dist/cli/{chunk-BZ77OTRF.mjs → chunk-RES6RQXX.mjs} +2 -2
- package/dist/cli/{chunk-G46HHFNB.mjs → chunk-S5CEMBUJ.mjs} +4 -4
- package/dist/cli/{chunk-7D6QG5KF.js → chunk-TOAXEXTC.js} +6 -6
- package/dist/cli/{chunk-NTEZFZLE.mjs → chunk-U6G52KUV.mjs} +1 -1
- package/dist/cli/{chunk-RCUE5C5C.mjs → chunk-XZNFOO5U.mjs} +1 -1
- package/dist/cli/{chunk-NPPJX3BL.mjs → chunk-YE5PJMFK.mjs} +1 -1
- package/dist/cli/{chunk-7UAO5MWV.mjs → chunk-YFNB2GPD.mjs} +3 -3
- package/dist/cli/{chunk-L4HBNHFW.js → chunk-YJX7FY4F.js} +2 -2
- package/dist/cli/{client-CZDA4JKO.mjs → client-2TV2OKUH.mjs} +3 -3
- package/dist/cli/client-QKZ6CTWN.js +20 -0
- package/dist/cli/{csv-6KOMZA2H.mjs → csv-7XFZ333H.mjs} +3 -3
- package/dist/cli/{csv-UTEQY3NA.js → csv-N2CI4OLO.js} +12 -12
- package/dist/cli/{db-D5EP6TKO.mjs → db-R37F3UHM.mjs} +4 -4
- package/dist/cli/{db-SIBLPIKC.js → db-UXTCDLUO.js} +20 -20
- package/dist/cli/{executions-2PHT57IO.js → executions-AVGJESD2.js} +6 -6
- package/dist/cli/{executions-DFWM2YYY.mjs → executions-SQ3CYCNF.mjs} +4 -4
- package/dist/cli/{feedback-IQVWIJZ4.js → feedback-DY5GZCHY.js} +6 -6
- package/dist/cli/{feedback-GZW37JMI.mjs → feedback-VRUQVLR2.mjs} +3 -3
- package/dist/cli/git-72HXNB6W.js +23 -0
- package/dist/cli/{git-B72Y4FFQ.mjs → git-YCT5WDUM.mjs} +4 -4
- package/dist/cli/index.js +73 -73
- package/dist/cli/index.mjs +30 -30
- package/dist/cli/{legacy-noops-IFGVDCOM.js → legacy-noops-EC6NUDQG.js} +7 -7
- package/dist/cli/{legacy-noops-37F5MX2P.mjs → legacy-noops-TPKXHLEJ.mjs} +4 -4
- package/dist/cli/{monitors-42H6LOVT.mjs → monitors-BVIPCPTM.mjs} +4 -4
- package/dist/cli/{monitors-GQCHXBXZ.js → monitors-RAJW7CTX.js} +85 -85
- package/dist/cli/{org-4GCPBTGR.js → org-CYBSXWOL.js} +60 -60
- package/dist/cli/{org-JYZA3ZRJ.mjs → org-FQ6DJMPU.mjs} +4 -4
- package/dist/cli/{play-Q2XV3FZZ.mjs → play-5KQLW4UV.mjs} +6 -6
- package/dist/cli/{play-46ZJ4FMI.js → play-W5UAFX62.js} +200 -200
- package/dist/cli/{providers-PCNF5E3K.js → providers-2YN7WGZW.js} +7 -7
- package/dist/cli/{providers-CTKQP45X.mjs → providers-NPP7DKNJ.mjs} +4 -4
- package/dist/cli/{quickstart-FTHWRVWN.js → quickstart-F3UEWVYN.js} +5 -5
- package/dist/cli/{quickstart-X7EVVWRG.mjs → quickstart-NRCBIY5D.mjs} +3 -3
- package/dist/cli/{search-73YPOFDO.mjs → search-3HZ7PFXE.mjs} +5 -5
- package/dist/cli/{search-XA5UVC3G.js → search-HOHTWO7A.js} +6 -6
- package/dist/cli/{secrets-OUMPT4FX.mjs → secrets-44DTR7F7.mjs} +4 -4
- package/dist/cli/{secrets-UOEVR73Q.js → secrets-ROFLUSZW.js} +13 -13
- package/dist/cli/{sessions-CMKXCN5Y.js → sessions-U7T5MEHM.js} +5 -5
- package/dist/cli/{sessions-ZIFGDZE7.mjs → sessions-ZGKRSQ7U.mjs} +4 -4
- package/dist/cli/{settings-ULZT2NIC.js → settings-SAFOFNX3.js} +74 -74
- package/dist/cli/{settings-OO5R3G52.mjs → settings-WDAIAP72.mjs} +7 -7
- package/dist/cli/{setup-DHGERXPZ.js → setup-SO5Y5PPR.js} +41 -41
- package/dist/cli/{setup-6GZH52OZ.mjs → setup-VZWFB35G.mjs} +6 -6
- package/dist/cli/skills-PVOBZRLZ.js +28 -0
- package/dist/cli/{skills-T3EY2656.mjs → skills-YUNBWLQ2.mjs} +4 -4
- package/dist/cli/{tools-BIMOAOTX.mjs → tools-HSBS6CL6.mjs} +5 -5
- package/dist/cli/{tools-ODXVCKO7.js → tools-HYYND5GY.js} +50 -50
- package/dist/cli/update-KTAZKIHP.js +28 -0
- package/dist/cli/{update-X4HX7Z3M.mjs → update-MENMYHFK.mjs} +6 -6
- package/dist/cli/{workflow-IVLCPFTG.js → workflow-JZIB3YKI.js} +15 -15
- package/dist/cli/{workflow-EAUFVPIP.mjs → workflow-TWGYS6II.mjs} +5 -5
- package/dist/index.js +6 -6
- package/dist/index.mjs +3 -3
- package/dist/install-integrity.json +68 -68
- 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-QDWV3TXX.js +0 -31
- package/dist/cli/client-IZGIN2ZA.js +0 -20
- package/dist/cli/git-563GYLMA.js +0 -23
- package/dist/cli/skills-Q7NUCS2W.js +0 -28
- package/dist/cli/update-UMB3ULBR.js +0 -28
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
* as a wake hint, and one exact timer for the next due row. There is
|
|
9
9
|
* deliberately no worker fleet polling cadence.
|
|
10
10
|
*/
|
|
11
|
+
import { isIsolatedRuntimeSchedulerSchema } from '../runtime-scheduler-topology';
|
|
11
12
|
import {
|
|
12
13
|
dispatchRunLedgerOutboxToLedgerBatchOnceWithClientScope,
|
|
13
14
|
postgresSchedulerNotifyChannel,
|
|
@@ -36,7 +37,17 @@ const RECOVERY_FAILURE_RETRY_MAX_MS = 60_000;
|
|
|
36
37
|
// seconds of worker deferrals. Only the dedicated projector performs this
|
|
37
38
|
// fallback; the worker fleet still never polls the outbox.
|
|
38
39
|
export const NOTIFY_UNAVAILABLE_SAFETY_WAKE_MS = 1_000;
|
|
40
|
+
/** Isolated Preview/dev schemas have no LISTEN session, so halve discovery latency. */
|
|
41
|
+
export const ISOLATED_NOTIFY_UNAVAILABLE_SAFETY_WAKE_MS = 500;
|
|
39
42
|
const MAX_TIMEOUT_MS = 2_147_483_647;
|
|
43
|
+
|
|
44
|
+
export function runLedgerOutboxNotifySafetyWakeMs(
|
|
45
|
+
schedulerSchema: string | null | undefined,
|
|
46
|
+
): number {
|
|
47
|
+
return isIsolatedRuntimeSchedulerSchema(schedulerSchema)
|
|
48
|
+
? ISOLATED_NOTIFY_UNAVAILABLE_SAFETY_WAKE_MS
|
|
49
|
+
: NOTIFY_UNAVAILABLE_SAFETY_WAKE_MS;
|
|
50
|
+
}
|
|
40
51
|
/**
|
|
41
52
|
* One projector can keep this many independent Run Ledger deliveries in
|
|
42
53
|
* flight after it has found durable work. Each delivery owns only short
|
|
@@ -63,6 +74,7 @@ export const RUN_LEDGER_OUTBOX_RECOVERY_MAX_IN_FLIGHT = 32;
|
|
|
63
74
|
// The higher exported ceiling remains available to isolated recovery callers,
|
|
64
75
|
// but it is not the steady-state production setting.
|
|
65
76
|
const RUN_LEDGER_OUTBOX_RECOVERY_PRODUCTION_IN_FLIGHT = 8;
|
|
77
|
+
const RUN_LEDGER_OUTBOX_RECOVERY_INDEX_IN_FLIGHT = 4;
|
|
66
78
|
// Admissions retain three of four claim opportunities. The fourth selects
|
|
67
79
|
// the oldest eligible causal head across all runs, preventing terminal work
|
|
68
80
|
// from starving behind continuous new admissions. An empty class never costs
|
|
@@ -78,12 +90,17 @@ export type RunLedgerOutboxRecoveryDeps = {
|
|
|
78
90
|
dispatchOnce: (
|
|
79
91
|
headPriority: RunLedgerOutboxHeadPriority,
|
|
80
92
|
) => Promise<PostgresSchedulerOutboxProjectionResult>;
|
|
93
|
+
/** Independent index deliveries share this controller and notification source. */
|
|
94
|
+
dispatchObservabilityOnce?: () => Promise<PostgresSchedulerOutboxProjectionResult>;
|
|
95
|
+
observabilityParallelism?: number;
|
|
81
96
|
/** Earliest pending retry time or active lease expiry in the durable outbox. */
|
|
82
97
|
readNextDueAt: () => Promise<Date | null>;
|
|
83
98
|
/** A direct LISTEN connection. It is a hint only; a null lease is safe. */
|
|
84
99
|
acquireNotifyHub: () => PgNotifyHubLease | null;
|
|
85
100
|
/** Bounded number of independent runs this replica may deliver at once. */
|
|
86
101
|
parallelism?: number;
|
|
102
|
+
/** Fast polling is used only when the topology intentionally has no LISTEN session. */
|
|
103
|
+
notifyUnavailableSafetyWakeMs?: number;
|
|
87
104
|
now?: () => number;
|
|
88
105
|
setTimer?: (callback: () => void, delayMs: number) => RecoveryTimer;
|
|
89
106
|
clearTimer?: (timer: RecoveryTimer) => void;
|
|
@@ -135,6 +152,8 @@ export function startRunLedgerOutboxRecovery(
|
|
|
135
152
|
const clearTimer = deps.clearTimer ?? clearTimeout;
|
|
136
153
|
const logger = deps.logger ?? console;
|
|
137
154
|
const requestedParallelism = Math.floor(deps.parallelism ?? 1);
|
|
155
|
+
const notifyUnavailableSafetyWakeMs =
|
|
156
|
+
deps.notifyUnavailableSafetyWakeMs ?? NOTIFY_UNAVAILABLE_SAFETY_WAKE_MS;
|
|
138
157
|
const parallelism = Number.isFinite(requestedParallelism)
|
|
139
158
|
? Math.max(
|
|
140
159
|
1,
|
|
@@ -144,6 +163,22 @@ export function startRunLedgerOutboxRecovery(
|
|
|
144
163
|
),
|
|
145
164
|
)
|
|
146
165
|
: 1;
|
|
166
|
+
if (deps.dispatchObservabilityOnce && parallelism < 2) {
|
|
167
|
+
throw new Error(
|
|
168
|
+
'Independent observability delivery requires at least two slots.',
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
const observabilityParallelism = deps.dispatchObservabilityOnce
|
|
172
|
+
? Math.min(
|
|
173
|
+
Math.max(1, deps.observabilityParallelism ?? 1),
|
|
174
|
+
Math.max(1, parallelism - 1),
|
|
175
|
+
)
|
|
176
|
+
: 0;
|
|
177
|
+
const lifecycleParallelism = Math.max(
|
|
178
|
+
1,
|
|
179
|
+
parallelism - observabilityParallelism,
|
|
180
|
+
);
|
|
181
|
+
let observabilityRequested = false;
|
|
147
182
|
let closed = false;
|
|
148
183
|
let requested = false;
|
|
149
184
|
let failureCount = 0;
|
|
@@ -159,22 +194,24 @@ export function startRunLedgerOutboxRecovery(
|
|
|
159
194
|
let nextDispatchId = 0;
|
|
160
195
|
let lastDispatchSettledAt: number | null = null;
|
|
161
196
|
let admissionTurns = 0;
|
|
162
|
-
const dispatchOnce =
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
admissionTurns
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
197
|
+
const dispatchOnce = async (
|
|
198
|
+
observability = false,
|
|
199
|
+
): Promise<PostgresSchedulerOutboxProjectionResult> => {
|
|
200
|
+
const oldestReady =
|
|
201
|
+
admissionTurns === ADMISSION_TURNS_PER_OLDEST_READY_TURN;
|
|
202
|
+
if (!observability) admissionTurns = oldestReady ? 0 : admissionTurns + 1;
|
|
203
|
+
const id = nextDispatchId++;
|
|
204
|
+
inFlightStartedAt.set(id, now());
|
|
205
|
+
try {
|
|
206
|
+
if (observability) return await deps.dispatchObservabilityOnce!();
|
|
207
|
+
return await deps.dispatchOnce(
|
|
208
|
+
oldestReady ? 'oldest_ready' : 'admission_first',
|
|
209
|
+
);
|
|
210
|
+
} finally {
|
|
211
|
+
inFlightStartedAt.delete(id);
|
|
212
|
+
lastDispatchSettledAt = now();
|
|
213
|
+
}
|
|
214
|
+
};
|
|
178
215
|
|
|
179
216
|
const clearWakeTimer = () => {
|
|
180
217
|
if (!timer) return;
|
|
@@ -205,6 +242,7 @@ export function startRunLedgerOutboxRecovery(
|
|
|
205
242
|
requestDrain = (reason: string) => {
|
|
206
243
|
if (closed) return;
|
|
207
244
|
requested = true;
|
|
245
|
+
observabilityRequested = !!deps.dispatchObservabilityOnce;
|
|
208
246
|
if (cooldownUntilMs !== null && now() < cooldownUntilMs) return;
|
|
209
247
|
clearWakeTimer();
|
|
210
248
|
if (drainPromise) {
|
|
@@ -240,13 +278,13 @@ export function startRunLedgerOutboxRecovery(
|
|
|
240
278
|
failureCount += 1;
|
|
241
279
|
// A rejected pooled query is normally worth exponential backoff. The
|
|
242
280
|
// exception is an unavailable LISTEN session: this dedicated projector is
|
|
243
|
-
// the one durable poller, and its
|
|
281
|
+
// the one durable poller, and its topology-specific safety wake keeps
|
|
244
282
|
// `run.created` delivery live while a direct PostgreSQL connection is
|
|
245
283
|
// refused (for example, during a connection-capacity spike). Do not let a
|
|
246
284
|
// process-local exponential cooldown silently disable that fallback.
|
|
247
285
|
const delayMs = listenerIsAvailable()
|
|
248
286
|
? boundedFailureDelayMs(failureCount)
|
|
249
|
-
:
|
|
287
|
+
: notifyUnavailableSafetyWakeMs;
|
|
250
288
|
logger.warn('[run-ledger-outbox.recovery_retry]', {
|
|
251
289
|
stage,
|
|
252
290
|
delayMs,
|
|
@@ -281,7 +319,7 @@ export function startRunLedgerOutboxRecovery(
|
|
|
281
319
|
const exactDueMs = dueAt ? Math.max(0, dueAt.getTime() - now()) : null;
|
|
282
320
|
const delayMs = listenerIsAvailable()
|
|
283
321
|
? exactDueMs
|
|
284
|
-
: Math.min(exactDueMs ?? Infinity,
|
|
322
|
+
: Math.min(exactDueMs ?? Infinity, notifyUnavailableSafetyWakeMs);
|
|
285
323
|
if (delayMs === null || !Number.isFinite(delayMs)) return;
|
|
286
324
|
clearWakeTimer();
|
|
287
325
|
timer = setTimer(
|
|
@@ -298,11 +336,13 @@ export function startRunLedgerOutboxRecovery(
|
|
|
298
336
|
const drain = async (reason: string): Promise<void> => {
|
|
299
337
|
type Delivery = {
|
|
300
338
|
id: symbol;
|
|
339
|
+
observability: boolean;
|
|
301
340
|
result:
|
|
302
341
|
| PromiseSettledResult<PostgresSchedulerOutboxProjectionResult>
|
|
303
342
|
| { status: 'skipped' };
|
|
304
343
|
};
|
|
305
344
|
const pending = new Set<symbol>();
|
|
345
|
+
const pendingObservability = new Set<symbol>();
|
|
306
346
|
const deliveries: Delivery[] = [];
|
|
307
347
|
let refill = false;
|
|
308
348
|
let dispatchFailed = false;
|
|
@@ -330,15 +370,16 @@ export function startRunLedgerOutboxRecovery(
|
|
|
330
370
|
completed = attempted = projected = retrying = blocked = 0;
|
|
331
371
|
};
|
|
332
372
|
|
|
333
|
-
const launch = () => {
|
|
373
|
+
const launch = (observability = false) => {
|
|
334
374
|
const id = Symbol();
|
|
335
375
|
pending.add(id);
|
|
376
|
+
if (observability) pendingObservability.add(id);
|
|
336
377
|
const settle = (result: Delivery['result']) => {
|
|
337
378
|
if (result.status === 'rejected' && !dispatchFailed) {
|
|
338
379
|
dispatchFailed = true;
|
|
339
380
|
scheduleFailureRetry('dispatch', result.reason);
|
|
340
381
|
}
|
|
341
|
-
deliveries.push({ id, result });
|
|
382
|
+
deliveries.push({ id, observability, result });
|
|
342
383
|
wakeActiveDrain?.();
|
|
343
384
|
};
|
|
344
385
|
// Subscribe once per delivery. Repeated Promise.race calls would retain
|
|
@@ -349,26 +390,54 @@ export function startRunLedgerOutboxRecovery(
|
|
|
349
390
|
return;
|
|
350
391
|
}
|
|
351
392
|
try {
|
|
352
|
-
settle({
|
|
393
|
+
settle({
|
|
394
|
+
status: 'fulfilled',
|
|
395
|
+
value: await dispatchOnce(observability),
|
|
396
|
+
});
|
|
353
397
|
} catch (reason) {
|
|
354
398
|
settle({ status: 'rejected', reason });
|
|
355
399
|
}
|
|
356
400
|
});
|
|
357
401
|
};
|
|
358
402
|
|
|
403
|
+
const canProbeLifecycle = () =>
|
|
404
|
+
!closed &&
|
|
405
|
+
!dispatchFailed &&
|
|
406
|
+
requested &&
|
|
407
|
+
pending.size < parallelism &&
|
|
408
|
+
pending.size - pendingObservability.size < lifecycleParallelism;
|
|
409
|
+
const canProbeObservability = () =>
|
|
410
|
+
!closed &&
|
|
411
|
+
!dispatchFailed &&
|
|
412
|
+
observabilityRequested &&
|
|
413
|
+
pending.size < parallelism &&
|
|
414
|
+
pendingObservability.size < observabilityParallelism;
|
|
415
|
+
|
|
359
416
|
for (;;) {
|
|
360
417
|
if (!closed && !dispatchFailed) {
|
|
361
418
|
// A wake grants one indexed probe, including when other slots are
|
|
362
419
|
// still delivering. Keep it pending when full so an empty result
|
|
363
420
|
// cannot consume a notification that arrived after its query began.
|
|
364
|
-
if (
|
|
421
|
+
if (canProbeObservability()) {
|
|
422
|
+
observabilityRequested = false;
|
|
423
|
+
while (
|
|
424
|
+
pendingObservability.size < observabilityParallelism &&
|
|
425
|
+
pending.size < parallelism
|
|
426
|
+
)
|
|
427
|
+
launch(true);
|
|
428
|
+
}
|
|
429
|
+
if (canProbeLifecycle()) {
|
|
365
430
|
requested = false;
|
|
366
431
|
launch();
|
|
367
432
|
}
|
|
368
433
|
// Productive completion permits immediate use of every free slot.
|
|
369
434
|
// Empty results grant no refill, so idle work cannot spin on scans.
|
|
370
435
|
if (refill) {
|
|
371
|
-
while (
|
|
436
|
+
while (
|
|
437
|
+
pending.size < parallelism &&
|
|
438
|
+
pending.size - pendingObservability.size < lifecycleParallelism
|
|
439
|
+
)
|
|
440
|
+
launch();
|
|
372
441
|
refill = false;
|
|
373
442
|
}
|
|
374
443
|
}
|
|
@@ -383,10 +452,8 @@ export function startRunLedgerOutboxRecovery(
|
|
|
383
452
|
wakeActiveDrain = resolve;
|
|
384
453
|
if (
|
|
385
454
|
deliveries.length > 0 ||
|
|
386
|
-
(
|
|
387
|
-
|
|
388
|
-
!dispatchFailed &&
|
|
389
|
-
pending.size < parallelism)
|
|
455
|
+
canProbeLifecycle() ||
|
|
456
|
+
canProbeObservability()
|
|
390
457
|
)
|
|
391
458
|
resolve();
|
|
392
459
|
});
|
|
@@ -394,6 +461,7 @@ export function startRunLedgerOutboxRecovery(
|
|
|
394
461
|
const delivery = deliveries.shift();
|
|
395
462
|
if (!delivery) continue;
|
|
396
463
|
pending.delete(delivery.id);
|
|
464
|
+
pendingObservability.delete(delivery.id);
|
|
397
465
|
if (delivery.result.status !== 'fulfilled') {
|
|
398
466
|
// Stop new claims but settle every already-started delivery before
|
|
399
467
|
// cooldown or close can hand ownership to another drain.
|
|
@@ -408,7 +476,9 @@ export function startRunLedgerOutboxRecovery(
|
|
|
408
476
|
if (completed >= parallelism) reportDeliveries();
|
|
409
477
|
// Retryable rows own durable retry clocks. The SQL claim keeps their
|
|
410
478
|
// run ordered while successful slots keep unrelated runs moving.
|
|
411
|
-
|
|
479
|
+
if (delivery.observability) {
|
|
480
|
+
if (result.attempted > 0) observabilityRequested = true;
|
|
481
|
+
} else refill = result.attempted > 0;
|
|
412
482
|
}
|
|
413
483
|
};
|
|
414
484
|
|
|
@@ -583,12 +653,37 @@ export function startRunLedgerOutboxRecoveryController(input: {
|
|
|
583
653
|
onDelivered?: (deliveries: readonly RunLedgerOutboxDeliveredRow[]) => void;
|
|
584
654
|
}): RunLedgerOutboxRecoveryController {
|
|
585
655
|
const schedulerOptions = input.schedulerOptions ?? {};
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
656
|
+
const observabilityPoolOptions: RuntimeSchedulerPoolOptions = {
|
|
657
|
+
...input.poolOptions,
|
|
658
|
+
purpose: 'observability',
|
|
659
|
+
applicationName: 'deepline-runtime-observability',
|
|
660
|
+
maxClients: RUN_LEDGER_OUTBOX_RECOVERY_INDEX_IN_FLIGHT,
|
|
661
|
+
};
|
|
662
|
+
const dispatch = (
|
|
663
|
+
headPriority: RunLedgerOutboxHeadPriority,
|
|
664
|
+
searchOnly: boolean,
|
|
665
|
+
) =>
|
|
666
|
+
dispatchRunLedgerOutboxToLedgerBatchOnceWithClientScope(
|
|
667
|
+
(operation) =>
|
|
668
|
+
withRuntimeSchedulerClient(
|
|
669
|
+
searchOnly ? observabilityPoolOptions : input.poolOptions,
|
|
670
|
+
operation,
|
|
671
|
+
),
|
|
672
|
+
{
|
|
673
|
+
tokenAuthority: 'gateway',
|
|
674
|
+
materializeObservability: true,
|
|
675
|
+
searchOnly,
|
|
676
|
+
withObservabilityClient: (operation) =>
|
|
677
|
+
withRuntimeSchedulerClient(observabilityPoolOptions, operation),
|
|
678
|
+
limit: 8,
|
|
679
|
+
headPriority,
|
|
680
|
+
// The lease holder delivers a run's terminal committed during its
|
|
681
|
+
// append, instead of leaving it for the next wave.
|
|
682
|
+
continueThroughTerminal: true,
|
|
683
|
+
...(input.onDelivered ? { onDelivered: input.onDelivered } : {}),
|
|
684
|
+
},
|
|
685
|
+
schedulerOptions,
|
|
686
|
+
);
|
|
592
687
|
return startRunLedgerOutboxRecovery({
|
|
593
688
|
acquireNotifyHub: () =>
|
|
594
689
|
input.useDirectNotify === false
|
|
@@ -599,38 +694,17 @@ export function startRunLedgerOutboxRecoveryController(input: {
|
|
|
599
694
|
schedulerOptions,
|
|
600
695
|
}),
|
|
601
696
|
),
|
|
602
|
-
dispatchOnce:
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
if (searchOnly) searchInFlight += 1;
|
|
606
|
-
try {
|
|
607
|
-
return await dispatchRunLedgerOutboxToLedgerBatchOnceWithClientScope(
|
|
608
|
-
(operation) =>
|
|
609
|
-
withRuntimeSchedulerClient(input.poolOptions, operation),
|
|
610
|
-
{
|
|
611
|
-
tokenAuthority: 'gateway',
|
|
612
|
-
materializeObservability: true,
|
|
613
|
-
// One durable controller, with half its capacity reserved for
|
|
614
|
-
// lifecycle delivery even when every search operation is blocked.
|
|
615
|
-
searchOnly,
|
|
616
|
-
limit: 8,
|
|
617
|
-
headPriority,
|
|
618
|
-
// The lease holder delivers a run's terminal committed during its
|
|
619
|
-
// append, instead of leaving it for the next wave.
|
|
620
|
-
continueThroughTerminal: true,
|
|
621
|
-
...(input.onDelivered ? { onDelivered: input.onDelivered } : {}),
|
|
622
|
-
},
|
|
623
|
-
schedulerOptions,
|
|
624
|
-
);
|
|
625
|
-
} finally {
|
|
626
|
-
if (searchOnly) searchInFlight -= 1;
|
|
627
|
-
}
|
|
628
|
-
},
|
|
697
|
+
dispatchOnce: (headPriority) => dispatch(headPriority, false),
|
|
698
|
+
dispatchObservabilityOnce: () => dispatch('oldest_ready', true),
|
|
699
|
+
observabilityParallelism: RUN_LEDGER_OUTBOX_RECOVERY_INDEX_IN_FLIGHT,
|
|
629
700
|
// `dispatchRunLedgerOutboxToLedgerBatchOnceWithClientScope` releases each
|
|
630
701
|
// short scheduler checkout before it calls the Vercel gateway. The two
|
|
631
702
|
// replicas therefore drain up to sixteen independent runs concurrently
|
|
632
703
|
// without turning one outbox notification into sixty-four head scans.
|
|
633
704
|
parallelism: RUN_LEDGER_OUTBOX_RECOVERY_PRODUCTION_IN_FLIGHT,
|
|
705
|
+
notifyUnavailableSafetyWakeMs: runLedgerOutboxNotifySafetyWakeMs(
|
|
706
|
+
schedulerOptions.schema,
|
|
707
|
+
),
|
|
634
708
|
readNextDueAt: () =>
|
|
635
709
|
withRuntimeSchedulerClient(input.poolOptions, (client) =>
|
|
636
710
|
readPostgresSchedulerOutboxNextDueAt(client, schedulerOptions),
|
package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-event-search.ts
CHANGED
|
@@ -61,7 +61,7 @@ const RUNTIME_EVENT_LOG_POSITION_EXPRESSION = `jsonb_set(
|
|
|
61
61
|
// Migration readiness tracks this projection body independently of scheduler
|
|
62
62
|
// wire and schema versions. Bump when a changed trigger must be reinstalled.
|
|
63
63
|
export const RUNTIME_EVENT_SEARCH_OUTBOX_PROJECTION_MARKER =
|
|
64
|
-
'runtime-event-search-origin-batches-log-metadata';
|
|
64
|
+
'runtime-event-search-origin-batches-log-metadata-point-replay';
|
|
65
65
|
/** Trusted trigger-authored state; absent on already-projected legacy rows. */
|
|
66
66
|
export const RUNTIME_EVENT_DEFERRED_PROJECTION_FIELD =
|
|
67
67
|
'_runtimeSearchProjectionPending';
|
|
@@ -1310,8 +1310,16 @@ export async function attachRuntimeEventSearchTriggers(
|
|
|
1310
1310
|
-- Tombstones retain digest/identity: retry never restores an expired body.
|
|
1311
1311
|
SELECT count(*) INTO mismatches
|
|
1312
1312
|
FROM jsonb_array_elements(item->'lines') WITH ORDINALITY AS entries(body, ordinal)
|
|
1313
|
-
|
|
1314
|
-
|
|
1313
|
+
-- Keep each replay proof on the journal primary key. An unrestricted
|
|
1314
|
+
-- join can hash the whole shared org history for a small JSON batch.
|
|
1315
|
+
LEFT JOIN LATERAL (
|
|
1316
|
+
SELECT event.run_id, event.kind, event.source_digest
|
|
1317
|
+
FROM runtime_observability.events event
|
|
1318
|
+
WHERE event.runtime_scope = ${quoteLiteral(scope)} AND event.org_id = run_org
|
|
1319
|
+
AND event.event_id = 'log-origin:' || observation.run_id || ':' || (item->'lineIds'->>(ordinal-1)::int)
|
|
1320
|
+
-- The primary key admits one row; retain a parameterized point lookup.
|
|
1321
|
+
LIMIT 1
|
|
1322
|
+
) event ON true
|
|
1315
1323
|
WHERE event.run_id IS DISTINCT FROM observation.run_id OR event.kind IS DISTINCT FROM ${RUN_EVENT_KIND_SQL_LITERAL.logAppended}
|
|
1316
1324
|
OR event.source_digest IS DISTINCT FROM CASE WHEN NULLIF(item->'lineContexts'->(ordinal-1)::int, 'null'::jsonb) IS NULL
|
|
1317
1325
|
THEN encode(sha256(convert_to(body #>> '{}','UTF8')),'hex')
|
|
@@ -1982,11 +1990,15 @@ export async function attachRuntimeEventSearchTriggers(
|
|
|
1982
1990
|
DO UPDATE SET last_seq = runtime_observability.run_log_cursors.last_seq + EXCLUDED.last_seq,
|
|
1983
1991
|
updated_at = clock_timestamp()
|
|
1984
1992
|
RETURNING last_seq INTO assigned_seq;
|
|
1993
|
+
-- Bound sequence assignment before joining the variable-size ID list.
|
|
1994
|
+
-- Shared-journal history from other runs is never a candidate.
|
|
1985
1995
|
UPDATE runtime_observability.events AS event
|
|
1986
1996
|
SET log_seq = assigned_seq - line_count + fresh.ordinality
|
|
1987
1997
|
FROM unnest(fresh_event_ids) WITH ORDINALITY AS fresh(event_id, ordinality)
|
|
1988
1998
|
WHERE event.runtime_scope = ${quoteLiteral(scope)}
|
|
1989
1999
|
AND event.org_id = run_org
|
|
2000
|
+
AND event.run_id = observation.run_id
|
|
2001
|
+
AND event.event_id = ANY(fresh_event_ids)
|
|
1990
2002
|
AND event.event_id = fresh.event_id;
|
|
1991
2003
|
END IF;
|
|
1992
2004
|
RETURN;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
var _chunkBXYKLY5Tjs = require('./chunk-BXYKLY5T.js');
|
|
13
|
+
require('./chunk-TOAXEXTC.js');
|
|
14
|
+
require('./chunk-2Q4LGPVP.js');
|
|
15
|
+
require('./chunk-XNYIZMNQ.js');
|
|
16
|
+
require('./chunk-BUKTFUM7.js');
|
|
17
|
+
require('./chunk-7P5AA3SN.js');
|
|
18
|
+
require('./chunk-OG64RBAC.js');
|
|
19
|
+
require('./chunk-COGTRVWW.js');
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
exports.EXIT_WORKSPACE_MISMATCH = _chunkBXYKLY5Tjs.EXIT_WORKSPACE_MISMATCH; exports.clearPendingClaim = _chunkBXYKLY5Tjs.clearPendingClaim; exports.clearSatisfiedPendingClaim = _chunkBXYKLY5Tjs.clearSatisfiedPendingClaim; exports.handleRegister = _chunkBXYKLY5Tjs.handleRegister; exports.handleStatus = _chunkBXYKLY5Tjs.handleStatus; exports.handleWait = _chunkBXYKLY5Tjs.handleWait; exports.readPendingAuthClaim = _chunkBXYKLY5Tjs.readPendingAuthClaim; exports.registerAuthCommands = _chunkBXYKLY5Tjs.registerAuthCommands; exports.reportSetupCompleted = _chunkBXYKLY5Tjs.reportSetupCompleted; exports.resolvePendingAuthClaimForResume = _chunkBXYKLY5Tjs.resolvePendingAuthClaimForResume;
|
|
@@ -9,11 +9,11 @@ import {
|
|
|
9
9
|
registerAuthCommands,
|
|
10
10
|
reportSetupCompleted,
|
|
11
11
|
resolvePendingAuthClaimForResume
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-RES6RQXX.mjs";
|
|
13
|
+
import "./chunk-U6G52KUV.mjs";
|
|
14
|
+
import "./chunk-YE5PJMFK.mjs";
|
|
15
15
|
import "./chunk-DLIRSHV6.mjs";
|
|
16
|
-
import "./chunk-
|
|
16
|
+
import "./chunk-6IOQ43VG.mjs";
|
|
17
17
|
import "./chunk-NXGCO4JB.mjs";
|
|
18
18
|
import "./chunk-WZYKRD7T.mjs";
|
|
19
19
|
import "./chunk-KRD6H754.mjs";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DeeplineClient,
|
|
3
3
|
iterateCursorPages
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-FJTNI2TE.mjs";
|
|
5
5
|
import "./chunk-CBVIJSHF.mjs";
|
|
6
6
|
import {
|
|
7
7
|
createTimestampedName,
|
|
@@ -9,13 +9,13 @@ import {
|
|
|
9
9
|
openInBrowser,
|
|
10
10
|
printCommandEnvelope,
|
|
11
11
|
shouldEmitJson
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-U6G52KUV.mjs";
|
|
13
13
|
import {
|
|
14
14
|
AuthError,
|
|
15
15
|
ConfigError
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-YE5PJMFK.mjs";
|
|
17
17
|
import "./chunk-DLIRSHV6.mjs";
|
|
18
|
-
import "./chunk-
|
|
18
|
+
import "./chunk-6IOQ43VG.mjs";
|
|
19
19
|
import "./chunk-GVUJJJ5G.mjs";
|
|
20
20
|
import {
|
|
21
21
|
DeeplineError
|