deepline 0.3.114 → 0.3.116
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/observability/dlq.ts +942 -0
- package/dist/bundling-sources/shared_libs/observability/queue-health.ts +91 -21
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/postgres.ts +220 -5
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-queue-health.ts +245 -81
- package/dist/bundling-sources/shared_libs/plays/share/static-pipeline-summary.ts +2 -2
- 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
package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-queue-health.ts
CHANGED
|
@@ -9,6 +9,11 @@ import {
|
|
|
9
9
|
type QueueHealth,
|
|
10
10
|
type QueueObservation,
|
|
11
11
|
} from '../../observability/queue-health';
|
|
12
|
+
import {
|
|
13
|
+
dlqInventoryFromQueueObservation,
|
|
14
|
+
getDlqTransitionPaths,
|
|
15
|
+
type DlqInventory,
|
|
16
|
+
} from '../../observability/dlq';
|
|
12
17
|
|
|
13
18
|
/**
|
|
14
19
|
* Bounded, read-only health projection for the durable runtime queues.
|
|
@@ -59,13 +64,15 @@ export type RuntimeQueueFlow = {
|
|
|
59
64
|
|
|
60
65
|
export type RuntimeQueueHealthProjection = {
|
|
61
66
|
id: string;
|
|
62
|
-
kind: 'absurd' | 'run_ledger_outbox' | 'sandbox_cleanup';
|
|
67
|
+
kind: 'absurd' | 'run_ledger_outbox' | 'compute_billing' | 'sandbox_cleanup';
|
|
63
68
|
source: 'absurd' | 'runtime_postgres';
|
|
64
69
|
observedAt: string;
|
|
65
70
|
status: RuntimeQueueHealthStatus;
|
|
66
71
|
statusReason: string;
|
|
67
72
|
/** Shared scheduler-neutral contract consumed by transports and dashboards. */
|
|
68
73
|
observation: QueueObservation;
|
|
74
|
+
/** Shared DLQ contract consumed by operators and the admin CLI. */
|
|
75
|
+
dlq: DlqInventory;
|
|
69
76
|
health: QueueHealth;
|
|
70
77
|
depth: RuntimeQueueDepth;
|
|
71
78
|
oldestAgeMs: RuntimeQueueOldestAge;
|
|
@@ -86,6 +93,8 @@ export type RuntimeQueueHealthProjection = {
|
|
|
86
93
|
export type RuntimeQueueHealthSnapshot = {
|
|
87
94
|
observedAt: string;
|
|
88
95
|
staleAfterMs: number;
|
|
96
|
+
/** True when the control-plane lane inventory was capped before sampling. */
|
|
97
|
+
inventoryTruncated?: boolean;
|
|
89
98
|
queues: RuntimeQueueHealthProjection[];
|
|
90
99
|
summary: {
|
|
91
100
|
green: number;
|
|
@@ -96,6 +105,8 @@ export type RuntimeQueueHealthSnapshot = {
|
|
|
96
105
|
};
|
|
97
106
|
|
|
98
107
|
export type RuntimeQueueHealthOptions = {
|
|
108
|
+
/** Explicit deployment label carried into the shared DLQ inventory. */
|
|
109
|
+
environment?: string;
|
|
99
110
|
schema?: string;
|
|
100
111
|
now?: Date;
|
|
101
112
|
staleAfterMs?: number;
|
|
@@ -103,6 +114,8 @@ export type RuntimeQueueHealthOptions = {
|
|
|
103
114
|
failAgeMs?: number;
|
|
104
115
|
/** Restrict Absurd rows to these queue names. Registry values are validated. */
|
|
105
116
|
absurdQueueNames?: string[];
|
|
117
|
+
/** The caller could not enumerate every live lane within the bounded cap. */
|
|
118
|
+
absurdQueueInventoryTruncated?: boolean;
|
|
106
119
|
maxAbsurdQueues?: number;
|
|
107
120
|
};
|
|
108
121
|
|
|
@@ -134,6 +147,8 @@ type CountRow = {
|
|
|
134
147
|
in_flight_truncated?: boolean;
|
|
135
148
|
blocked_truncated?: boolean;
|
|
136
149
|
dead_lettered_truncated?: boolean;
|
|
150
|
+
/** False for durable worksets that expose blocked quarantine, not a DLQ. */
|
|
151
|
+
dead_lettered_available?: boolean;
|
|
137
152
|
flow_available?: boolean;
|
|
138
153
|
flow_unavailable_reason?: string | null;
|
|
139
154
|
};
|
|
@@ -164,7 +179,9 @@ function numberValue(value: string | number | null | undefined): number {
|
|
|
164
179
|
function ageValue(value: string | number | null | undefined): number | null {
|
|
165
180
|
if (value === null || value === undefined) return null;
|
|
166
181
|
const parsed = numberValue(value);
|
|
167
|
-
|
|
182
|
+
// Zero is a real age for freshly admitted work. Keep it distinct from
|
|
183
|
+
// NULL, which means that the bucket is empty and should render as N/A.
|
|
184
|
+
return Math.floor(parsed);
|
|
168
185
|
}
|
|
169
186
|
|
|
170
187
|
function optionsWithDefaults(
|
|
@@ -246,6 +263,7 @@ function projectionFromRow(input: {
|
|
|
246
263
|
source: RuntimeQueueHealthProjection['source'];
|
|
247
264
|
row: CountRow;
|
|
248
265
|
observedAt: Date;
|
|
266
|
+
environment?: string;
|
|
249
267
|
options: RuntimeQueueHealthThresholds;
|
|
250
268
|
}): RuntimeQueueHealthProjection {
|
|
251
269
|
const depth: RuntimeQueueDepth = {
|
|
@@ -262,6 +280,7 @@ function projectionFromRow(input: {
|
|
|
262
280
|
blocked: ageValue(input.row.oldest_blocked_ms),
|
|
263
281
|
deadLettered: ageValue(input.row.oldest_dead_lettered_ms),
|
|
264
282
|
};
|
|
283
|
+
const deadLetteredAvailable = input.row.dead_lettered_available !== false;
|
|
265
284
|
const lifecycle = {
|
|
266
285
|
started: numberValue(input.row.started),
|
|
267
286
|
completed: numberValue(input.row.completed),
|
|
@@ -299,7 +318,9 @@ function projectionFromRow(input: {
|
|
|
299
318
|
? 'Run admitted Play runtime tasks to terminal state'
|
|
300
319
|
: input.kind === 'run_ledger_outbox'
|
|
301
320
|
? 'Deliver causal Run Ledger events to control-plane projections'
|
|
302
|
-
:
|
|
321
|
+
: input.kind === 'compute_billing'
|
|
322
|
+
? 'Settle durable compute billing obligations after a runtime run ends'
|
|
323
|
+
: 'Complete durable sandbox deletion obligations',
|
|
303
324
|
unit: 'items',
|
|
304
325
|
kind: input.kind === 'absurd' ? 'fifo' : 'leased_workset',
|
|
305
326
|
ageSlo: {
|
|
@@ -328,20 +349,21 @@ function projectionFromRow(input: {
|
|
|
328
349
|
delayed: measureDepth(depth.delayed, input.row.delayed_truncated),
|
|
329
350
|
inFlight: measureDepth(depth.inFlight, input.row.in_flight_truncated),
|
|
330
351
|
blocked: measureDepth(depth.blocked, input.row.blocked_truncated),
|
|
331
|
-
deadLettered:
|
|
332
|
-
depth.deadLettered,
|
|
333
|
-
|
|
334
|
-
),
|
|
352
|
+
deadLettered: deadLetteredAvailable
|
|
353
|
+
? measureDepth(depth.deadLettered, input.row.dead_lettered_truncated)
|
|
354
|
+
: notApplicable<number>('This workset has blocked quarantine, not a DLQ.'),
|
|
335
355
|
},
|
|
336
356
|
oldestAgeMs: {
|
|
337
357
|
ready: measureAge(oldestAgeMs.ready, input.row.ready_truncated),
|
|
338
358
|
delayed: measureAge(oldestAgeMs.delayed, input.row.delayed_truncated),
|
|
339
359
|
inFlight: measureAge(oldestAgeMs.inFlight, input.row.in_flight_truncated),
|
|
340
360
|
blocked: measureAge(oldestAgeMs.blocked, input.row.blocked_truncated),
|
|
341
|
-
deadLettered:
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
361
|
+
deadLettered: deadLetteredAvailable
|
|
362
|
+
? measureAge(
|
|
363
|
+
oldestAgeMs.deadLettered,
|
|
364
|
+
input.row.dead_lettered_truncated,
|
|
365
|
+
)
|
|
366
|
+
: notApplicable<number>('This workset has blocked quarantine, not a DLQ.'),
|
|
345
367
|
},
|
|
346
368
|
flow: {
|
|
347
369
|
admitted: flowAvailable
|
|
@@ -369,6 +391,20 @@ function projectionFromRow(input: {
|
|
|
369
391
|
observation,
|
|
370
392
|
input.options.now.getTime(),
|
|
371
393
|
);
|
|
394
|
+
const dlq = dlqInventoryFromQueueObservation({
|
|
395
|
+
queueId: input.id,
|
|
396
|
+
environment:
|
|
397
|
+
input.environment?.trim() ||
|
|
398
|
+
process.env.DEEPLINE_ENV?.trim() ||
|
|
399
|
+
'unknown',
|
|
400
|
+
source: input.source,
|
|
401
|
+
observation,
|
|
402
|
+
paths: getDlqTransitionPaths({
|
|
403
|
+
queueId: input.id,
|
|
404
|
+
owner: 'runtime',
|
|
405
|
+
source: input.source,
|
|
406
|
+
}),
|
|
407
|
+
});
|
|
372
408
|
return {
|
|
373
409
|
id: input.id,
|
|
374
410
|
kind: input.kind,
|
|
@@ -377,6 +413,7 @@ function projectionFromRow(input: {
|
|
|
377
413
|
status: derived.status,
|
|
378
414
|
statusReason: derived.statusReason,
|
|
379
415
|
observation,
|
|
416
|
+
dlq,
|
|
380
417
|
health,
|
|
381
418
|
depth,
|
|
382
419
|
oldestAgeMs,
|
|
@@ -465,6 +502,7 @@ function absurdProjectionQuery(queueTable: string): string {
|
|
|
465
502
|
0::bigint AS completed,
|
|
466
503
|
0::bigint AS failed,
|
|
467
504
|
0::bigint AS retried,
|
|
505
|
+
true AS dead_lettered_available,
|
|
468
506
|
false AS flow_available,
|
|
469
507
|
'Absurd run history has no bounded exact rolling flow projection'::text AS flow_unavailable_reason
|
|
470
508
|
FROM sampled
|
|
@@ -474,114 +512,216 @@ function absurdProjectionQuery(queueTable: string): string {
|
|
|
474
512
|
function outboxProjectionQuery(schema: string): string {
|
|
475
513
|
const table = `${schema}."outbox"`;
|
|
476
514
|
return `
|
|
477
|
-
WITH
|
|
478
|
-
SELECT
|
|
479
|
-
CASE
|
|
480
|
-
WHEN lease_owner IS NULL AND coalesce(next_attempt_at, created_at) <= $1::timestamptz THEN 'ready'
|
|
481
|
-
WHEN lease_owner IS NULL THEN 'delayed'
|
|
482
|
-
WHEN lease_expires_at > $1::timestamptz THEN 'in_flight'
|
|
483
|
-
ELSE 'blocked'
|
|
484
|
-
END AS bucket,
|
|
485
|
-
CASE
|
|
486
|
-
WHEN lease_owner IS NULL AND coalesce(next_attempt_at, created_at) > $1::timestamptz
|
|
487
|
-
THEN coalesce(next_attempt_at, created_at)
|
|
488
|
-
WHEN lease_owner IS NULL THEN created_at
|
|
489
|
-
WHEN lease_expires_at > $1::timestamptz
|
|
490
|
-
THEN coalesce(delivery_batch_started_at, created_at)
|
|
491
|
-
ELSE coalesce(lease_expires_at, created_at)
|
|
492
|
-
END AS age_at
|
|
515
|
+
WITH ready AS (
|
|
516
|
+
SELECT coalesce(next_attempt_at, created_at) AS age_at
|
|
493
517
|
FROM ${table}
|
|
494
|
-
WHERE delivered_at IS NULL
|
|
518
|
+
WHERE delivered_at IS NULL
|
|
519
|
+
AND failed_at IS NULL
|
|
520
|
+
AND lease_owner IS NULL
|
|
521
|
+
AND coalesce(next_attempt_at, created_at) <= $1::timestamptz
|
|
495
522
|
ORDER BY coalesce(next_attempt_at, created_at), created_at, event_id
|
|
496
523
|
LIMIT $2::int
|
|
497
|
-
),
|
|
498
|
-
SELECT
|
|
524
|
+
), delayed AS (
|
|
525
|
+
SELECT coalesce(next_attempt_at, created_at) AS age_at
|
|
526
|
+
FROM ${table}
|
|
527
|
+
WHERE delivered_at IS NULL
|
|
528
|
+
AND failed_at IS NULL
|
|
529
|
+
AND lease_owner IS NULL
|
|
530
|
+
AND coalesce(next_attempt_at, created_at) > $1::timestamptz
|
|
531
|
+
ORDER BY coalesce(next_attempt_at, created_at), created_at, event_id
|
|
532
|
+
LIMIT $2::int
|
|
533
|
+
), in_flight AS (
|
|
534
|
+
SELECT coalesce(delivery_batch_started_at, created_at) AS age_at
|
|
535
|
+
FROM ${table}
|
|
536
|
+
WHERE delivered_at IS NULL
|
|
537
|
+
AND failed_at IS NULL
|
|
538
|
+
AND lease_owner IS NOT NULL
|
|
539
|
+
AND lease_expires_at > $1::timestamptz
|
|
540
|
+
ORDER BY lease_expires_at, created_at, event_id
|
|
541
|
+
LIMIT $2::int
|
|
542
|
+
), blocked AS (
|
|
543
|
+
SELECT coalesce(lease_expires_at, created_at) AS age_at
|
|
544
|
+
FROM ${table}
|
|
545
|
+
WHERE delivered_at IS NULL
|
|
546
|
+
AND failed_at IS NULL
|
|
547
|
+
AND lease_owner IS NOT NULL
|
|
548
|
+
AND (lease_expires_at IS NULL OR lease_expires_at <= $1::timestamptz)
|
|
549
|
+
ORDER BY coalesce(lease_expires_at, created_at), created_at, event_id
|
|
550
|
+
LIMIT $2::int
|
|
551
|
+
), dead_lettered AS (
|
|
552
|
+
SELECT coalesce(failed_at, created_at) AS age_at
|
|
499
553
|
FROM ${table}
|
|
500
554
|
WHERE delivered_at IS NULL AND failed_at IS NOT NULL
|
|
501
555
|
ORDER BY failed_at, event_id
|
|
502
556
|
LIMIT $2::int
|
|
503
|
-
), sampled AS (
|
|
504
|
-
SELECT * FROM pending_sample
|
|
505
|
-
UNION ALL
|
|
506
|
-
SELECT * FROM dead_sample
|
|
507
557
|
)
|
|
508
558
|
SELECT
|
|
509
|
-
least(count(*)
|
|
510
|
-
least(count(*)
|
|
511
|
-
least(count(*)
|
|
512
|
-
least(count(*)
|
|
513
|
-
least(count(*)
|
|
514
|
-
max(${intervalExpr('age_at')})
|
|
515
|
-
max(${intervalExpr('age_at')})
|
|
516
|
-
max(${intervalExpr('age_at')})
|
|
517
|
-
max(${intervalExpr('age_at')})
|
|
518
|
-
max(${intervalExpr('age_at')})
|
|
519
|
-
count(*)
|
|
520
|
-
count(*)
|
|
521
|
-
count(*)
|
|
522
|
-
count(*)
|
|
523
|
-
count(*)
|
|
559
|
+
least((SELECT count(*) FROM ready), $3) AS ready,
|
|
560
|
+
least((SELECT count(*) FROM delayed), $3) AS delayed,
|
|
561
|
+
least((SELECT count(*) FROM in_flight), $3) AS in_flight,
|
|
562
|
+
least((SELECT count(*) FROM blocked), $3) AS blocked,
|
|
563
|
+
least((SELECT count(*) FROM dead_lettered), $3) AS dead_lettered,
|
|
564
|
+
(SELECT max(${intervalExpr('age_at')}) FROM ready) AS oldest_ready_ms,
|
|
565
|
+
(SELECT max(${intervalExpr('age_at')}) FROM delayed) AS oldest_delayed_ms,
|
|
566
|
+
(SELECT max(${intervalExpr('age_at')}) FROM in_flight) AS oldest_in_flight_ms,
|
|
567
|
+
(SELECT max(${intervalExpr('age_at')}) FROM blocked) AS oldest_blocked_ms,
|
|
568
|
+
(SELECT max(${intervalExpr('age_at')}) FROM dead_lettered) AS oldest_dead_lettered_ms,
|
|
569
|
+
(SELECT count(*) FROM ready) > $3 AS ready_truncated,
|
|
570
|
+
(SELECT count(*) FROM delayed) > $3 AS delayed_truncated,
|
|
571
|
+
(SELECT count(*) FROM in_flight) > $3 AS in_flight_truncated,
|
|
572
|
+
(SELECT count(*) FROM blocked) > $3 AS blocked_truncated,
|
|
573
|
+
(SELECT count(*) FROM dead_lettered) > $3 AS dead_lettered_truncated,
|
|
524
574
|
0::bigint AS admitted,
|
|
525
575
|
0::bigint AS started,
|
|
526
576
|
0::bigint AS completed,
|
|
527
577
|
0::bigint AS failed,
|
|
528
578
|
0::bigint AS retried,
|
|
579
|
+
true AS dead_lettered_available,
|
|
529
580
|
false AS flow_available,
|
|
530
581
|
'Outbox health has no bounded exact rolling flow projection'::text AS flow_unavailable_reason
|
|
531
|
-
FROM sampled
|
|
532
582
|
`;
|
|
533
583
|
}
|
|
534
584
|
|
|
535
585
|
function cleanupProjectionQuery(schema: string): string {
|
|
536
586
|
const table = `${schema}."sandbox_cleanup_jobs_v2"`;
|
|
537
587
|
return `
|
|
538
|
-
WITH
|
|
588
|
+
WITH ready AS (
|
|
589
|
+
SELECT created_at AS age_at
|
|
590
|
+
FROM ${table}
|
|
591
|
+
WHERE status <> 'deleted'
|
|
592
|
+
AND blocked_at IS NULL
|
|
593
|
+
AND lease_owner IS NULL
|
|
594
|
+
AND status <> 'deleting'
|
|
595
|
+
AND available_at <= $1::timestamptz
|
|
596
|
+
ORDER BY available_at, created_at, provider, sandbox_id
|
|
597
|
+
LIMIT $2::int
|
|
598
|
+
), delayed AS (
|
|
599
|
+
SELECT available_at AS age_at
|
|
600
|
+
FROM ${table}
|
|
601
|
+
WHERE status <> 'deleted'
|
|
602
|
+
AND blocked_at IS NULL
|
|
603
|
+
AND lease_owner IS NULL
|
|
604
|
+
AND status <> 'deleting'
|
|
605
|
+
AND available_at > $1::timestamptz
|
|
606
|
+
ORDER BY available_at, created_at, provider, sandbox_id
|
|
607
|
+
LIMIT $2::int
|
|
608
|
+
), in_flight AS (
|
|
609
|
+
SELECT coalesce(updated_at, created_at) AS age_at
|
|
610
|
+
FROM ${table}
|
|
611
|
+
WHERE status <> 'deleted'
|
|
612
|
+
AND blocked_at IS NULL
|
|
613
|
+
AND lease_owner IS NOT NULL
|
|
614
|
+
AND lease_expires_at > $1::timestamptz
|
|
615
|
+
ORDER BY lease_expires_at, created_at, provider, sandbox_id
|
|
616
|
+
LIMIT $2::int
|
|
617
|
+
), blocked AS (
|
|
539
618
|
SELECT
|
|
540
|
-
CASE
|
|
541
|
-
WHEN blocked_at IS NOT NULL THEN 'blocked'
|
|
542
|
-
WHEN lease_owner IS NOT NULL AND lease_expires_at > $1::timestamptz THEN 'in_flight'
|
|
543
|
-
WHEN lease_owner IS NOT NULL OR status = 'deleting' THEN 'blocked'
|
|
544
|
-
WHEN available_at > $1::timestamptz THEN 'delayed'
|
|
545
|
-
ELSE 'ready'
|
|
546
|
-
END AS bucket,
|
|
547
619
|
CASE
|
|
548
620
|
WHEN blocked_at IS NOT NULL THEN blocked_at
|
|
549
|
-
|
|
550
|
-
THEN coalesce(updated_at, created_at)
|
|
551
|
-
WHEN lease_owner IS NOT NULL OR status = 'deleting'
|
|
552
|
-
THEN coalesce(lease_expires_at, created_at)
|
|
553
|
-
WHEN available_at > $1::timestamptz THEN available_at
|
|
554
|
-
ELSE created_at
|
|
621
|
+
ELSE coalesce(lease_expires_at, created_at)
|
|
555
622
|
END AS age_at
|
|
556
623
|
FROM ${table}
|
|
557
624
|
WHERE status <> 'deleted'
|
|
558
|
-
|
|
625
|
+
AND (
|
|
626
|
+
blocked_at IS NOT NULL
|
|
627
|
+
OR lease_owner IS NOT NULL AND (lease_expires_at IS NULL OR lease_expires_at <= $1::timestamptz)
|
|
628
|
+
OR lease_owner IS NULL AND status = 'deleting'
|
|
629
|
+
)
|
|
630
|
+
ORDER BY coalesce(blocked_at, lease_expires_at, created_at), created_at, provider, sandbox_id
|
|
559
631
|
LIMIT $2::int
|
|
560
632
|
)
|
|
561
633
|
SELECT
|
|
562
|
-
least(count(*)
|
|
563
|
-
least(count(*)
|
|
564
|
-
least(count(*)
|
|
565
|
-
least(count(*)
|
|
634
|
+
least((SELECT count(*) FROM ready), $3) AS ready,
|
|
635
|
+
least((SELECT count(*) FROM delayed), $3) AS delayed,
|
|
636
|
+
least((SELECT count(*) FROM in_flight), $3) AS in_flight,
|
|
637
|
+
least((SELECT count(*) FROM blocked), $3) AS blocked,
|
|
566
638
|
0::bigint AS dead_lettered,
|
|
567
|
-
max(${intervalExpr('age_at')})
|
|
568
|
-
max(${intervalExpr('age_at')})
|
|
569
|
-
max(${intervalExpr('age_at')})
|
|
570
|
-
max(${intervalExpr('age_at')})
|
|
639
|
+
(SELECT max(${intervalExpr('age_at')}) FROM ready) AS oldest_ready_ms,
|
|
640
|
+
(SELECT max(${intervalExpr('age_at')}) FROM delayed) AS oldest_delayed_ms,
|
|
641
|
+
(SELECT max(${intervalExpr('age_at')}) FROM in_flight) AS oldest_in_flight_ms,
|
|
642
|
+
(SELECT max(${intervalExpr('age_at')}) FROM blocked) AS oldest_blocked_ms,
|
|
571
643
|
NULL::bigint AS oldest_dead_lettered_ms,
|
|
572
|
-
count(*) > $3 AS ready_truncated,
|
|
573
|
-
count(*) > $3 AS delayed_truncated,
|
|
574
|
-
count(*) > $3 AS in_flight_truncated,
|
|
575
|
-
count(*) > $3 AS blocked_truncated,
|
|
644
|
+
(SELECT count(*) FROM ready) > $3 AS ready_truncated,
|
|
645
|
+
(SELECT count(*) FROM delayed) > $3 AS delayed_truncated,
|
|
646
|
+
(SELECT count(*) FROM in_flight) > $3 AS in_flight_truncated,
|
|
647
|
+
(SELECT count(*) FROM blocked) > $3 AS blocked_truncated,
|
|
576
648
|
false AS dead_lettered_truncated,
|
|
577
649
|
0::bigint AS admitted,
|
|
578
650
|
0::bigint AS started,
|
|
579
651
|
0::bigint AS completed,
|
|
580
652
|
0::bigint AS failed,
|
|
581
653
|
0::bigint AS retried,
|
|
654
|
+
false AS dead_lettered_available,
|
|
582
655
|
false AS flow_available,
|
|
583
656
|
'Sandbox cleanup health has no bounded exact rolling flow projection'::text AS flow_unavailable_reason
|
|
584
|
-
|
|
657
|
+
`;
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
function computeBillingProjectionQuery(schema: string): string {
|
|
661
|
+
const table = `${schema}."compute_billing_jobs_v2"`;
|
|
662
|
+
return `
|
|
663
|
+
WITH ready AS (
|
|
664
|
+
SELECT created_at AS age_at
|
|
665
|
+
FROM ${table}
|
|
666
|
+
WHERE status <> 'settled'
|
|
667
|
+
AND blocked_at IS NULL
|
|
668
|
+
AND lease_owner IS NULL
|
|
669
|
+
AND available_at <= $1::timestamptz
|
|
670
|
+
ORDER BY available_at, created_at, run_id
|
|
671
|
+
LIMIT $2::int
|
|
672
|
+
), delayed AS (
|
|
673
|
+
SELECT available_at AS age_at
|
|
674
|
+
FROM ${table}
|
|
675
|
+
WHERE status <> 'settled'
|
|
676
|
+
AND blocked_at IS NULL
|
|
677
|
+
AND lease_owner IS NULL
|
|
678
|
+
AND available_at > $1::timestamptz
|
|
679
|
+
ORDER BY available_at, created_at, run_id
|
|
680
|
+
LIMIT $2::int
|
|
681
|
+
), in_flight AS (
|
|
682
|
+
SELECT coalesce(updated_at, created_at) AS age_at
|
|
683
|
+
FROM ${table}
|
|
684
|
+
WHERE status <> 'settled'
|
|
685
|
+
AND blocked_at IS NULL
|
|
686
|
+
AND lease_owner IS NOT NULL
|
|
687
|
+
AND lease_expires_at > $1::timestamptz
|
|
688
|
+
ORDER BY lease_expires_at, created_at, run_id
|
|
689
|
+
LIMIT $2::int
|
|
690
|
+
), blocked AS (
|
|
691
|
+
SELECT coalesce(blocked_at, lease_expires_at, created_at) AS age_at
|
|
692
|
+
FROM ${table}
|
|
693
|
+
WHERE status <> 'settled'
|
|
694
|
+
AND (
|
|
695
|
+
blocked_at IS NOT NULL
|
|
696
|
+
OR lease_owner IS NOT NULL AND (lease_expires_at IS NULL OR lease_expires_at <= $1::timestamptz)
|
|
697
|
+
)
|
|
698
|
+
ORDER BY coalesce(blocked_at, lease_expires_at, created_at), created_at, run_id
|
|
699
|
+
LIMIT $2::int
|
|
700
|
+
)
|
|
701
|
+
SELECT
|
|
702
|
+
least((SELECT count(*) FROM ready), $3) AS ready,
|
|
703
|
+
least((SELECT count(*) FROM delayed), $3) AS delayed,
|
|
704
|
+
least((SELECT count(*) FROM in_flight), $3) AS in_flight,
|
|
705
|
+
least((SELECT count(*) FROM blocked), $3) AS blocked,
|
|
706
|
+
0::bigint AS dead_lettered,
|
|
707
|
+
(SELECT max(${intervalExpr('age_at')}) FROM ready) AS oldest_ready_ms,
|
|
708
|
+
(SELECT max(${intervalExpr('age_at')}) FROM delayed) AS oldest_delayed_ms,
|
|
709
|
+
(SELECT max(${intervalExpr('age_at')}) FROM in_flight) AS oldest_in_flight_ms,
|
|
710
|
+
(SELECT max(${intervalExpr('age_at')}) FROM blocked) AS oldest_blocked_ms,
|
|
711
|
+
NULL::bigint AS oldest_dead_lettered_ms,
|
|
712
|
+
(SELECT count(*) FROM ready) > $3 AS ready_truncated,
|
|
713
|
+
(SELECT count(*) FROM delayed) > $3 AS delayed_truncated,
|
|
714
|
+
(SELECT count(*) FROM in_flight) > $3 AS in_flight_truncated,
|
|
715
|
+
(SELECT count(*) FROM blocked) > $3 AS blocked_truncated,
|
|
716
|
+
false AS dead_lettered_truncated,
|
|
717
|
+
0::bigint AS admitted,
|
|
718
|
+
0::bigint AS started,
|
|
719
|
+
0::bigint AS completed,
|
|
720
|
+
0::bigint AS failed,
|
|
721
|
+
0::bigint AS retried,
|
|
722
|
+
false AS dead_lettered_available,
|
|
723
|
+
false AS flow_available,
|
|
724
|
+
'Compute billing health has no bounded exact rolling flow projection'::text AS flow_unavailable_reason
|
|
585
725
|
`;
|
|
586
726
|
}
|
|
587
727
|
|
|
@@ -649,9 +789,13 @@ export async function readRuntimeQueueHealthFromClient(
|
|
|
649
789
|
)
|
|
650
790
|
: await client.query<{ queue_name: string }>(
|
|
651
791
|
`SELECT queue_name FROM absurd.queues ORDER BY queue_name LIMIT $1::int`,
|
|
652
|
-
[maxQueues],
|
|
792
|
+
[maxQueues + 1],
|
|
653
793
|
);
|
|
654
|
-
const
|
|
794
|
+
const registryTruncated =
|
|
795
|
+
requestedNames === undefined && registry.rows.length > maxQueues;
|
|
796
|
+
const queueNames = registry.rows
|
|
797
|
+
.slice(0, maxQueues)
|
|
798
|
+
.map((row) => row.queue_name);
|
|
655
799
|
if (requestedNames) {
|
|
656
800
|
const found = new Set(queueNames);
|
|
657
801
|
const missing = requestedNames.filter((name) => !found.has(name));
|
|
@@ -674,16 +818,22 @@ export async function readRuntimeQueueHealthFromClient(
|
|
|
674
818
|
source: 'absurd',
|
|
675
819
|
row: rowFromResult(result),
|
|
676
820
|
observedAt: now,
|
|
821
|
+
environment: input.environment,
|
|
677
822
|
options,
|
|
678
823
|
}),
|
|
679
824
|
);
|
|
680
825
|
}
|
|
681
|
-
const [outbox, cleanup] = await Promise.all([
|
|
826
|
+
const [outbox, computeBilling, cleanup] = await Promise.all([
|
|
682
827
|
client.query<CountRow>(outboxProjectionQuery(schema), [
|
|
683
828
|
now,
|
|
684
829
|
sampleLimit + 1,
|
|
685
830
|
sampleLimit,
|
|
686
831
|
]),
|
|
832
|
+
client.query<CountRow>(computeBillingProjectionQuery(schema), [
|
|
833
|
+
now,
|
|
834
|
+
sampleLimit + 1,
|
|
835
|
+
sampleLimit,
|
|
836
|
+
]),
|
|
687
837
|
client.query<CountRow>(cleanupProjectionQuery(schema), [
|
|
688
838
|
now,
|
|
689
839
|
sampleLimit + 1,
|
|
@@ -697,6 +847,16 @@ export async function readRuntimeQueueHealthFromClient(
|
|
|
697
847
|
source: 'runtime_postgres',
|
|
698
848
|
row: rowFromResult(outbox),
|
|
699
849
|
observedAt: now,
|
|
850
|
+
environment: input.environment,
|
|
851
|
+
options,
|
|
852
|
+
}),
|
|
853
|
+
projectionFromRow({
|
|
854
|
+
id: 'runtime:compute-billing-jobs-v2',
|
|
855
|
+
kind: 'compute_billing',
|
|
856
|
+
source: 'runtime_postgres',
|
|
857
|
+
row: rowFromResult(computeBilling),
|
|
858
|
+
observedAt: now,
|
|
859
|
+
environment: input.environment,
|
|
700
860
|
options,
|
|
701
861
|
}),
|
|
702
862
|
projectionFromRow({
|
|
@@ -705,6 +865,7 @@ export async function readRuntimeQueueHealthFromClient(
|
|
|
705
865
|
source: 'runtime_postgres',
|
|
706
866
|
row: rowFromResult(cleanup),
|
|
707
867
|
observedAt: now,
|
|
868
|
+
environment: input.environment,
|
|
708
869
|
options,
|
|
709
870
|
}),
|
|
710
871
|
);
|
|
@@ -717,6 +878,9 @@ export async function readRuntimeQueueHealthFromClient(
|
|
|
717
878
|
return {
|
|
718
879
|
observedAt: now.toISOString(),
|
|
719
880
|
staleAfterMs: options.staleAfterMs,
|
|
881
|
+
...(input.absurdQueueInventoryTruncated || registryTruncated
|
|
882
|
+
? { inventoryTruncated: true }
|
|
883
|
+
: {}),
|
|
720
884
|
queues: projections,
|
|
721
885
|
summary,
|
|
722
886
|
};
|
|
@@ -328,8 +328,8 @@ function previewDetailFor(substep: PlayStaticSubstep): string | null {
|
|
|
328
328
|
? `${substep.steps.length} fallbacks`
|
|
329
329
|
: 'first match wins';
|
|
330
330
|
case 'step_suite': {
|
|
331
|
-
const count =
|
|
332
|
-
return
|
|
331
|
+
const count = effectiveStepCount(substep);
|
|
332
|
+
return `${count} step${count === 1 ? '' : 's'}`;
|
|
333
333
|
}
|
|
334
334
|
case 'control_flow': {
|
|
335
335
|
const count = substep.steps.reduce(
|
package/dist/cli/index.js
CHANGED
|
@@ -1298,7 +1298,7 @@ var SDK_RELEASE = {
|
|
|
1298
1298
|
// getters keep their established compatibility behavior.
|
|
1299
1299
|
// 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
|
|
1300
1300
|
// 0.3.90 is the first deliberately versioned SDK release for API v3.
|
|
1301
|
-
version: "0.3.
|
|
1301
|
+
version: "0.3.116",
|
|
1302
1302
|
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.",
|
|
1303
1303
|
packageCapabilities: {
|
|
1304
1304
|
updatePreferences: 1
|
package/dist/cli/index.mjs
CHANGED
|
@@ -1271,7 +1271,7 @@ var SDK_RELEASE = {
|
|
|
1271
1271
|
// getters keep their established compatibility behavior.
|
|
1272
1272
|
// 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
|
|
1273
1273
|
// 0.3.90 is the first deliberately versioned SDK release for API v3.
|
|
1274
|
-
version: "0.3.
|
|
1274
|
+
version: "0.3.116",
|
|
1275
1275
|
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.",
|
|
1276
1276
|
packageCapabilities: {
|
|
1277
1277
|
updatePreferences: 1
|
package/dist/index.js
CHANGED
|
@@ -860,7 +860,7 @@ var SDK_RELEASE = {
|
|
|
860
860
|
// getters keep their established compatibility behavior.
|
|
861
861
|
// 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
|
|
862
862
|
// 0.3.90 is the first deliberately versioned SDK release for API v3.
|
|
863
|
-
version: "0.3.
|
|
863
|
+
version: "0.3.116",
|
|
864
864
|
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.",
|
|
865
865
|
packageCapabilities: {
|
|
866
866
|
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.116",
|
|
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
|
|
@@ -88,6 +88,7 @@
|
|
|
88
88
|
"dist/bundling-sources/shared_libs/monitors/tsconfig.json",
|
|
89
89
|
"dist/bundling-sources/shared_libs/monitors/validation.ts",
|
|
90
90
|
"dist/bundling-sources/shared_libs/observability/build-context.ts",
|
|
91
|
+
"dist/bundling-sources/shared_libs/observability/dlq.ts",
|
|
91
92
|
"dist/bundling-sources/shared_libs/observability/log-metadata.ts",
|
|
92
93
|
"dist/bundling-sources/shared_libs/observability/node-tracing.ts",
|
|
93
94
|
"dist/bundling-sources/shared_libs/observability/queue-health.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.116";
|
|
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.116";
|
|
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.116",
|
|
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.116",
|
|
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
|