deepline 0.3.297 → 0.3.299
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/async-operation.ts +15 -2
- 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 +115 -59
- package/dist/bundling-sources/shared_libs/play-runtime/scheduler-backends/runtime-event-search.ts +15 -3
- package/dist/cli/auth-4WFBFN3L.js +31 -0
- package/dist/cli/{auth-FOHTQKQV.mjs → auth-GWIEEZWL.mjs} +4 -4
- package/dist/cli/{billing-NRKIBTKJ.js → billing-K5EVUVEH.js} +70 -70
- package/dist/cli/{billing-ZY3KZNZD.mjs → billing-O5RAKWXK.mjs} +4 -4
- package/dist/cli/{chunk-VIOM5OEQ.js → chunk-2BISKKLW.js} +58 -58
- package/dist/cli/{chunk-YH2XATMF.js → chunk-3M3LQJUV.js} +26 -26
- package/dist/cli/{chunk-FSPE246W.js → chunk-4B7VWFHW.js} +15 -15
- package/dist/cli/{chunk-YCCDPYIV.mjs → chunk-5465KL4F.mjs} +4 -4
- package/dist/cli/{chunk-QPBTAYNK.mjs → chunk-6ECTEH6V.mjs} +2 -2
- package/dist/cli/{chunk-4NYMO67X.js → chunk-ACSNZYU3.js} +2 -2
- package/dist/cli/{chunk-ZXJWXNGA.mjs → chunk-BQ63LCEL.mjs} +3 -3
- package/dist/cli/{chunk-PYXPP7NX.mjs → chunk-CJBMCJW7.mjs} +1 -1
- package/dist/cli/{chunk-B52G7BYN.js → chunk-CL4YLYGW.js} +6 -6
- package/dist/cli/{chunk-FHO5PO6Q.js → chunk-D2P4AM5M.js} +6 -6
- package/dist/cli/{chunk-OSUS6K5I.js → chunk-DMTWRFPD.js} +4 -4
- package/dist/cli/{chunk-PLKA4WFH.mjs → chunk-FKKCGFQ2.mjs} +3 -3
- package/dist/cli/{chunk-DBZX2IWV.mjs → chunk-FT2TIKOX.mjs} +2 -2
- package/dist/cli/{chunk-R2COLUYE.mjs → chunk-QAEIUQPS.mjs} +1 -1
- package/dist/cli/{chunk-IJGJKU4L.js → chunk-REFGDIMC.js} +1 -1
- package/dist/cli/{chunk-YFPOHUWQ.mjs → chunk-S34ZVHGJ.mjs} +1 -1
- package/dist/cli/{chunk-QIJ32UEW.js → chunk-SJK2LSDQ.js} +6 -6
- package/dist/cli/{chunk-SZJM7D7W.mjs → chunk-TRSF2X3K.mjs} +1 -1
- package/dist/cli/{chunk-AC3SC3AC.mjs → chunk-W2N5FICT.mjs} +1 -1
- package/dist/cli/{chunk-34A5RSXF.js → chunk-WF7XMZAC.js} +6 -6
- package/dist/cli/{chunk-V24XJVLX.js → chunk-XUMCCIOY.js} +48 -48
- package/dist/cli/{chunk-R5BISWXF.mjs → chunk-ZWUOF7WR.mjs} +1 -1
- package/dist/cli/{client-65MCTEMR.mjs → client-OXUEAZD2.mjs} +3 -3
- package/dist/cli/client-ZBLK3VOY.js +20 -0
- package/dist/cli/{csv-SHCW3IJL.js → csv-J24BXLDP.js} +12 -12
- package/dist/cli/{csv-TJWBSMR2.mjs → csv-NV6QBRGT.mjs} +3 -3
- package/dist/cli/{db-DN6YHQTC.js → db-FL4N5LXG.js} +20 -20
- package/dist/cli/{db-K7QXXM5C.mjs → db-IY4LHKLR.mjs} +4 -4
- package/dist/cli/{executions-FRQO6SJF.mjs → executions-72PNXJWI.mjs} +4 -4
- package/dist/cli/{executions-2POJWTCH.js → executions-OYGLF6K2.js} +6 -6
- package/dist/cli/{feedback-A6232HB5.mjs → feedback-NGPJBTUS.mjs} +3 -3
- package/dist/cli/{feedback-EEYZOH3S.js → feedback-WHOLOKBU.js} +6 -6
- package/dist/cli/git-GD5I7YOP.js +23 -0
- package/dist/cli/{git-FRVNZNIA.mjs → git-HQKCORLT.mjs} +4 -4
- package/dist/cli/index.js +73 -73
- package/dist/cli/index.mjs +30 -30
- package/dist/cli/{legacy-noops-NREP3YMQ.js → legacy-noops-5RHXWONK.js} +7 -7
- package/dist/cli/{legacy-noops-WEN2VQKS.mjs → legacy-noops-MCAHTGPU.mjs} +4 -4
- package/dist/cli/{monitors-EHHO4IGT.js → monitors-MC4QEQ7N.js} +85 -85
- package/dist/cli/{monitors-2F7GLG24.mjs → monitors-X2KE6CL6.mjs} +4 -4
- package/dist/cli/{org-TTFZKSMD.js → org-75TWPW5D.js} +60 -60
- package/dist/cli/{org-JONFO5PV.mjs → org-YW6EKMHL.mjs} +4 -4
- package/dist/cli/{play-N3JMRLKG.js → play-CAMPEI5I.js} +200 -200
- package/dist/cli/{play-Y7U2XU2K.mjs → play-DEBY5SCV.mjs} +6 -6
- package/dist/cli/{providers-CWPT5L3U.mjs → providers-IA77P6YJ.mjs} +4 -4
- package/dist/cli/{providers-I4V4QCOM.js → providers-VNOHQ2AS.js} +7 -7
- package/dist/cli/{quickstart-UBONJ6EY.mjs → quickstart-K7HQS543.mjs} +3 -3
- package/dist/cli/{quickstart-2DDUIWC5.js → quickstart-LDTV2HGI.js} +5 -5
- package/dist/cli/{search-BHCCYLF2.mjs → search-536X3UCU.mjs} +5 -5
- package/dist/cli/{search-Z72FUFXL.js → search-SN5OPRXZ.js} +6 -6
- package/dist/cli/{secrets-AE22MX42.js → secrets-2EW56WXT.js} +13 -13
- package/dist/cli/{secrets-BGD4PNTG.mjs → secrets-B3AJVZEX.mjs} +4 -4
- package/dist/cli/{sessions-7SIBBFHF.js → sessions-3VDMBHNS.js} +5 -5
- package/dist/cli/{sessions-JYSG6SUN.mjs → sessions-WBJUUGWS.mjs} +4 -4
- package/dist/cli/{settings-LCA42CL3.js → settings-KABYSG3X.js} +74 -74
- package/dist/cli/{settings-4XWN4JFT.mjs → settings-RLDDNKLV.mjs} +7 -7
- package/dist/cli/{setup-NID2M4GQ.js → setup-CSOSGT4H.js} +41 -41
- package/dist/cli/{setup-WMOKDWHV.mjs → setup-LXS6GANX.mjs} +6 -6
- package/dist/cli/{skills-6IL3LQUJ.mjs → skills-63SF5XTZ.mjs} +4 -4
- package/dist/cli/skills-C7MLZJEK.js +28 -0
- package/dist/cli/{tools-BOIRKQA4.mjs → tools-HNP35FVR.mjs} +5 -5
- package/dist/cli/{tools-TZLX4WAL.js → tools-RHL5K6UA.js} +50 -50
- package/dist/cli/{update-VF3BB3R7.mjs → update-BIUXK2GK.mjs} +6 -6
- package/dist/cli/update-NFJGKKZ6.js +28 -0
- package/dist/cli/{workflow-RUTOLKOS.js → workflow-45YNQNPE.js} +15 -15
- package/dist/cli/{workflow-UZKD5KU2.mjs → workflow-EKLCRCUD.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-DLGUNY3B.js +0 -31
- package/dist/cli/client-QLERARAF.js +0 -20
- package/dist/cli/git-SZHVHZWU.js +0 -23
- package/dist/cli/skills-AYCZ4UXS.js +0 -28
- package/dist/cli/update-EEFUC76J.js +0 -28
|
@@ -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.299',
|
|
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: {
|
|
@@ -1,20 +1,35 @@
|
|
|
1
1
|
export type MonitorQuickstartPrompt = {
|
|
2
|
+
id: string;
|
|
3
|
+
title: string;
|
|
4
|
+
description: string;
|
|
2
5
|
prompt: string;
|
|
3
6
|
icon: 'job-change' | 'new-hires' | 'hiring-signal';
|
|
4
7
|
};
|
|
5
8
|
|
|
9
|
+
/** Shared by the first-run card, template gallery, and template discovery API. */
|
|
6
10
|
export const MONITOR_QUICKSTART_PROMPTS: MonitorQuickstartPrompt[] = [
|
|
7
11
|
{
|
|
12
|
+
id: 'new-leadership-hires',
|
|
13
|
+
title: 'New leadership hires',
|
|
14
|
+
description:
|
|
15
|
+
'Watch target accounts for new VP Sales, Marketing, and Revenue hires.',
|
|
8
16
|
prompt:
|
|
9
17
|
'/deepline-gtm Monitor my target accounts for new VP Sales, Marketing, and Revenue hires.',
|
|
10
18
|
icon: 'new-hires',
|
|
11
19
|
},
|
|
12
20
|
{
|
|
21
|
+
id: 'champion-job-change',
|
|
22
|
+
title: 'Job changes',
|
|
23
|
+
description: 'Find when people at your target accounts change jobs.',
|
|
13
24
|
prompt:
|
|
14
25
|
'/deepline-gtm Monitor when people at my target accounts change jobs.',
|
|
15
26
|
icon: 'job-change',
|
|
16
27
|
},
|
|
17
28
|
{
|
|
29
|
+
id: 'job-post-keywords',
|
|
30
|
+
title: 'Job openings',
|
|
31
|
+
description:
|
|
32
|
+
'Watch target accounts for hiring signals in the roles you sell to.',
|
|
18
33
|
prompt:
|
|
19
34
|
'/deepline-gtm Monitor my target accounts for job openings in the roles I sell to.',
|
|
20
35
|
icon: 'hiring-signal',
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { MONITOR_QUICKSTART_PROMPTS } from './quickstart-prompts';
|
|
2
|
+
|
|
1
3
|
export type MonitorStarterTemplate = {
|
|
2
4
|
id: string;
|
|
3
5
|
title: string;
|
|
@@ -5,101 +7,10 @@ export type MonitorStarterTemplate = {
|
|
|
5
7
|
prompt: string;
|
|
6
8
|
};
|
|
7
9
|
|
|
8
|
-
export const MONITOR_STARTER_TEMPLATES: MonitorStarterTemplate[] =
|
|
9
|
-
{
|
|
10
|
-
id
|
|
11
|
-
title
|
|
12
|
-
description
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
Input: a list of target accounts, job title or description keywords, optional regions, and optional owner routing.
|
|
17
|
-
Behavior: check each account for recent open roles that match the keywords, dedupe against prior matches, enrich each match with company context and job URL, and rank the signal by relevance.
|
|
18
|
-
Output: one concise rep-ready message per owner with account name, matched role, why it matters, job URL, and recommended next step. Include Slack Block Kit formatting and an email fallback.
|
|
19
|
-
Verification: add a small dry-run input, run deepline plays check, run one sample execution against a scratch output destination, and report exactly what changed and what was not published.`,
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
id: 'champion-job-change',
|
|
23
|
-
title: 'Champion job change monitor',
|
|
24
|
-
description:
|
|
25
|
-
'Find when a known buyer, user, or champion joins a new account and route a warm-path action.',
|
|
26
|
-
prompt: `Create a Deepline definePlay() workflow for a champion job change monitor.
|
|
27
|
-
|
|
28
|
-
Input: known champions or contacts from CRM, their prior companies, owner routing rules, and optional target-account filters.
|
|
29
|
-
Behavior: detect likely role or company changes, validate the new company and title, suppress weak matches, and connect the signal back to the owning rep or CSM.
|
|
30
|
-
Output: one routed message per owner with champion name, old company, new company, new title, relationship context, source URL, and suggested outreach angle. Include Slack Block Kit formatting and an email fallback.
|
|
31
|
-
Verification: add a small dry-run input, run deepline plays check, run one sample execution against a scratch output destination, and report exactly what changed and what was not published.`,
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
id: 'website-page-change',
|
|
35
|
-
title: 'Website page change monitor',
|
|
36
|
-
description:
|
|
37
|
-
'Track pricing, docs, security, integrations, or product pages for GTM-relevant changes.',
|
|
38
|
-
prompt: `Create a Deepline definePlay() workflow for a website page change monitor.
|
|
39
|
-
|
|
40
|
-
Input: a list of account URLs, page categories to watch, a minimum change threshold, and owner routing rules.
|
|
41
|
-
Behavior: fetch current page content, compare it with the prior snapshot, classify meaningful GTM changes, ignore noisy cosmetic edits, and store the new snapshot only after a successful run.
|
|
42
|
-
Output: one routed message per owner with account name, changed URL, before/after summary, why the change matters, confidence, and suggested next step. Include Slack Block Kit formatting and an email fallback.
|
|
43
|
-
Verification: add a small dry-run input, run deepline plays check, run one sample execution against a scratch output destination, and report exactly what changed and what was not published.`,
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
id: 'website-visitor-intent',
|
|
47
|
-
title: 'Website visitor intent monitor',
|
|
48
|
-
description:
|
|
49
|
-
'Turn repeat high-value website visits into account-specific follow-up for the right owner.',
|
|
50
|
-
prompt: `Create a Deepline definePlay() workflow for a website visitor intent monitor.
|
|
51
|
-
|
|
52
|
-
Input: visitor or account intent events, high-intent page definitions, account matching rules, suppression rules, and owner routing.
|
|
53
|
-
Behavior: group events by account, score intent from page depth and recency, suppress existing active opportunities when configured, and explain why the account is worth actioning.
|
|
54
|
-
Output: one routed message per owner with account name, intent score, pages visited, timing, CRM context, and recommended next step. Include Slack Block Kit formatting and an email fallback.
|
|
55
|
-
Verification: add a small dry-run input, run deepline plays check, run one sample execution against a scratch output destination, and report exactly what changed and what was not published.`,
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
id: 'tech-stack-change',
|
|
59
|
-
title: 'Tech stack change monitor',
|
|
60
|
-
description:
|
|
61
|
-
'Detect install, removal, or competitor stack changes that create a concrete sales motion.',
|
|
62
|
-
prompt: `Create a Deepline definePlay() workflow for a tech stack change monitor.
|
|
63
|
-
|
|
64
|
-
Input: target accounts, technologies to watch, competitor or complementary-product tags, owner routing, and optional exclusion rules.
|
|
65
|
-
Behavior: detect meaningful install or removal events, confirm with available evidence, classify the motion as displacement, expansion, integration, or renewal risk, and dedupe prior alerts.
|
|
66
|
-
Output: one routed message per owner with account name, detected technology change, evidence, GTM interpretation, and suggested next step. Include Slack Block Kit formatting and an email fallback.
|
|
67
|
-
Verification: add a small dry-run input, run deepline plays check, run one sample execution against a scratch output destination, and report exactly what changed and what was not published.`,
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
id: 'social-community-mention',
|
|
71
|
-
title: 'Social and community mention monitor',
|
|
72
|
-
description:
|
|
73
|
-
'Catch relevant public mentions, buying questions, complaints, or competitor comparisons.',
|
|
74
|
-
prompt: `Create a Deepline definePlay() workflow for a social and community mention monitor.
|
|
75
|
-
|
|
76
|
-
Input: keywords, target accounts or personas, source allowlist, sentiment or category filters, and owner routing rules.
|
|
77
|
-
Behavior: find recent relevant mentions, classify each mention as buying intent, competitor comparison, complaint, hiring, integration request, or general awareness, and suppress duplicates or low-quality chatter.
|
|
78
|
-
Output: one routed message per owner with mention summary, source link, account/person context, signal category, confidence, and suggested next step. Include Slack Block Kit formatting and an email fallback.
|
|
79
|
-
Verification: add a small dry-run input, run deepline plays check, run one sample execution against a scratch output destination, and report exactly what changed and what was not published.`,
|
|
80
|
-
},
|
|
81
|
-
{
|
|
82
|
-
id: 'competitor-churn',
|
|
83
|
-
title: 'Competitor complaint monitor',
|
|
84
|
-
description:
|
|
85
|
-
'Surface competitor dissatisfaction or sunset risk while the account is likely open to change.',
|
|
86
|
-
prompt: `Create a Deepline definePlay() workflow for a competitor complaint monitor.
|
|
87
|
-
|
|
88
|
-
Input: competitor names, complaint or migration keywords, source allowlist, target-account matching rules, and owner routing.
|
|
89
|
-
Behavior: find recent competitor dissatisfaction or sunset-risk mentions, match them to companies where possible, classify the pain, and suppress vague or stale mentions.
|
|
90
|
-
Output: one routed message per owner with account or person, competitor, pain summary, source URL, suggested displacement angle, and confidence. Include Slack Block Kit formatting and an email fallback.
|
|
91
|
-
Verification: add a small dry-run input, run deepline plays check, run one sample execution against a scratch output destination, and report exactly what changed and what was not published.`,
|
|
92
|
-
},
|
|
93
|
-
{
|
|
94
|
-
id: 'customer-usage-renewal',
|
|
95
|
-
title: 'Customer usage and renewal monitor',
|
|
96
|
-
description:
|
|
97
|
-
'Route expansion, risk, and renewal signals from product behavior to the account team.',
|
|
98
|
-
prompt: `Create a Deepline definePlay() workflow for a customer usage and renewal monitor.
|
|
99
|
-
|
|
100
|
-
Input: product usage events, entitlement limits, renewal dates, account health fields, and owner routing.
|
|
101
|
-
Behavior: detect expansion signals, underuse risk, overage pressure, renewal timing, or feature adoption changes; explain the evidence; and suppress noisy repeat alerts.
|
|
102
|
-
Output: one routed message per owner with account name, signal type, usage evidence, renewal context, business impact, and suggested next step. Include Slack Block Kit formatting and an email fallback.
|
|
103
|
-
Verification: add a small dry-run input, run deepline plays check, run one sample execution against a scratch output destination, and report exactly what changed and what was not published.`,
|
|
104
|
-
},
|
|
105
|
-
];
|
|
10
|
+
export const MONITOR_STARTER_TEMPLATES: MonitorStarterTemplate[] =
|
|
11
|
+
MONITOR_QUICKSTART_PROMPTS.map(({ id, title, description, prompt }) => ({
|
|
12
|
+
id,
|
|
13
|
+
title,
|
|
14
|
+
description,
|
|
15
|
+
prompt,
|
|
16
|
+
}));
|
|
@@ -149,6 +149,13 @@ export type AsyncOperationContractWire = {
|
|
|
149
149
|
launchValue?: boolean;
|
|
150
150
|
}
|
|
151
151
|
| { kind: 'caller_managed' };
|
|
152
|
+
/** Opt-in completion wait for keyed API calls; ordinary Play waiting is unchanged. */
|
|
153
|
+
recoveryWait?: {
|
|
154
|
+
kind: 'input_flag';
|
|
155
|
+
field: string;
|
|
156
|
+
default: boolean;
|
|
157
|
+
launchValue?: boolean;
|
|
158
|
+
};
|
|
152
159
|
};
|
|
153
160
|
|
|
154
161
|
export type AsyncOperationContract = AsyncOperationContractWire;
|
|
@@ -363,6 +370,8 @@ export function defineAsyncOperation(
|
|
|
363
370
|
required(contract.result.path, 'result.path');
|
|
364
371
|
if (contract.wait.kind === 'input_flag')
|
|
365
372
|
required(contract.wait.field, 'wait.field');
|
|
373
|
+
if (contract.recoveryWait)
|
|
374
|
+
required(contract.recoveryWait.field, 'recoveryWait.field');
|
|
366
375
|
if (typeof contract.compatibility?.asyncGetAction === 'string') {
|
|
367
376
|
required(
|
|
368
377
|
contract.compatibility.asyncGetAction,
|
|
@@ -567,8 +576,12 @@ export function readAsyncOperationPath(value: unknown, path: string): unknown {
|
|
|
567
576
|
if (path === '$' || path === '') return value;
|
|
568
577
|
let current = value;
|
|
569
578
|
for (const segment of path.split('.').filter(Boolean)) {
|
|
570
|
-
if (!current || typeof current !== 'object'
|
|
571
|
-
|
|
579
|
+
if (!current || typeof current !== 'object') return undefined;
|
|
580
|
+
if (Array.isArray(current)) {
|
|
581
|
+
if (!/^(0|[1-9]\d*)$/.test(segment)) return undefined;
|
|
582
|
+
current = current[Number(segment)];
|
|
583
|
+
continue;
|
|
584
|
+
}
|
|
572
585
|
current = (current as Record<string, unknown>)[segment];
|
|
573
586
|
}
|
|
574
587
|
return current;
|
|
@@ -196,6 +196,8 @@ export const RUNTIME_SCHEDULER_CANCEL_STATEMENT_TIMEOUT_MS = 15_000;
|
|
|
196
196
|
|
|
197
197
|
export type RuntimeSchedulerPoolOptions = {
|
|
198
198
|
url: string;
|
|
199
|
+
/** Background indexing must not occupy the lifecycle checkout budget. */
|
|
200
|
+
purpose?: 'observability';
|
|
199
201
|
applicationName?: string;
|
|
200
202
|
maxClients?: number;
|
|
201
203
|
/**
|
|
@@ -783,7 +785,7 @@ function getPoolEntry(options: RuntimeSchedulerPoolOptions): PoolEntry {
|
|
|
783
785
|
// The connection lifetime is part of a Pool's semantics. Do not let a
|
|
784
786
|
// serverless short-idle caller accidentally reuse a long-lived worker pool
|
|
785
787
|
// merely because both target the same runtime database.
|
|
786
|
-
const key = `${connectionString}::${maxClients}::${idleTimeoutMs}::${maxAcquireQueueDepth}::${maxAcquireQueueWaitMs}`;
|
|
788
|
+
const key = `${connectionString}::${maxClients}::${idleTimeoutMs}::${maxAcquireQueueDepth}::${maxAcquireQueueWaitMs}${options.purpose === 'observability' ? '::observability' : ''}`;
|
|
787
789
|
const existing = registry.get(key);
|
|
788
790
|
if (existing) {
|
|
789
791
|
// Next dev can retain the process-global pool across a module hot reload.
|
|
@@ -18023,10 +18023,15 @@ async function claimPostgresSchedulerOutboxPrefix(
|
|
|
18023
18023
|
input.searchOnly === true
|
|
18024
18024
|
? runLedgerTerminalPendingSql(alias, options)
|
|
18025
18025
|
: runLedgerUrgentLifecyclePendingSql(alias, options);
|
|
18026
|
+
// Search is locally indexed and acknowledged; it has no remote ingress
|
|
18027
|
+
// receipt to freeze. Preserve causal ordering/due/lease checks, but admit
|
|
18028
|
+
// its full prefix instead of inheriting lifecycle's singleton transport.
|
|
18026
18029
|
const ingressPrefixSql =
|
|
18027
|
-
|
|
18028
|
-
?
|
|
18029
|
-
:
|
|
18030
|
+
input.searchOnly === true
|
|
18031
|
+
? 'true'
|
|
18032
|
+
: supportsTerminalBatchMarker && input.allowIngressPrefix === true
|
|
18033
|
+
? `(head.event_type = ${RUN_SCHEDULER_OUTBOX_EVENT_TYPE_SQL_LITERAL.runEvents})`
|
|
18034
|
+
: 'false';
|
|
18030
18035
|
return await client.query<{
|
|
18031
18036
|
row_kind: 'claimed' | 'delivered';
|
|
18032
18037
|
event_id: string;
|
|
@@ -18145,14 +18150,16 @@ async function claimPostgresSchedulerOutboxPrefix(
|
|
|
18145
18150
|
-- Admission is causally first and must be projected alone. A later
|
|
18146
18151
|
-- start/terminal append may not leapfrog a delayed queued row.
|
|
18147
18152
|
AND (
|
|
18148
|
-
|
|
18153
|
+
${input.searchOnly === true ? 'true' : 'false'}
|
|
18154
|
+
OR head.event_type NOT IN (${RUN_EVENT_KIND_SQL_LITERAL.runCreated}, ${RUN_EVENT_KIND_SQL_LITERAL.runStarted}, ${RUN_SCHEDULER_OUTBOX_EVENT_TYPE_SQL_LITERAL.runEvents})
|
|
18149
18155
|
OR outbox.event_id = head.event_id
|
|
18150
18156
|
OR (head.event_type = ${RUN_SCHEDULER_OUTBOX_EVENT_TYPE_SQL_LITERAL.runEvents}
|
|
18151
18157
|
AND ${ingressPrefixSql})
|
|
18152
18158
|
)
|
|
18153
18159
|
-- Only a receiver with the exact-prefix verifier may combine ingress
|
|
18154
18160
|
-- facts; old launch origins and schemas retain singleton receipts.
|
|
18155
|
-
AND (
|
|
18161
|
+
AND (${input.searchOnly === true ? 'true' : 'false'}
|
|
18162
|
+
OR outbox.event_type <> ${RUN_SCHEDULER_OUTBOX_EVENT_TYPE_SQL_LITERAL.runEvents}
|
|
18156
18163
|
OR outbox.event_id = head.event_id
|
|
18157
18164
|
OR ${ingressPrefixSql})
|
|
18158
18165
|
-- Once any ingress prefix was attempted, its receipt is immutable,
|
|
@@ -19456,6 +19463,11 @@ export function postgresSchedulerCancellationOutboxLease(runId: string): {
|
|
|
19456
19463
|
}
|
|
19457
19464
|
|
|
19458
19465
|
export type RunLedgerOutboxDispatchInput = {
|
|
19466
|
+
/** Dedicated bounded checkout for indexing; claims/ACKs use withClient. */
|
|
19467
|
+
withObservabilityClient?: <T>(
|
|
19468
|
+
operation: (client: PostgresSchedulerQueryClient) => Promise<T>,
|
|
19469
|
+
) => Promise<T>;
|
|
19470
|
+
|
|
19459
19471
|
/** Only the existing background projector claims the independent search prefix. */
|
|
19460
19472
|
searchOnly?: boolean;
|
|
19461
19473
|
/** Only the existing background projector indexes deferred raw inputs. */
|
|
@@ -19995,63 +20007,98 @@ async function dispatchRunLedgerOutboxBatchWithScope(
|
|
|
19995
20007
|
retryingEventIds: released,
|
|
19996
20008
|
};
|
|
19997
20009
|
}
|
|
19998
|
-
|
|
19999
|
-
|
|
20010
|
+
const deferredEvents = events.filter(
|
|
20011
|
+
(event) =>
|
|
20000
20012
|
payloadField(
|
|
20001
20013
|
event.payload,
|
|
20002
20014
|
RUNTIME_EVENT_DEFERRED_PROJECTION_FIELD,
|
|
20003
|
-
)
|
|
20004
|
-
|
|
20005
|
-
|
|
20006
|
-
await withClient(
|
|
20007
|
-
|
|
20015
|
+
) === true,
|
|
20016
|
+
);
|
|
20017
|
+
const materialize = async (prefix: typeof deferredEvents) => {
|
|
20018
|
+
await withClient((client) =>
|
|
20019
|
+
renewPostgresRunLedgerDelivery(
|
|
20008
20020
|
client,
|
|
20009
20021
|
{
|
|
20010
|
-
eventIds: events.map((
|
|
20022
|
+
eventIds: events.map((event) => event.eventId),
|
|
20011
20023
|
leaseOwner,
|
|
20012
20024
|
leaseSeconds: 120,
|
|
20013
20025
|
},
|
|
20014
20026
|
options,
|
|
20015
|
-
)
|
|
20016
|
-
|
|
20017
|
-
|
|
20027
|
+
),
|
|
20028
|
+
);
|
|
20029
|
+
await (input.withObservabilityClient ?? withClient)(async (client) => {
|
|
20018
20030
|
await client.query('BEGIN');
|
|
20019
20031
|
try {
|
|
20020
|
-
// Let PostgreSQL cancel before the pool's client-side timeout,
|
|
20021
|
-
// so rollback completes while the checkout is still usable.
|
|
20022
20032
|
await client.query(
|
|
20023
20033
|
"SELECT set_config('statement_timeout', $1, true)",
|
|
20024
20034
|
[
|
|
20025
20035
|
`${Math.min(60_000, RUNTIME_RELIABILITY_POLICY.schedulerDatabase.queryTimeoutMs - 1_000)}ms`,
|
|
20026
20036
|
],
|
|
20027
20037
|
);
|
|
20028
|
-
|
|
20029
|
-
|
|
20030
|
-
|
|
20038
|
+
// The recursive dependency evaluates this already-bounded causal
|
|
20039
|
+
// prefix in order, in one database round trip. Its eight-fact
|
|
20040
|
+
// contract is unchanged. The timeout bounds the entire statement
|
|
20041
|
+
// below the lease; the installed function still fences every fact.
|
|
20042
|
+
const result = await client.query<{
|
|
20043
|
+
ordinal: number;
|
|
20044
|
+
payload: unknown;
|
|
20045
|
+
}>(
|
|
20046
|
+
`WITH RECURSIVE projected(ordinal, payload) AS (
|
|
20047
|
+
SELECT 1, ${quoteIdent(schemaName(options))}.materialize_runtime_outbox_event(($1::text[])[1], $2)
|
|
20048
|
+
UNION ALL
|
|
20049
|
+
SELECT prior.ordinal + 1,
|
|
20050
|
+
${quoteIdent(schemaName(options))}.materialize_runtime_outbox_event(($1::text[])[prior.ordinal + 1], $2)
|
|
20051
|
+
FROM projected AS prior
|
|
20052
|
+
WHERE prior.ordinal < cardinality($1::text[])
|
|
20053
|
+
)
|
|
20054
|
+
SELECT ordinal, payload FROM projected ORDER BY ordinal`,
|
|
20055
|
+
[prefix.map((event) => event.eventId), leaseOwner],
|
|
20031
20056
|
);
|
|
20032
20057
|
await client.query('COMMIT');
|
|
20033
|
-
|
|
20058
|
+
for (const row of result.rows)
|
|
20059
|
+
prefix[row.ordinal - 1]!.payload = row.payload;
|
|
20034
20060
|
} catch (error) {
|
|
20035
20061
|
await client.query('ROLLBACK');
|
|
20062
|
+
throw error;
|
|
20063
|
+
}
|
|
20064
|
+
});
|
|
20065
|
+
};
|
|
20066
|
+
try {
|
|
20067
|
+
await materialize(deferredEvents);
|
|
20068
|
+
} catch (error) {
|
|
20069
|
+
if (
|
|
20070
|
+
!(
|
|
20071
|
+
error &&
|
|
20072
|
+
typeof error === 'object' &&
|
|
20073
|
+
'code' in error &&
|
|
20074
|
+
error.code === 'P0001'
|
|
20075
|
+
)
|
|
20076
|
+
) {
|
|
20077
|
+
throw error;
|
|
20078
|
+
}
|
|
20079
|
+
// An invalid immutable fact must quarantine only itself. The aborted
|
|
20080
|
+
// batch wrote nothing; replay its small prefix one fact at a time to
|
|
20081
|
+
// identify that fact and retain the valid indexed predecessors.
|
|
20082
|
+
for (const event of deferredEvents) {
|
|
20083
|
+
try {
|
|
20084
|
+
await materialize([event]);
|
|
20085
|
+
} catch (factError) {
|
|
20036
20086
|
if (
|
|
20037
|
-
|
|
20038
|
-
typeof
|
|
20039
|
-
'code' in
|
|
20040
|
-
|
|
20087
|
+
factError &&
|
|
20088
|
+
typeof factError === 'object' &&
|
|
20089
|
+
'code' in factError &&
|
|
20090
|
+
factError.code === 'P0001'
|
|
20041
20091
|
) {
|
|
20042
|
-
// The installed projector's explicit RAISEs reject malformed
|
|
20043
|
-
// or conflicting immutable facts. Retain them in the existing
|
|
20044
|
-
// quarantine instead of retrying the same invalid input forever.
|
|
20045
20092
|
throw new DeferredRuntimeProjectionInputError(
|
|
20046
20093
|
event.eventId,
|
|
20047
|
-
|
|
20048
|
-
?
|
|
20094
|
+
factError instanceof Error
|
|
20095
|
+
? factError.message
|
|
20049
20096
|
: 'Invalid runtime event projection input.',
|
|
20050
20097
|
);
|
|
20051
20098
|
}
|
|
20052
|
-
throw
|
|
20099
|
+
throw factError;
|
|
20053
20100
|
}
|
|
20054
|
-
}
|
|
20101
|
+
}
|
|
20055
20102
|
}
|
|
20056
20103
|
}
|
|
20057
20104
|
return null;
|