deepline 0.3.220 → 0.3.222
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/play-runtime/app-runtime-api.ts +10 -103
- package/dist/bundling-sources/shared_libs/play-runtime/deployment/fly-registry.ts +2 -1
- package/dist/bundling-sources/shared_libs/play-runtime/run-ledger-event-transport.ts +110 -0
- package/dist/bundling-sources/shared_libs/play-runtime/run-ledger-projection-contract.ts +23 -0
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts +15 -11
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres-pool.ts +61 -4
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +19 -1
- package/dist/cli/index.js +1 -1
- package/dist/cli/index.mjs +1 -1
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/dist/install-integrity.json +1 -0
- package/dist/release.d.mts +1 -1
- package/dist/release.d.ts +1 -1
- package/dist/release.js +1 -1
- package/dist/release.mjs +1 -1
- package/package.json +1 -1
|
@@ -200,7 +200,7 @@ export const SDK_RELEASE = {
|
|
|
200
200
|
// getters keep their established compatibility behavior.
|
|
201
201
|
// 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
|
|
202
202
|
// 0.3.90 is the first deliberately versioned SDK release for API v3.
|
|
203
|
-
version: '0.3.
|
|
203
|
+
version: '0.3.222',
|
|
204
204
|
updateSummary:
|
|
205
205
|
'Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.',
|
|
206
206
|
packageCapabilities: {
|
|
@@ -52,8 +52,10 @@ import { PLAY_RUNTIME_API_COMPAT_PATH } from './/runtime-api-paths';
|
|
|
52
52
|
import {
|
|
53
53
|
buildRunLedgerEventsIdempotencyKey,
|
|
54
54
|
isRunLedgerProjectionLeaseLostReason,
|
|
55
|
+
type RunLedgerProjectionChunk,
|
|
55
56
|
type RunLedgerProjectionLeaseLostReason,
|
|
56
57
|
} from './run-ledger-projection-contract';
|
|
58
|
+
import { partitionRunEventsForAppRuntime } from './run-ledger-event-transport';
|
|
57
59
|
import {
|
|
58
60
|
RUNTIME_API_ACCEPTS_HEADER,
|
|
59
61
|
gzipRuntimeApiRequestBody,
|
|
@@ -79,6 +81,8 @@ import {
|
|
|
79
81
|
type RuntimeTrafficPolicy,
|
|
80
82
|
} from './/runtime-traffic-policy';
|
|
81
83
|
|
|
84
|
+
export type { RunLedgerProjectionChunk } from './run-ledger-projection-contract';
|
|
85
|
+
|
|
82
86
|
export type StoredPlayArtifactPayload = {
|
|
83
87
|
sourceCode: string;
|
|
84
88
|
codeFormat: 'function' | 'cjs_module' | 'esm_module';
|
|
@@ -170,6 +174,7 @@ type RuntimeApiRequest =
|
|
|
170
174
|
idempotencyKey?: string;
|
|
171
175
|
deliveryIdempotencyKey?: string;
|
|
172
176
|
deliveryLeaseOwner?: string;
|
|
177
|
+
projectionChunk?: RunLedgerProjectionChunk;
|
|
173
178
|
}
|
|
174
179
|
| {
|
|
175
180
|
action: 'start_run';
|
|
@@ -499,9 +504,8 @@ const runStatusUpdateChains = new Map<string, Promise<void>>();
|
|
|
499
504
|
const receiptClaimResponseTimeoutFaults = new Map<string, number>();
|
|
500
505
|
const receiptClaimQueryHoldFaults = new Set<string>();
|
|
501
506
|
const RECEIPT_CLAIM_RESPONSE_TIMEOUT_FAULT_LIMIT = 1_000;
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
const appRuntimeTextEncoder = new TextEncoder();
|
|
507
|
+
|
|
508
|
+
export { partitionRunEventsForAppRuntime } from './run-ledger-event-transport';
|
|
505
509
|
|
|
506
510
|
function shouldSuppressBulkClaimResponse(input: {
|
|
507
511
|
body: RuntimeApiRequest;
|
|
@@ -593,106 +597,6 @@ async function suppressBulkClaimResponseUntilTimeout(
|
|
|
593
597
|
});
|
|
594
598
|
}
|
|
595
599
|
|
|
596
|
-
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
597
|
-
return Boolean(value && typeof value === 'object' && !Array.isArray(value));
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
function splitRunEventForAppRuntime(
|
|
601
|
-
event: PlayRunLedgerIngressEvent,
|
|
602
|
-
): PlayRunLedgerIngressEvent[] {
|
|
603
|
-
const eventType =
|
|
604
|
-
typeof event.key === 'string'
|
|
605
|
-
? event.key
|
|
606
|
-
: typeof event.type === 'string'
|
|
607
|
-
? event.type
|
|
608
|
-
: null;
|
|
609
|
-
const payload = isRecord(event.payload) ? event.payload : null;
|
|
610
|
-
const payloadLines = payload?.lines;
|
|
611
|
-
const payloadOwnsLines = Array.isArray(payloadLines);
|
|
612
|
-
const rawLines = payloadOwnsLines ? payloadLines : event.lines;
|
|
613
|
-
const lines = Array.isArray(rawLines)
|
|
614
|
-
? rawLines.filter((line): line is string => typeof line === 'string')
|
|
615
|
-
: [];
|
|
616
|
-
if (eventType !== 'log.appended' || lines.length === 0) return [event];
|
|
617
|
-
const payloadChannelOffset =
|
|
618
|
-
typeof payload?.channelOffset === 'number'
|
|
619
|
-
? payload.channelOffset
|
|
620
|
-
: undefined;
|
|
621
|
-
const eventChannelOffset =
|
|
622
|
-
typeof event.channelOffset === 'number' ? event.channelOffset : undefined;
|
|
623
|
-
const split: PlayRunLedgerIngressEvent[] = [];
|
|
624
|
-
const { lines: _outerLines, ...eventWithoutOuterLines } = event;
|
|
625
|
-
let index = 0;
|
|
626
|
-
while (index < lines.length) {
|
|
627
|
-
const start = index;
|
|
628
|
-
let bytes = 2;
|
|
629
|
-
while (index < lines.length) {
|
|
630
|
-
const lineBytes = appRuntimeTextEncoder.encode(
|
|
631
|
-
JSON.stringify(lines[index]!),
|
|
632
|
-
).length;
|
|
633
|
-
if (
|
|
634
|
-
index > start &&
|
|
635
|
-
bytes + lineBytes + 1 > APP_RUNTIME_LOG_EVENT_MAX_JSON_BYTES
|
|
636
|
-
) {
|
|
637
|
-
break;
|
|
638
|
-
}
|
|
639
|
-
bytes += lineBytes + 1;
|
|
640
|
-
index += 1;
|
|
641
|
-
}
|
|
642
|
-
const batchLines = lines.slice(start, index);
|
|
643
|
-
split.push(
|
|
644
|
-
payload
|
|
645
|
-
? {
|
|
646
|
-
...eventWithoutOuterLines,
|
|
647
|
-
...(payloadOwnsLines ? {} : { lines: batchLines }),
|
|
648
|
-
payload: {
|
|
649
|
-
...payload,
|
|
650
|
-
...(payloadOwnsLines ? { lines: batchLines } : {}),
|
|
651
|
-
...(payloadChannelOffset === undefined
|
|
652
|
-
? {}
|
|
653
|
-
: { channelOffset: payloadChannelOffset + start }),
|
|
654
|
-
},
|
|
655
|
-
...(eventChannelOffset === undefined
|
|
656
|
-
? {}
|
|
657
|
-
: { channelOffset: eventChannelOffset + start }),
|
|
658
|
-
}
|
|
659
|
-
: {
|
|
660
|
-
...event,
|
|
661
|
-
lines: batchLines,
|
|
662
|
-
...(eventChannelOffset === undefined
|
|
663
|
-
? {}
|
|
664
|
-
: { channelOffset: eventChannelOffset + start }),
|
|
665
|
-
},
|
|
666
|
-
);
|
|
667
|
-
}
|
|
668
|
-
return split;
|
|
669
|
-
}
|
|
670
|
-
|
|
671
|
-
export function partitionRunEventsForAppRuntime(
|
|
672
|
-
events: readonly PlayRunLedgerIngressEvent[],
|
|
673
|
-
): PlayRunLedgerIngressEvent[][] {
|
|
674
|
-
const batches: PlayRunLedgerIngressEvent[][] = [];
|
|
675
|
-
let current: PlayRunLedgerIngressEvent[] = [];
|
|
676
|
-
let currentBytes = 2;
|
|
677
|
-
for (const event of events.flatMap(splitRunEventForAppRuntime)) {
|
|
678
|
-
const eventBytes = appRuntimeTextEncoder.encode(
|
|
679
|
-
JSON.stringify(event),
|
|
680
|
-
).length;
|
|
681
|
-
if (
|
|
682
|
-
current.length > 0 &&
|
|
683
|
-
currentBytes + eventBytes + 1 > APP_RUNTIME_EVENT_BATCH_MAX_JSON_BYTES
|
|
684
|
-
) {
|
|
685
|
-
batches.push(current);
|
|
686
|
-
current = [];
|
|
687
|
-
currentBytes = 2;
|
|
688
|
-
}
|
|
689
|
-
current.push(event);
|
|
690
|
-
currentBytes += eventBytes + 1;
|
|
691
|
-
}
|
|
692
|
-
if (current.length > 0) batches.push(current);
|
|
693
|
-
return batches;
|
|
694
|
-
}
|
|
695
|
-
|
|
696
600
|
async function appendRunEventBatchesViaAppRuntime(
|
|
697
601
|
context: WorkerRuntimeApiContext,
|
|
698
602
|
input: { playId: string; events: readonly PlayRunLedgerEvent[] },
|
|
@@ -2436,6 +2340,9 @@ export async function projectRunEventsViaAppRuntime(
|
|
|
2436
2340
|
idempotencyKey,
|
|
2437
2341
|
deliveryIdempotencyKey: input.idempotencyKey,
|
|
2438
2342
|
deliveryLeaseOwner: input.deliveryLeaseOwner,
|
|
2343
|
+
...(batches.length > 1
|
|
2344
|
+
? { projectionChunk: { index, count: batches.length } }
|
|
2345
|
+
: {}),
|
|
2439
2346
|
};
|
|
2440
2347
|
// The durable outbox owns recovery; this helper does not retry OCCs or
|
|
2441
2348
|
// other delivery failures inside an already-leased invocation.
|
|
@@ -96,7 +96,8 @@ export function runtimeImageManifestExists(
|
|
|
96
96
|
throw new Error('Fly registry manifest probe exhausted without a result.');
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
|
|
99
|
+
// Registry reachability outages can outlast three bounded auth requests.
|
|
100
|
+
export const FLY_REGISTRY_AUTH_ATTEMPTS = 5;
|
|
100
101
|
const FLY_REGISTRY_AUTH_RETRY_DELAY_MS = 1_500;
|
|
101
102
|
|
|
102
103
|
/**
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import type { PlayRunLedgerIngressEvent } from './run-ledger';
|
|
2
|
+
|
|
3
|
+
const APP_RUNTIME_LOG_EVENT_MAX_JSON_BYTES = 128 * 1024;
|
|
4
|
+
const APP_RUNTIME_EVENT_BATCH_MAX_JSON_BYTES = 512 * 1024;
|
|
5
|
+
const appRuntimeTextEncoder = new TextEncoder();
|
|
6
|
+
|
|
7
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
8
|
+
return Boolean(value && typeof value === 'object' && !Array.isArray(value));
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function splitRunEventForAppRuntime(
|
|
12
|
+
event: PlayRunLedgerIngressEvent,
|
|
13
|
+
): PlayRunLedgerIngressEvent[] {
|
|
14
|
+
const eventType =
|
|
15
|
+
typeof event.key === 'string'
|
|
16
|
+
? event.key
|
|
17
|
+
: typeof event.type === 'string'
|
|
18
|
+
? event.type
|
|
19
|
+
: null;
|
|
20
|
+
const payload = isRecord(event.payload) ? event.payload : null;
|
|
21
|
+
const payloadLines = payload?.lines;
|
|
22
|
+
const payloadOwnsLines = Array.isArray(payloadLines);
|
|
23
|
+
const rawLines = payloadOwnsLines ? payloadLines : event.lines;
|
|
24
|
+
const lines = Array.isArray(rawLines)
|
|
25
|
+
? rawLines.filter((line): line is string => typeof line === 'string')
|
|
26
|
+
: [];
|
|
27
|
+
if (eventType !== 'log.appended' || lines.length === 0) return [event];
|
|
28
|
+
const payloadChannelOffset =
|
|
29
|
+
typeof payload?.channelOffset === 'number'
|
|
30
|
+
? payload.channelOffset
|
|
31
|
+
: undefined;
|
|
32
|
+
const eventChannelOffset =
|
|
33
|
+
typeof event.channelOffset === 'number' ? event.channelOffset : undefined;
|
|
34
|
+
const split: PlayRunLedgerIngressEvent[] = [];
|
|
35
|
+
const { lines: _outerLines, ...eventWithoutOuterLines } = event;
|
|
36
|
+
let index = 0;
|
|
37
|
+
while (index < lines.length) {
|
|
38
|
+
const start = index;
|
|
39
|
+
let bytes = 2;
|
|
40
|
+
while (index < lines.length) {
|
|
41
|
+
const lineBytes = appRuntimeTextEncoder.encode(
|
|
42
|
+
JSON.stringify(lines[index]!),
|
|
43
|
+
).length;
|
|
44
|
+
if (
|
|
45
|
+
index > start &&
|
|
46
|
+
bytes + lineBytes + 1 > APP_RUNTIME_LOG_EVENT_MAX_JSON_BYTES
|
|
47
|
+
) {
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
bytes += lineBytes + 1;
|
|
51
|
+
index += 1;
|
|
52
|
+
}
|
|
53
|
+
const batchLines = lines.slice(start, index);
|
|
54
|
+
split.push(
|
|
55
|
+
payload
|
|
56
|
+
? {
|
|
57
|
+
...eventWithoutOuterLines,
|
|
58
|
+
...(payloadOwnsLines ? {} : { lines: batchLines }),
|
|
59
|
+
payload: {
|
|
60
|
+
...payload,
|
|
61
|
+
...(payloadOwnsLines ? { lines: batchLines } : {}),
|
|
62
|
+
...(payloadChannelOffset === undefined
|
|
63
|
+
? {}
|
|
64
|
+
: { channelOffset: payloadChannelOffset + start }),
|
|
65
|
+
},
|
|
66
|
+
...(eventChannelOffset === undefined
|
|
67
|
+
? {}
|
|
68
|
+
: { channelOffset: eventChannelOffset + start }),
|
|
69
|
+
}
|
|
70
|
+
: {
|
|
71
|
+
...event,
|
|
72
|
+
lines: batchLines,
|
|
73
|
+
...(eventChannelOffset === undefined
|
|
74
|
+
? {}
|
|
75
|
+
: { channelOffset: eventChannelOffset + start }),
|
|
76
|
+
},
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
return split;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Reproduce the exact event and byte boundaries used by the App Runtime API.
|
|
84
|
+
* The outbox lease verifier uses this same function to validate each chunk
|
|
85
|
+
* against its canonical event prefix before accepting a projection.
|
|
86
|
+
*/
|
|
87
|
+
export function partitionRunEventsForAppRuntime(
|
|
88
|
+
events: readonly PlayRunLedgerIngressEvent[],
|
|
89
|
+
): PlayRunLedgerIngressEvent[][] {
|
|
90
|
+
const batches: PlayRunLedgerIngressEvent[][] = [];
|
|
91
|
+
let current: PlayRunLedgerIngressEvent[] = [];
|
|
92
|
+
let currentBytes = 2;
|
|
93
|
+
for (const event of events.flatMap(splitRunEventForAppRuntime)) {
|
|
94
|
+
const eventBytes = appRuntimeTextEncoder.encode(
|
|
95
|
+
JSON.stringify(event),
|
|
96
|
+
).length;
|
|
97
|
+
if (
|
|
98
|
+
current.length > 0 &&
|
|
99
|
+
currentBytes + eventBytes + 1 > APP_RUNTIME_EVENT_BATCH_MAX_JSON_BYTES
|
|
100
|
+
) {
|
|
101
|
+
batches.push(current);
|
|
102
|
+
current = [];
|
|
103
|
+
currentBytes = 2;
|
|
104
|
+
}
|
|
105
|
+
current.push(event);
|
|
106
|
+
currentBytes += eventBytes + 1;
|
|
107
|
+
}
|
|
108
|
+
if (current.length > 0) batches.push(current);
|
|
109
|
+
return batches;
|
|
110
|
+
}
|
|
@@ -10,6 +10,29 @@ const UUID_PATTERN =
|
|
|
10
10
|
/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
11
11
|
const SHA256_HEX_PATTERN = /^[0-9a-f]{64}$/i;
|
|
12
12
|
|
|
13
|
+
/** Identifies one bounded transport piece of a canonical outbox projection. */
|
|
14
|
+
export type RunLedgerProjectionChunk = {
|
|
15
|
+
index: number;
|
|
16
|
+
count: number;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/** Shared wire validation for the app route and the outbox lease verifier. */
|
|
20
|
+
export function isRunLedgerProjectionChunk(
|
|
21
|
+
value: unknown,
|
|
22
|
+
): value is RunLedgerProjectionChunk {
|
|
23
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
const candidate = value as Record<string, unknown>;
|
|
27
|
+
return (
|
|
28
|
+
Number.isSafeInteger(candidate.index) &&
|
|
29
|
+
Number.isSafeInteger(candidate.count) &&
|
|
30
|
+
Number(candidate.index) >= 0 &&
|
|
31
|
+
Number(candidate.count) > 1 &&
|
|
32
|
+
Number(candidate.index) < Number(candidate.count)
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
13
36
|
export const RUN_LEDGER_PROJECTION_LEASE_LOST_REASONS = [
|
|
14
37
|
'delivery_lease_not_current',
|
|
15
38
|
'head_lease_missing',
|
package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/absurd-runtime-worker.ts
CHANGED
|
@@ -351,12 +351,14 @@ const HEARTBEAT_CLAIM_TIMEOUT_SECONDS = RUNTIME_CLAIM_LEASE_SECONDS;
|
|
|
351
351
|
*/
|
|
352
352
|
export const ABSURD_IDLE_POLL_INTERVAL_SECONDS = 30;
|
|
353
353
|
/**
|
|
354
|
-
*
|
|
355
|
-
*
|
|
356
|
-
*
|
|
357
|
-
* may add latency but must not invent a terminal result outside that policy.
|
|
354
|
+
* Worker modes that intentionally have no wake hook keep a fast durable poll.
|
|
355
|
+
* Active lanes with an election hook use the slower standby cadence below
|
|
356
|
+
* when they are not the elected listener.
|
|
358
357
|
*/
|
|
359
358
|
export const ABSURD_WAKE_UNAVAILABLE_POLL_INTERVAL_MS = 1_000;
|
|
359
|
+
/** A standby lane still discovers new work durably if its elected listener is unavailable. */
|
|
360
|
+
export const ABSURD_ACTIVE_STANDBY_POLL_INTERVAL_MS =
|
|
361
|
+
ABSURD_IDLE_POLL_INTERVAL_SECONDS * 1000;
|
|
360
362
|
/**
|
|
361
363
|
* An adopted (retired) lane is served by durable polling only. Its parked
|
|
362
364
|
* sleeps and event waits already tolerate the adoption rotation (minutes), so
|
|
@@ -5681,8 +5683,8 @@ export function selectAbsurdAdoptionQueues(input: {
|
|
|
5681
5683
|
*
|
|
5682
5684
|
* - No `onWake`: an adopted queue never opens a direct LISTEN session (see
|
|
5683
5685
|
* `ABSURD_ADOPTED_LANE_POLL_INTERVAL_MS`).
|
|
5684
|
-
* - `idlePollFallbackMs` is the 30-second durable bound
|
|
5685
|
-
*
|
|
5686
|
+
* - `idlePollFallbackMs` is the same 30-second durable bound used by active
|
|
5687
|
+
* lanes waiting for their elected listener.
|
|
5686
5688
|
* - `nextPollDelayMs` still shortens the wait to the lane's next indexed due
|
|
5687
5689
|
* transition, so an already-due parked wake is claimed on the next pass.
|
|
5688
5690
|
*/
|
|
@@ -7066,8 +7068,9 @@ export type AbsurdWorkerWakeHook = ((
|
|
|
7066
7068
|
export function resolveAbsurdIdlePollFallbackMs(
|
|
7067
7069
|
onWake: AbsurdWorkerWakeHook | undefined,
|
|
7068
7070
|
): number | null {
|
|
7069
|
-
|
|
7070
|
-
|
|
7071
|
+
if (onWake?.isListening() === true) return null;
|
|
7072
|
+
return onWake
|
|
7073
|
+
? ABSURD_ACTIVE_STANDBY_POLL_INTERVAL_MS
|
|
7071
7074
|
: ABSURD_WAKE_UNAVAILABLE_POLL_INTERVAL_MS;
|
|
7072
7075
|
}
|
|
7073
7076
|
|
|
@@ -7301,9 +7304,10 @@ export async function startRuntimeWorkerHost(
|
|
|
7301
7304
|
if (!nextDue.dueAt) return null;
|
|
7302
7305
|
return nextDue.dueAt.getTime() - Date.now();
|
|
7303
7306
|
}),
|
|
7304
|
-
// Once this lane is the elected healthy listener,
|
|
7305
|
-
//
|
|
7306
|
-
//
|
|
7307
|
+
// Once this lane is the elected healthy listener, a transactional NOTIFY
|
|
7308
|
+
// wakes it. Standby/down lanes use a 30-second safety poll to avoid
|
|
7309
|
+
// repeating empty claims on every worker; the indexed next-due read still
|
|
7310
|
+
// shortens the wait for known deadlines.
|
|
7307
7311
|
idlePollFallbackMs: () => resolveAbsurdIdlePollFallbackMs(onWake),
|
|
7308
7312
|
onWake,
|
|
7309
7313
|
fatalOnLeaseTimeout: false,
|
|
@@ -327,6 +327,7 @@ type PoolAdmissionWaiter = {
|
|
|
327
327
|
* burst of executor-token lookups into starvation for new durable launches.
|
|
328
328
|
*/
|
|
329
329
|
const MAX_CONSECUTIVE_CRITICAL_ADMISSIONS = 1;
|
|
330
|
+
const ADMISSION_REJECTION_LOG_INTERVAL_MS = 10_000;
|
|
330
331
|
|
|
331
332
|
/**
|
|
332
333
|
* Keep priority outside `pg.Pool`: once pg-pool owns a checkout request it is
|
|
@@ -393,6 +394,10 @@ export class RuntimeSchedulerPoolAdmission {
|
|
|
393
394
|
return this.#waiting.ordinary.length + this.#waiting.critical.length;
|
|
394
395
|
}
|
|
395
396
|
|
|
397
|
+
get activeCount(): number {
|
|
398
|
+
return this.#active;
|
|
399
|
+
}
|
|
400
|
+
|
|
396
401
|
#grant(): () => void {
|
|
397
402
|
this.#active += 1;
|
|
398
403
|
let released = false;
|
|
@@ -429,6 +434,10 @@ type PoolEntry = {
|
|
|
429
434
|
maxClients: number;
|
|
430
435
|
maxAcquireQueueDepth: number;
|
|
431
436
|
admission: RuntimeSchedulerPoolAdmission;
|
|
437
|
+
admissionRejectionLog?: {
|
|
438
|
+
lastLoggedAt: number | null;
|
|
439
|
+
suppressedRejections: number;
|
|
440
|
+
};
|
|
432
441
|
breaker: BreakerState;
|
|
433
442
|
stats: {
|
|
434
443
|
acquires: number;
|
|
@@ -585,6 +594,39 @@ function recordCapacityRejection(entry: PoolEntry, error: unknown): void {
|
|
|
585
594
|
});
|
|
586
595
|
}
|
|
587
596
|
|
|
597
|
+
function recordAdmissionSaturation(
|
|
598
|
+
entry: PoolEntry,
|
|
599
|
+
priority: RuntimeSchedulerPoolPriority,
|
|
600
|
+
waitMs: number,
|
|
601
|
+
): void {
|
|
602
|
+
entry.stats.saturationRejections += 1;
|
|
603
|
+
const now = Date.now();
|
|
604
|
+
const logState = (entry.admissionRejectionLog ??= {
|
|
605
|
+
lastLoggedAt: null,
|
|
606
|
+
suppressedRejections: 0,
|
|
607
|
+
});
|
|
608
|
+
if (
|
|
609
|
+
logState.lastLoggedAt !== null &&
|
|
610
|
+
now - logState.lastLoggedAt < ADMISSION_REJECTION_LOG_INTERVAL_MS
|
|
611
|
+
) {
|
|
612
|
+
logState.suppressedRejections += 1;
|
|
613
|
+
return;
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
console.warn('[runtime-scheduler-pool.admission_rejected]', {
|
|
617
|
+
stage: 'admission',
|
|
618
|
+
priority,
|
|
619
|
+
waitMs: Math.max(0, waitMs),
|
|
620
|
+
maxClients: entry.maxClients,
|
|
621
|
+
activeOperations: entry.admission.activeCount,
|
|
622
|
+
remainingWaiters: entry.admission.waitingCount,
|
|
623
|
+
maxWaitingClients: entry.maxAcquireQueueDepth,
|
|
624
|
+
suppressedRejectionsSinceLastLog: logState.suppressedRejections,
|
|
625
|
+
});
|
|
626
|
+
logState.lastLoggedAt = now;
|
|
627
|
+
logState.suppressedRejections = 0;
|
|
628
|
+
}
|
|
629
|
+
|
|
588
630
|
function getPoolEntry(options: RuntimeSchedulerPoolOptions): PoolEntry {
|
|
589
631
|
assertRuntimeSchedulerHotPathUrl(options.url);
|
|
590
632
|
const maxClients =
|
|
@@ -799,10 +841,25 @@ export async function withRuntimeSchedulerClient<T>(
|
|
|
799
841
|
);
|
|
800
842
|
const operationStartedAt = performance.now();
|
|
801
843
|
const admissionStartedAt = performance.now();
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
844
|
+
let releaseAdmission: () => void;
|
|
845
|
+
try {
|
|
846
|
+
releaseAdmission = await entry.admission.acquire(
|
|
847
|
+
trace?.priority ?? 'ordinary',
|
|
848
|
+
signal,
|
|
849
|
+
);
|
|
850
|
+
} catch (error) {
|
|
851
|
+
if (
|
|
852
|
+
error instanceof RuntimeSchedulerSaturatedError &&
|
|
853
|
+
!(signal?.aborted && signal.reason === error)
|
|
854
|
+
) {
|
|
855
|
+
recordAdmissionSaturation(
|
|
856
|
+
entry,
|
|
857
|
+
trace?.priority ?? 'ordinary',
|
|
858
|
+
performance.now() - admissionStartedAt,
|
|
859
|
+
);
|
|
860
|
+
}
|
|
861
|
+
throw error;
|
|
862
|
+
}
|
|
806
863
|
const admissionWaitMs = performance.now() - admissionStartedAt;
|
|
807
864
|
let lastError: unknown = null;
|
|
808
865
|
try {
|
|
@@ -94,11 +94,14 @@ import {
|
|
|
94
94
|
} from '../log-provenance';
|
|
95
95
|
import {
|
|
96
96
|
buildRunLedgerEventsIdempotencyKey,
|
|
97
|
+
isRunLedgerProjectionChunk,
|
|
97
98
|
RunLedgerProjectionLeaseLostError,
|
|
99
|
+
type RunLedgerProjectionChunk,
|
|
98
100
|
type RunLedgerProjectionLeaseLostReason,
|
|
99
101
|
buildRunLedgerStartIdempotencyKey,
|
|
100
102
|
buildRunLedgerTerminalIdempotencyKey,
|
|
101
103
|
} from '../run-ledger-projection-contract';
|
|
104
|
+
import { partitionRunEventsForAppRuntime } from '../run-ledger-event-transport';
|
|
102
105
|
import {
|
|
103
106
|
assertTerminalRunResultWithinLimit,
|
|
104
107
|
isLedgerTerminalResultRef,
|
|
@@ -16026,6 +16029,7 @@ export async function assertPostgresRunLedgerDelivery(
|
|
|
16026
16029
|
idempotencyKey: string;
|
|
16027
16030
|
leaseOwner?: string;
|
|
16028
16031
|
projectedEvents?: readonly AcceptedPlayRunLedgerEvent[];
|
|
16032
|
+
projectionChunk?: RunLedgerProjectionChunk;
|
|
16029
16033
|
normalizeProjectedEvents?: (
|
|
16030
16034
|
events: readonly PlayRunLedgerIngressEvent[],
|
|
16031
16035
|
) => readonly AcceptedPlayRunLedgerEvent[];
|
|
@@ -16165,10 +16169,24 @@ export async function assertPostgresRunLedgerDelivery(
|
|
|
16165
16169
|
)[] = input.normalizeProjectedEvents
|
|
16166
16170
|
? input.normalizeProjectedEvents(prefixEvents)
|
|
16167
16171
|
: prefixEvents;
|
|
16172
|
+
let expectedProjectionEvents:
|
|
16173
|
+
| readonly (AcceptedPlayRunLedgerEvent | PlayRunLedgerIngressEvent)[]
|
|
16174
|
+
| undefined = comparablePrefixEvents;
|
|
16175
|
+
if (input.projectionChunk) {
|
|
16176
|
+
const chunk = input.projectionChunk;
|
|
16177
|
+
const chunks = isRunLedgerProjectionChunk(chunk)
|
|
16178
|
+
? partitionRunEventsForAppRuntime(
|
|
16179
|
+
comparablePrefixEvents as readonly PlayRunLedgerIngressEvent[],
|
|
16180
|
+
)
|
|
16181
|
+
: [];
|
|
16182
|
+
expectedProjectionEvents =
|
|
16183
|
+
chunks.length === chunk.count ? chunks[chunk.index] : undefined;
|
|
16184
|
+
}
|
|
16168
16185
|
if (
|
|
16186
|
+
expectedProjectionEvents !== undefined &&
|
|
16169
16187
|
runLedgerProjectionMatchesCanonicalPrefix(
|
|
16170
16188
|
input.projectedEvents,
|
|
16171
|
-
|
|
16189
|
+
expectedProjectionEvents,
|
|
16172
16190
|
)
|
|
16173
16191
|
) {
|
|
16174
16192
|
return;
|
package/dist/cli/index.js
CHANGED
|
@@ -3051,7 +3051,7 @@ var SDK_RELEASE = {
|
|
|
3051
3051
|
// getters keep their established compatibility behavior.
|
|
3052
3052
|
// 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
|
|
3053
3053
|
// 0.3.90 is the first deliberately versioned SDK release for API v3.
|
|
3054
|
-
version: "0.3.
|
|
3054
|
+
version: "0.3.222",
|
|
3055
3055
|
updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.",
|
|
3056
3056
|
packageCapabilities: {
|
|
3057
3057
|
updatePreferences: 1
|
package/dist/cli/index.mjs
CHANGED
|
@@ -3046,7 +3046,7 @@ var SDK_RELEASE = {
|
|
|
3046
3046
|
// getters keep their established compatibility behavior.
|
|
3047
3047
|
// 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
|
|
3048
3048
|
// 0.3.90 is the first deliberately versioned SDK release for API v3.
|
|
3049
|
-
version: "0.3.
|
|
3049
|
+
version: "0.3.222",
|
|
3050
3050
|
updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.",
|
|
3051
3051
|
packageCapabilities: {
|
|
3052
3052
|
updatePreferences: 1
|
package/dist/index.js
CHANGED
|
@@ -864,7 +864,7 @@ var SDK_RELEASE = {
|
|
|
864
864
|
// getters keep their established compatibility behavior.
|
|
865
865
|
// 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
|
|
866
866
|
// 0.3.90 is the first deliberately versioned SDK release for API v3.
|
|
867
|
-
version: "0.3.
|
|
867
|
+
version: "0.3.222",
|
|
868
868
|
updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.",
|
|
869
869
|
packageCapabilities: {
|
|
870
870
|
updatePreferences: 1
|
package/dist/index.mjs
CHANGED
|
@@ -768,7 +768,7 @@ var SDK_RELEASE = {
|
|
|
768
768
|
// getters keep their established compatibility behavior.
|
|
769
769
|
// 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
|
|
770
770
|
// 0.3.90 is the first deliberately versioned SDK release for API v3.
|
|
771
|
-
version: "0.3.
|
|
771
|
+
version: "0.3.222",
|
|
772
772
|
updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.",
|
|
773
773
|
packageCapabilities: {
|
|
774
774
|
updatePreferences: 1
|
|
@@ -293,6 +293,7 @@
|
|
|
293
293
|
"dist/bundling-sources/shared_libs/play-runtime/run-execution-scope.ts",
|
|
294
294
|
"dist/bundling-sources/shared_libs/play-runtime/run-failure.ts",
|
|
295
295
|
"dist/bundling-sources/shared_libs/play-runtime/run-identity.ts",
|
|
296
|
+
"dist/bundling-sources/shared_libs/play-runtime/run-ledger-event-transport.ts",
|
|
296
297
|
"dist/bundling-sources/shared_libs/play-runtime/run-ledger-projection-contract.ts",
|
|
297
298
|
"dist/bundling-sources/shared_libs/play-runtime/run-ledger.ts",
|
|
298
299
|
"dist/bundling-sources/shared_libs/play-runtime/run-lifecycle-policy.ts",
|
package/dist/release.d.mts
CHANGED
|
@@ -149,7 +149,7 @@ type SdkRelease = {
|
|
|
149
149
|
supportPolicy: SdkSupportPolicy;
|
|
150
150
|
};
|
|
151
151
|
declare const SDK_RELEASE: {
|
|
152
|
-
readonly version: "0.3.
|
|
152
|
+
readonly version: "0.3.222";
|
|
153
153
|
readonly updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.";
|
|
154
154
|
readonly packageCapabilities: {
|
|
155
155
|
readonly updatePreferences: 1;
|
package/dist/release.d.ts
CHANGED
|
@@ -149,7 +149,7 @@ type SdkRelease = {
|
|
|
149
149
|
supportPolicy: SdkSupportPolicy;
|
|
150
150
|
};
|
|
151
151
|
declare const SDK_RELEASE: {
|
|
152
|
-
readonly version: "0.3.
|
|
152
|
+
readonly version: "0.3.222";
|
|
153
153
|
readonly updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.";
|
|
154
154
|
readonly packageCapabilities: {
|
|
155
155
|
readonly updatePreferences: 1;
|
package/dist/release.js
CHANGED
|
@@ -74,7 +74,7 @@ var SDK_RELEASE = {
|
|
|
74
74
|
// getters keep their established compatibility behavior.
|
|
75
75
|
// 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
|
|
76
76
|
// 0.3.90 is the first deliberately versioned SDK release for API v3.
|
|
77
|
-
version: "0.3.
|
|
77
|
+
version: "0.3.222",
|
|
78
78
|
updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.",
|
|
79
79
|
packageCapabilities: {
|
|
80
80
|
updatePreferences: 1
|
package/dist/release.mjs
CHANGED
|
@@ -48,7 +48,7 @@ var SDK_RELEASE = {
|
|
|
48
48
|
// getters keep their established compatibility behavior.
|
|
49
49
|
// 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
|
|
50
50
|
// 0.3.90 is the first deliberately versioned SDK release for API v3.
|
|
51
|
-
version: "0.3.
|
|
51
|
+
version: "0.3.222",
|
|
52
52
|
updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.",
|
|
53
53
|
packageCapabilities: {
|
|
54
54
|
updatePreferences: 1
|