deepline 0.3.174 → 0.3.175
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/client.ts +3 -0
- package/dist/bundling-sources/sdk/src/release.ts +1 -1
- package/dist/bundling-sources/shared_libs/integration-contracts/index.ts +1 -0
- package/dist/bundling-sources/shared_libs/integration-contracts/waterfall/execution-policy.ts +18 -0
- package/dist/bundling-sources/shared_libs/play-data-plane/index.ts +1 -0
- package/dist/bundling-sources/shared_libs/play-data-plane/runtime-sheet-orm.ts +489 -0
- package/dist/bundling-sources/shared_libs/play-data-plane/runtime-sheet-storage-contract.ts +4 -13
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +143 -110
- package/dist/cli/index.js +13 -1
- package/dist/cli/index.mjs +13 -1
- package/dist/index.js +13 -1
- package/dist/index.mjs +13 -1
- package/dist/install-integrity.json +2 -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
|
@@ -107,6 +107,7 @@ import type { PlayCompilerManifest } from '../../shared_libs/plays/compiler-mani
|
|
|
107
107
|
import type { EnrichCompiledConfig } from './cli/enrich-play-compiler.js';
|
|
108
108
|
import { RUNTIME_ENVIRONMENT_TOKEN_HEADER } from '../../shared_libs/play-runtime/coordinator-headers.js';
|
|
109
109
|
import { resolveTheirstackClientTimeoutMs } from '../../shared_libs/integration-contracts/theirstack/execution-policy.js';
|
|
110
|
+
import { resolveWaterfallClientTimeoutMs } from '../../shared_libs/integration-contracts/waterfall/execution-policy.js';
|
|
110
111
|
import {
|
|
111
112
|
BETTERCONTACT_LAUNCHER_CLIENT_TIMEOUT_MS,
|
|
112
113
|
usesExtendedBetterContactLauncherBudget,
|
|
@@ -724,6 +725,8 @@ function resolveToolExecuteTimeoutMs(
|
|
|
724
725
|
input,
|
|
725
726
|
);
|
|
726
727
|
if (theirstackTimeoutMs !== null) return theirstackTimeoutMs;
|
|
728
|
+
const waterfallTimeoutMs = resolveWaterfallClientTimeoutMs(normalized);
|
|
729
|
+
if (waterfallTimeoutMs !== null) return waterfallTimeoutMs;
|
|
727
730
|
if (usesExtendedBetterContactLauncherBudget(normalized)) {
|
|
728
731
|
return BETTERCONTACT_LAUNCHER_CLIENT_TIMEOUT_MS;
|
|
729
732
|
}
|
|
@@ -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.175',
|
|
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: {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Waterfall launcher responses include a bounded launch-and-poll window. The
|
|
3
|
+
* SDK default is only 60 seconds, which can abandon a valid prospector job
|
|
4
|
+
* while the server is still polling it. Keep this budget specific to the
|
|
5
|
+
* launcher instead of widening every integration request.
|
|
6
|
+
*/
|
|
7
|
+
export const WATERFALL_PROSPECTOR_CLIENT_TIMEOUT_MS = 180_000;
|
|
8
|
+
|
|
9
|
+
const WATERFALL_PROSPECTOR_LAUNCHER_TOOL_IDS = new Set([
|
|
10
|
+
'prospector',
|
|
11
|
+
'deepline_native_prospector',
|
|
12
|
+
]);
|
|
13
|
+
|
|
14
|
+
export function resolveWaterfallClientTimeoutMs(toolId: string): number | null {
|
|
15
|
+
return WATERFALL_PROSPECTOR_LAUNCHER_TOOL_IDS.has(toolId.trim().toLowerCase())
|
|
16
|
+
? WATERFALL_PROSPECTOR_CLIENT_TIMEOUT_MS
|
|
17
|
+
: null;
|
|
18
|
+
}
|
|
@@ -0,0 +1,489 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed owner for the physical Runtime Sheet table contract.
|
|
3
|
+
*
|
|
4
|
+
* This is intentionally a small ORM seam, not a general SQL builder. It owns
|
|
5
|
+
* the facts that every Runtime Sheet writer needs to agree on: which columns
|
|
6
|
+
* belong to Deepline, what shape they have, how readiness is determined, and
|
|
7
|
+
* which additive/default repairs are safe. Application and worker code supply
|
|
8
|
+
* the query adapter and keep their transport-specific concerns outside this
|
|
9
|
+
* Module.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
export const RUNTIME_SHEET_VERSION_SEQUENCE = '_deepline_sheet_version_seq';
|
|
13
|
+
|
|
14
|
+
export const RUNTIME_SHEET_CELL_META_COLUMN = {
|
|
15
|
+
name: '_cell_meta',
|
|
16
|
+
dataType: 'jsonb',
|
|
17
|
+
nullable: 'NO',
|
|
18
|
+
defaultSql: "'{}'::jsonb",
|
|
19
|
+
} as const;
|
|
20
|
+
|
|
21
|
+
type RuntimeSheetNullable = 'YES' | 'NO';
|
|
22
|
+
|
|
23
|
+
export type RuntimeSheetColumnContract = {
|
|
24
|
+
name: string;
|
|
25
|
+
sqlType: string;
|
|
26
|
+
dataType: string;
|
|
27
|
+
nullable: RuntimeSheetNullable;
|
|
28
|
+
defaultSql: string | null;
|
|
29
|
+
defaultKind?: 'version_sequence';
|
|
30
|
+
/** A missing column can be added without guessing at customer data. */
|
|
31
|
+
repairable: boolean;
|
|
32
|
+
/** The column must have a default because writers intentionally omit it. */
|
|
33
|
+
requiresDefault: boolean;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export type RuntimeSheetColumnState = {
|
|
37
|
+
column_name: string;
|
|
38
|
+
data_type: string;
|
|
39
|
+
is_nullable: string;
|
|
40
|
+
column_default: string | null;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export type RuntimeSheetSchemaSnapshot = {
|
|
44
|
+
sequenceExists: boolean;
|
|
45
|
+
columns: ReadonlyMap<string, RuntimeSheetColumnState>;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export type RuntimeSheetSchemaReadiness = {
|
|
49
|
+
ready: boolean;
|
|
50
|
+
missingColumns: string[];
|
|
51
|
+
incompatibleColumns: string[];
|
|
52
|
+
missingDefaults: string[];
|
|
53
|
+
sequenceReady: boolean;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export type RuntimeSheetOrmQuery = <Row = Record<string, unknown>>(
|
|
57
|
+
sql: string,
|
|
58
|
+
params?: readonly unknown[],
|
|
59
|
+
) => Promise<{ rows: Row[] }>;
|
|
60
|
+
|
|
61
|
+
export type RuntimeSheetOrm = {
|
|
62
|
+
inspect(): Promise<RuntimeSheetSchemaSnapshot>;
|
|
63
|
+
readiness(
|
|
64
|
+
snapshot?: RuntimeSheetSchemaSnapshot,
|
|
65
|
+
): Promise<RuntimeSheetSchemaReadiness>;
|
|
66
|
+
repairOwnerMetadata(): Promise<void>;
|
|
67
|
+
isOwnerMetadataConstraintError(error: unknown): boolean;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
export function isRuntimeSheetOwnerMetadataConstraintError(
|
|
71
|
+
error: unknown,
|
|
72
|
+
input: { table: string },
|
|
73
|
+
): boolean {
|
|
74
|
+
if (!error || typeof error !== 'object') return false;
|
|
75
|
+
const record = error as Record<string, unknown>;
|
|
76
|
+
if (String(record.code ?? '') !== '23502') return false;
|
|
77
|
+
const table = typeof record.table === 'string' ? record.table : null;
|
|
78
|
+
const message = typeof record.message === 'string' ? record.message : '';
|
|
79
|
+
const tableMatches =
|
|
80
|
+
table === input.table || message.includes(`relation "${input.table}"`);
|
|
81
|
+
const column = readColumnName(error);
|
|
82
|
+
return (
|
|
83
|
+
tableMatches &&
|
|
84
|
+
column !== null &&
|
|
85
|
+
RUNTIME_SHEET_REPAIRABLE_COLUMNS.some(
|
|
86
|
+
(contract) => contract.name === column,
|
|
87
|
+
)
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const RUNTIME_SHEET_COLUMN_CONTRACTS: readonly RuntimeSheetColumnContract[] = [
|
|
92
|
+
{
|
|
93
|
+
name: '_key',
|
|
94
|
+
sqlType: 'text',
|
|
95
|
+
dataType: 'text',
|
|
96
|
+
nullable: 'NO',
|
|
97
|
+
defaultSql: null,
|
|
98
|
+
repairable: false,
|
|
99
|
+
requiresDefault: false,
|
|
100
|
+
},
|
|
101
|
+
{
|
|
102
|
+
name: '_status',
|
|
103
|
+
sqlType: 'text NOT NULL',
|
|
104
|
+
dataType: 'text',
|
|
105
|
+
nullable: 'NO',
|
|
106
|
+
defaultSql: null,
|
|
107
|
+
repairable: false,
|
|
108
|
+
requiresDefault: false,
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
name: '_run_id',
|
|
112
|
+
sqlType: 'text',
|
|
113
|
+
dataType: 'text',
|
|
114
|
+
nullable: 'YES',
|
|
115
|
+
defaultSql: null,
|
|
116
|
+
repairable: true,
|
|
117
|
+
requiresDefault: false,
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
name: '_error',
|
|
121
|
+
sqlType: 'text',
|
|
122
|
+
dataType: 'text',
|
|
123
|
+
nullable: 'YES',
|
|
124
|
+
defaultSql: null,
|
|
125
|
+
repairable: true,
|
|
126
|
+
requiresDefault: false,
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
name: '_stage',
|
|
130
|
+
sqlType: 'text',
|
|
131
|
+
dataType: 'text',
|
|
132
|
+
nullable: 'YES',
|
|
133
|
+
defaultSql: null,
|
|
134
|
+
repairable: true,
|
|
135
|
+
requiresDefault: false,
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
name: '_provider',
|
|
139
|
+
sqlType: 'text',
|
|
140
|
+
dataType: 'text',
|
|
141
|
+
nullable: 'YES',
|
|
142
|
+
defaultSql: null,
|
|
143
|
+
repairable: true,
|
|
144
|
+
requiresDefault: false,
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
name: '_input_index',
|
|
148
|
+
sqlType: 'bigint',
|
|
149
|
+
dataType: 'bigint',
|
|
150
|
+
nullable: 'YES',
|
|
151
|
+
defaultSql: null,
|
|
152
|
+
repairable: true,
|
|
153
|
+
requiresDefault: false,
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
name: '_attempt_id',
|
|
157
|
+
sqlType: 'text',
|
|
158
|
+
dataType: 'text',
|
|
159
|
+
nullable: 'YES',
|
|
160
|
+
defaultSql: null,
|
|
161
|
+
repairable: true,
|
|
162
|
+
requiresDefault: false,
|
|
163
|
+
},
|
|
164
|
+
{
|
|
165
|
+
name: '_attempt_owner_run_id',
|
|
166
|
+
sqlType: 'text',
|
|
167
|
+
dataType: 'text',
|
|
168
|
+
nullable: 'YES',
|
|
169
|
+
defaultSql: null,
|
|
170
|
+
repairable: true,
|
|
171
|
+
requiresDefault: false,
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
name: '_attempt_expires_at',
|
|
175
|
+
sqlType: 'timestamptz',
|
|
176
|
+
dataType: 'timestamp with time zone',
|
|
177
|
+
nullable: 'YES',
|
|
178
|
+
defaultSql: null,
|
|
179
|
+
repairable: true,
|
|
180
|
+
requiresDefault: false,
|
|
181
|
+
},
|
|
182
|
+
{
|
|
183
|
+
name: '_attempt_seq',
|
|
184
|
+
sqlType: 'integer',
|
|
185
|
+
dataType: 'integer',
|
|
186
|
+
nullable: 'YES',
|
|
187
|
+
defaultSql: null,
|
|
188
|
+
repairable: true,
|
|
189
|
+
requiresDefault: false,
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
name: '_write_version',
|
|
193
|
+
sqlType: 'bigint NOT NULL DEFAULT 0',
|
|
194
|
+
dataType: 'bigint',
|
|
195
|
+
nullable: 'NO',
|
|
196
|
+
defaultSql: '0',
|
|
197
|
+
repairable: true,
|
|
198
|
+
requiresDefault: true,
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
name: '_writer_run_id',
|
|
202
|
+
sqlType: 'text',
|
|
203
|
+
dataType: 'text',
|
|
204
|
+
nullable: 'YES',
|
|
205
|
+
defaultSql: null,
|
|
206
|
+
repairable: true,
|
|
207
|
+
requiresDefault: false,
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
name: '_created_at',
|
|
211
|
+
sqlType: 'timestamptz NOT NULL DEFAULT now()',
|
|
212
|
+
dataType: 'timestamp with time zone',
|
|
213
|
+
nullable: 'NO',
|
|
214
|
+
defaultSql: 'now()',
|
|
215
|
+
repairable: true,
|
|
216
|
+
requiresDefault: true,
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
name: '_updated_at',
|
|
220
|
+
sqlType: 'timestamptz NOT NULL DEFAULT now()',
|
|
221
|
+
dataType: 'timestamp with time zone',
|
|
222
|
+
nullable: 'NO',
|
|
223
|
+
defaultSql: 'now()',
|
|
224
|
+
repairable: true,
|
|
225
|
+
requiresDefault: true,
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
name: '_version',
|
|
229
|
+
sqlType: 'bigint NOT NULL',
|
|
230
|
+
dataType: 'bigint',
|
|
231
|
+
nullable: 'NO',
|
|
232
|
+
defaultSql: null,
|
|
233
|
+
defaultKind: 'version_sequence',
|
|
234
|
+
repairable: true,
|
|
235
|
+
requiresDefault: true,
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
...RUNTIME_SHEET_CELL_META_COLUMN,
|
|
239
|
+
sqlType: `jsonb NOT NULL DEFAULT ${RUNTIME_SHEET_CELL_META_COLUMN.defaultSql}`,
|
|
240
|
+
repairable: true,
|
|
241
|
+
requiresDefault: true,
|
|
242
|
+
},
|
|
243
|
+
];
|
|
244
|
+
|
|
245
|
+
export const RUNTIME_SHEET_ATTEMPT_COLUMNS =
|
|
246
|
+
RUNTIME_SHEET_COLUMN_CONTRACTS.filter((column) =>
|
|
247
|
+
column.name.startsWith('_attempt_'),
|
|
248
|
+
).map((column) => column.name);
|
|
249
|
+
|
|
250
|
+
export const RUNTIME_SHEET_WRITE_VERSION_COLUMNS =
|
|
251
|
+
RUNTIME_SHEET_COLUMN_CONTRACTS.filter(
|
|
252
|
+
(column) =>
|
|
253
|
+
column.name === '_write_version' || column.name === '_writer_run_id',
|
|
254
|
+
).map((column) => column.name);
|
|
255
|
+
|
|
256
|
+
export const RUNTIME_SHEET_TIMESTAMP_COLUMNS =
|
|
257
|
+
RUNTIME_SHEET_COLUMN_CONTRACTS.filter(
|
|
258
|
+
(column) => column.name === '_created_at' || column.name === '_updated_at',
|
|
259
|
+
).map((column) => column.name);
|
|
260
|
+
|
|
261
|
+
export const RUNTIME_SHEET_SYSTEM_COLUMNS = new Set(
|
|
262
|
+
RUNTIME_SHEET_COLUMN_CONTRACTS.map((column) => column.name),
|
|
263
|
+
);
|
|
264
|
+
|
|
265
|
+
const RUNTIME_SHEET_REPAIRABLE_COLUMNS = RUNTIME_SHEET_COLUMN_CONTRACTS.filter(
|
|
266
|
+
(column) => column.repairable,
|
|
267
|
+
);
|
|
268
|
+
|
|
269
|
+
export function runtimeSheetColumnContracts(): readonly RuntimeSheetColumnContract[] {
|
|
270
|
+
return RUNTIME_SHEET_COLUMN_CONTRACTS;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export function runtimeSheetRepairableColumnContracts(): readonly RuntimeSheetColumnContract[] {
|
|
274
|
+
return RUNTIME_SHEET_REPAIRABLE_COLUMNS;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
export function isRuntimeSheetSystemColumn(columnName: string): boolean {
|
|
278
|
+
return RUNTIME_SHEET_SYSTEM_COLUMNS.has(columnName);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* SQL projection for adapters that already have a larger relation-readiness
|
|
283
|
+
* query. The expected rows are generated from the contract, so adding an
|
|
284
|
+
* owner column expands this projection automatically instead of requiring a
|
|
285
|
+
* new field-specific boolean in every adapter.
|
|
286
|
+
*/
|
|
287
|
+
export function runtimeSheetOwnerColumnsReadinessSql(input: {
|
|
288
|
+
schemaParam: string;
|
|
289
|
+
tableParam: string;
|
|
290
|
+
}): string {
|
|
291
|
+
const expectedRows = RUNTIME_SHEET_COLUMN_CONTRACTS.map(
|
|
292
|
+
(column) =>
|
|
293
|
+
`(${quoteLiteral(column.name)}, ${quoteLiteral(column.dataType)}, ${quoteLiteral(column.nullable)}, ${column.requiresDefault ? 'TRUE' : 'FALSE'})`,
|
|
294
|
+
).join(',\n ');
|
|
295
|
+
return `(
|
|
296
|
+
SELECT count(*) = ${RUNTIME_SHEET_COLUMN_CONTRACTS.length}
|
|
297
|
+
FROM information_schema.columns AS actual
|
|
298
|
+
JOIN (VALUES
|
|
299
|
+
${expectedRows}
|
|
300
|
+
) AS expected(column_name, data_type, is_nullable, requires_default)
|
|
301
|
+
ON expected.column_name = actual.column_name
|
|
302
|
+
WHERE actual.table_schema = ${input.schemaParam}
|
|
303
|
+
AND actual.table_name = ${input.tableParam}
|
|
304
|
+
AND actual.data_type = expected.data_type
|
|
305
|
+
AND actual.is_nullable = expected.is_nullable
|
|
306
|
+
AND (NOT expected.requires_default OR actual.column_default IS NOT NULL)
|
|
307
|
+
)`;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
export function isRuntimeSheetColumnReady(
|
|
311
|
+
contract: RuntimeSheetColumnContract,
|
|
312
|
+
state: RuntimeSheetColumnState | undefined,
|
|
313
|
+
): boolean {
|
|
314
|
+
return (
|
|
315
|
+
state?.data_type === contract.dataType &&
|
|
316
|
+
state.is_nullable === contract.nullable &&
|
|
317
|
+
(!contract.requiresDefault || state.column_default != null)
|
|
318
|
+
);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
export function evaluateRuntimeSheetSchema(
|
|
322
|
+
snapshot: RuntimeSheetSchemaSnapshot,
|
|
323
|
+
): RuntimeSheetSchemaReadiness {
|
|
324
|
+
const missingColumns: string[] = [];
|
|
325
|
+
const incompatibleColumns: string[] = [];
|
|
326
|
+
const missingDefaults: string[] = [];
|
|
327
|
+
|
|
328
|
+
for (const contract of RUNTIME_SHEET_COLUMN_CONTRACTS) {
|
|
329
|
+
const state = snapshot.columns.get(contract.name);
|
|
330
|
+
if (!state) {
|
|
331
|
+
missingColumns.push(contract.name);
|
|
332
|
+
continue;
|
|
333
|
+
}
|
|
334
|
+
if (
|
|
335
|
+
state.data_type !== contract.dataType ||
|
|
336
|
+
state.is_nullable !== contract.nullable
|
|
337
|
+
) {
|
|
338
|
+
incompatibleColumns.push(contract.name);
|
|
339
|
+
continue;
|
|
340
|
+
}
|
|
341
|
+
if (contract.requiresDefault && state.column_default == null) {
|
|
342
|
+
missingDefaults.push(contract.name);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
const sequenceReady = snapshot.sequenceExists;
|
|
347
|
+
return {
|
|
348
|
+
ready:
|
|
349
|
+
missingColumns.length === 0 &&
|
|
350
|
+
incompatibleColumns.length === 0 &&
|
|
351
|
+
missingDefaults.length === 0 &&
|
|
352
|
+
sequenceReady,
|
|
353
|
+
missingColumns,
|
|
354
|
+
incompatibleColumns,
|
|
355
|
+
missingDefaults,
|
|
356
|
+
sequenceReady,
|
|
357
|
+
};
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
function quoteIdentifier(identifier: string): string {
|
|
361
|
+
return `"${identifier.replace(/"/g, '""')}"`;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
function quoteLiteral(value: string): string {
|
|
365
|
+
return `'${value.replace(/'/g, "''")}'`;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
function relation(schema: string, table: string): string {
|
|
369
|
+
return `${quoteIdentifier(schema)}.${quoteIdentifier(table)}`;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
function versionDefaultSql(schema: string): string {
|
|
373
|
+
return `nextval(${quoteLiteral(`${schema}.${RUNTIME_SHEET_VERSION_SEQUENCE}`)}::regclass)`;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
function columnDefaultSql(
|
|
377
|
+
column: RuntimeSheetColumnContract,
|
|
378
|
+
schema: string,
|
|
379
|
+
): string | null {
|
|
380
|
+
if (column.defaultKind === 'version_sequence') {
|
|
381
|
+
return versionDefaultSql(schema);
|
|
382
|
+
}
|
|
383
|
+
return column.defaultSql;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
function readColumnName(error: unknown): string | null {
|
|
387
|
+
if (!error || typeof error !== 'object') return null;
|
|
388
|
+
const record = error as Record<string, unknown>;
|
|
389
|
+
if (typeof record.column === 'string') return record.column;
|
|
390
|
+
if (typeof record.message !== 'string') return null;
|
|
391
|
+
return /column ['"]([^'"]+)['"]/i.exec(record.message)?.[1] ?? null;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
export function createRuntimeSheetOrm(input: {
|
|
395
|
+
schema: string;
|
|
396
|
+
table: string;
|
|
397
|
+
query: RuntimeSheetOrmQuery;
|
|
398
|
+
}): RuntimeSheetOrm {
|
|
399
|
+
const tableReference = relation(input.schema, input.table);
|
|
400
|
+
const versionSequenceReference = `${input.schema}.${RUNTIME_SHEET_VERSION_SEQUENCE}`;
|
|
401
|
+
|
|
402
|
+
async function inspect(): Promise<RuntimeSheetSchemaSnapshot> {
|
|
403
|
+
const [columns, sequence] = await Promise.all([
|
|
404
|
+
input.query<RuntimeSheetColumnState>(
|
|
405
|
+
`
|
|
406
|
+
SELECT column_name, data_type, is_nullable, column_default
|
|
407
|
+
FROM information_schema.columns
|
|
408
|
+
WHERE table_schema = $1
|
|
409
|
+
AND table_name = $2
|
|
410
|
+
AND column_name = ANY($3::text[])
|
|
411
|
+
`,
|
|
412
|
+
[input.schema, input.table, [...RUNTIME_SHEET_SYSTEM_COLUMNS]],
|
|
413
|
+
),
|
|
414
|
+
input.query<{ exists: boolean }>(
|
|
415
|
+
'SELECT to_regclass($1) IS NOT NULL AS exists',
|
|
416
|
+
[versionSequenceReference],
|
|
417
|
+
),
|
|
418
|
+
]);
|
|
419
|
+
return {
|
|
420
|
+
sequenceExists: sequence.rows[0]?.exists === true,
|
|
421
|
+
columns: new Map(columns.rows.map((row) => [row.column_name, row])),
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
async function readiness(
|
|
426
|
+
snapshot?: RuntimeSheetSchemaSnapshot,
|
|
427
|
+
): Promise<RuntimeSheetSchemaReadiness> {
|
|
428
|
+
return evaluateRuntimeSheetSchema(snapshot ?? (await inspect()));
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
async function repairOwnerMetadata(): Promise<void> {
|
|
432
|
+
await input.query(`
|
|
433
|
+
ALTER TABLE ${tableReference}
|
|
434
|
+
${RUNTIME_SHEET_REPAIRABLE_COLUMNS.map(
|
|
435
|
+
(column) =>
|
|
436
|
+
`ADD COLUMN IF NOT EXISTS ${quoteIdentifier(column.name)} ${column.dataType}`,
|
|
437
|
+
).join(',\n ')}
|
|
438
|
+
`);
|
|
439
|
+
|
|
440
|
+
const defaultedColumns = RUNTIME_SHEET_REPAIRABLE_COLUMNS.filter(
|
|
441
|
+
(column) => column.requiresDefault,
|
|
442
|
+
);
|
|
443
|
+
await input.query(`
|
|
444
|
+
ALTER TABLE ${tableReference}
|
|
445
|
+
${defaultedColumns
|
|
446
|
+
.map(
|
|
447
|
+
(column) =>
|
|
448
|
+
`ALTER COLUMN ${quoteIdentifier(column.name)} SET DEFAULT ${columnDefaultSql(column, input.schema)}`,
|
|
449
|
+
)
|
|
450
|
+
.join(',\n ')}
|
|
451
|
+
`);
|
|
452
|
+
|
|
453
|
+
for (const column of defaultedColumns) {
|
|
454
|
+
const defaultSql = columnDefaultSql(column, input.schema);
|
|
455
|
+
if (defaultSql === null) continue;
|
|
456
|
+
await input.query(`
|
|
457
|
+
UPDATE ${tableReference}
|
|
458
|
+
SET ${quoteIdentifier(column.name)} = ${defaultSql}
|
|
459
|
+
WHERE ${quoteIdentifier(column.name)} IS NULL
|
|
460
|
+
`);
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
const nonNullableColumns = RUNTIME_SHEET_REPAIRABLE_COLUMNS.filter(
|
|
464
|
+
(column) => column.nullable === 'NO',
|
|
465
|
+
);
|
|
466
|
+
await input.query(`
|
|
467
|
+
ALTER TABLE ${tableReference}
|
|
468
|
+
${nonNullableColumns
|
|
469
|
+
.map(
|
|
470
|
+
(column) =>
|
|
471
|
+
`ALTER COLUMN ${quoteIdentifier(column.name)} SET NOT NULL`,
|
|
472
|
+
)
|
|
473
|
+
.join(',\n ')}
|
|
474
|
+
`);
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
function isOwnerMetadataConstraintError(error: unknown): boolean {
|
|
478
|
+
return isRuntimeSheetOwnerMetadataConstraintError(error, {
|
|
479
|
+
table: input.table,
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
return {
|
|
484
|
+
inspect,
|
|
485
|
+
readiness,
|
|
486
|
+
repairOwnerMetadata,
|
|
487
|
+
isOwnerMetadataConstraintError,
|
|
488
|
+
};
|
|
489
|
+
}
|
|
@@ -1,16 +1,7 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
* database default. Keep the type, nullability, and default in one Module so
|
|
6
|
-
* table creation, readiness probes, migrations, and diagnostics cannot drift.
|
|
7
|
-
*/
|
|
8
|
-
export const RUNTIME_SHEET_CELL_META_COLUMN = {
|
|
9
|
-
name: '_cell_meta',
|
|
10
|
-
dataType: 'jsonb',
|
|
11
|
-
nullable: 'NO',
|
|
12
|
-
defaultSql: "'{}'::jsonb",
|
|
13
|
-
} as const;
|
|
1
|
+
/** Compatibility seam for callers that used the cell-meta-only contract. */
|
|
2
|
+
import { RUNTIME_SHEET_CELL_META_COLUMN } from './runtime-sheet-orm';
|
|
3
|
+
|
|
4
|
+
export { RUNTIME_SHEET_CELL_META_COLUMN } from './runtime-sheet-orm';
|
|
14
5
|
|
|
15
6
|
export type RuntimeSheetCellMetaColumnState = {
|
|
16
7
|
data_type: string;
|
|
@@ -25,6 +25,13 @@ import {
|
|
|
25
25
|
type PhysicalSheetColumnProjection,
|
|
26
26
|
} from '../play-data-plane/sheet-contract';
|
|
27
27
|
import { RUNTIME_SHEET_CELL_META_COLUMN } from '../play-data-plane/runtime-sheet-storage-contract';
|
|
28
|
+
import {
|
|
29
|
+
createRuntimeSheetOrm,
|
|
30
|
+
isRuntimeSheetOwnerMetadataConstraintError,
|
|
31
|
+
RUNTIME_SHEET_ATTEMPT_COLUMNS,
|
|
32
|
+
RUNTIME_SHEET_TIMESTAMP_COLUMNS,
|
|
33
|
+
RUNTIME_SHEET_VERSION_SEQUENCE,
|
|
34
|
+
} from '../play-data-plane/runtime-sheet-orm';
|
|
28
35
|
import type {
|
|
29
36
|
CreateDbSessionResponse,
|
|
30
37
|
DbLogicalTable,
|
|
@@ -316,13 +323,6 @@ const APPEND_KEY_SUFFIX_LENGTH = 12;
|
|
|
316
323
|
// 60-min alignment fixed. A shorter TTL only causes periodic re-mints (cheap;
|
|
317
324
|
// the tenant runtime role is long-lived), not run failures.
|
|
318
325
|
const RUNTIME_DB_SESSION_TTL_SECONDS = 10 * 60;
|
|
319
|
-
const RUNTIME_SHEET_ATTEMPT_COLUMNS = [
|
|
320
|
-
'_attempt_id',
|
|
321
|
-
'_attempt_owner_run_id',
|
|
322
|
-
'_attempt_seq',
|
|
323
|
-
'_attempt_expires_at',
|
|
324
|
-
] as const;
|
|
325
|
-
const RUNTIME_SHEET_TIMESTAMP_COLUMNS = ['_created_at', '_updated_at'] as const;
|
|
326
326
|
const RUNTIME_SHEET_ENSURE_CACHE_TTL_MS = 10 * 60_000;
|
|
327
327
|
const RUNTIME_SHEET_READY_AFTER_ENSURE_RETRY_DELAYS_MS = [
|
|
328
328
|
100, 250, 500, 1_000, 2_000,
|
|
@@ -519,6 +519,7 @@ type RuntimeApiActionRequest =
|
|
|
519
519
|
tableNamespace: string;
|
|
520
520
|
sheetContract?: PlaySheetContract | null;
|
|
521
521
|
userEmail?: string | null;
|
|
522
|
+
forceRepair?: boolean;
|
|
522
523
|
}
|
|
523
524
|
| {
|
|
524
525
|
action: 'create_db_session';
|
|
@@ -1135,62 +1136,21 @@ async function isRuntimeSheetSchemaReady(
|
|
|
1135
1136
|
FROM ${sheetTable(session)}
|
|
1136
1137
|
LIMIT 0`,
|
|
1137
1138
|
);
|
|
1138
|
-
const
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
[
|
|
1150
|
-
|
|
1151
|
-
);
|
|
1152
|
-
|
|
1153
|
-
`
|
|
1154
|
-
SELECT count(*)::int AS ready_count
|
|
1155
|
-
FROM information_schema.columns
|
|
1156
|
-
WHERE table_schema = $1
|
|
1157
|
-
AND table_name = $2
|
|
1158
|
-
AND column_name = ANY($3::text[])
|
|
1159
|
-
AND data_type = 'timestamp with time zone'
|
|
1160
|
-
AND is_nullable = 'NO'
|
|
1161
|
-
AND column_default IS NOT NULL
|
|
1162
|
-
`,
|
|
1163
|
-
[
|
|
1164
|
-
session.postgres.schema,
|
|
1165
|
-
session.postgres.sheetTable,
|
|
1166
|
-
[...RUNTIME_SHEET_TIMESTAMP_COLUMNS],
|
|
1167
|
-
],
|
|
1168
|
-
);
|
|
1169
|
-
const cellMetaColumn = await client.query<Record<string, unknown>>(
|
|
1170
|
-
`
|
|
1171
|
-
SELECT count(*)::int AS ready_count
|
|
1172
|
-
FROM information_schema.columns
|
|
1173
|
-
WHERE table_schema = $1
|
|
1174
|
-
AND table_name = $2
|
|
1175
|
-
AND column_name = $3
|
|
1176
|
-
AND data_type = $4
|
|
1177
|
-
AND is_nullable = 'NO'
|
|
1178
|
-
AND column_default IS NOT NULL
|
|
1179
|
-
`,
|
|
1180
|
-
[
|
|
1181
|
-
session.postgres.schema,
|
|
1182
|
-
session.postgres.sheetTable,
|
|
1183
|
-
RUNTIME_SHEET_CELL_META_COLUMN.name,
|
|
1184
|
-
RUNTIME_SHEET_CELL_META_COLUMN.dataType,
|
|
1185
|
-
],
|
|
1186
|
-
);
|
|
1187
|
-
return (
|
|
1188
|
-
Number(attemptColumns.rows[0]?.present_count ?? 0) ===
|
|
1189
|
-
RUNTIME_SHEET_ATTEMPT_COLUMNS.length &&
|
|
1190
|
-
Number(timestampColumns.rows[0]?.ready_count ?? 0) ===
|
|
1191
|
-
RUNTIME_SHEET_TIMESTAMP_COLUMNS.length &&
|
|
1192
|
-
Number(cellMetaColumn.rows[0]?.ready_count ?? 0) === 1
|
|
1193
|
-
);
|
|
1139
|
+
const orm = createRuntimeSheetOrm({
|
|
1140
|
+
schema: session.postgres.schema,
|
|
1141
|
+
table: session.postgres.sheetTable,
|
|
1142
|
+
query: async <Row = Record<string, unknown>>(
|
|
1143
|
+
sql: string,
|
|
1144
|
+
params?: readonly unknown[],
|
|
1145
|
+
): Promise<{ rows: Row[] }> => {
|
|
1146
|
+
const result = await client.query<Row & Record<string, unknown>>(
|
|
1147
|
+
sql,
|
|
1148
|
+
params === undefined ? undefined : [...params],
|
|
1149
|
+
);
|
|
1150
|
+
return { rows: result.rows as Row[] };
|
|
1151
|
+
},
|
|
1152
|
+
});
|
|
1153
|
+
return (await orm.readiness()).ready;
|
|
1194
1154
|
};
|
|
1195
1155
|
try {
|
|
1196
1156
|
if (isRuntimeOneShotQueryFactoryRegistered()) {
|
|
@@ -1250,15 +1210,31 @@ async function readRuntimeSheetSchemaDiagnostic(
|
|
|
1250
1210
|
`${quoteIdentifier(session.postgres.schema)}.${quoteIdentifier(session.postgres.sheetTable)}`,
|
|
1251
1211
|
],
|
|
1252
1212
|
);
|
|
1213
|
+
const orm = createRuntimeSheetOrm({
|
|
1214
|
+
schema: session.postgres.schema,
|
|
1215
|
+
table: session.postgres.sheetTable,
|
|
1216
|
+
query: async <Row = Record<string, unknown>>(
|
|
1217
|
+
sql: string,
|
|
1218
|
+
params?: readonly unknown[],
|
|
1219
|
+
): Promise<{ rows: Row[] }> => {
|
|
1220
|
+
const result = await client.query<Row & Record<string, unknown>>(
|
|
1221
|
+
sql,
|
|
1222
|
+
params === undefined ? undefined : [...params],
|
|
1223
|
+
);
|
|
1224
|
+
return { rows: result.rows as Row[] };
|
|
1225
|
+
},
|
|
1226
|
+
});
|
|
1227
|
+
const ownerSchema = await orm.inspect();
|
|
1228
|
+
const ownerReadiness = await orm.readiness(ownerSchema);
|
|
1253
1229
|
const visible = new Set(visibleColumns.rows.map((row) => row.column_name));
|
|
1254
1230
|
const timestampColumns = new Map(
|
|
1255
|
-
|
|
1256
|
-
.
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1231
|
+
[...ownerSchema.columns.entries()].filter(([column]) =>
|
|
1232
|
+
RUNTIME_SHEET_TIMESTAMP_COLUMNS.includes(column),
|
|
1233
|
+
),
|
|
1234
|
+
);
|
|
1235
|
+
const versionColumn = ownerSchema.columns.get('_version');
|
|
1236
|
+
const cellMetaColumn = ownerSchema.columns.get(
|
|
1237
|
+
RUNTIME_SHEET_CELL_META_COLUMN.name,
|
|
1262
1238
|
);
|
|
1263
1239
|
return {
|
|
1264
1240
|
schema: session.postgres.schema,
|
|
@@ -1268,6 +1244,16 @@ async function readRuntimeSheetSchemaDiagnostic(
|
|
|
1268
1244
|
canSelect: privileges.rows[0]?.can_select ?? null,
|
|
1269
1245
|
canInsert: privileges.rows[0]?.can_insert ?? null,
|
|
1270
1246
|
canUpdate: privileges.rows[0]?.can_update ?? null,
|
|
1247
|
+
ownerSchemaReady: ownerReadiness.ready,
|
|
1248
|
+
ownerSchemaMissingColumns: ownerReadiness.missingColumns,
|
|
1249
|
+
ownerSchemaIncompatibleColumns: ownerReadiness.incompatibleColumns,
|
|
1250
|
+
ownerSchemaMissingDefaults: ownerReadiness.missingDefaults,
|
|
1251
|
+
versionSequenceExists: ownerSchema.sequenceExists,
|
|
1252
|
+
versionColumnState: {
|
|
1253
|
+
dataType: versionColumn?.data_type ?? null,
|
|
1254
|
+
isNullable: versionColumn?.is_nullable ?? null,
|
|
1255
|
+
hasDefault: versionColumn?.column_default != null,
|
|
1256
|
+
},
|
|
1271
1257
|
visibleColumnCount: visible.size,
|
|
1272
1258
|
missingAttemptColumns: RUNTIME_SHEET_ATTEMPT_COLUMNS.filter(
|
|
1273
1259
|
(column) => !visible.has(column),
|
|
@@ -1282,14 +1268,10 @@ async function readRuntimeSheetSchemaDiagnostic(
|
|
|
1282
1268
|
};
|
|
1283
1269
|
}),
|
|
1284
1270
|
cellMetaColumnState: (() => {
|
|
1285
|
-
const state = visibleColumns.rows.find(
|
|
1286
|
-
(column) =>
|
|
1287
|
-
column.column_name === RUNTIME_SHEET_CELL_META_COLUMN.name,
|
|
1288
|
-
);
|
|
1289
1271
|
return {
|
|
1290
|
-
dataType:
|
|
1291
|
-
isNullable:
|
|
1292
|
-
hasDefault:
|
|
1272
|
+
dataType: cellMetaColumn?.data_type ?? null,
|
|
1273
|
+
isNullable: cellMetaColumn?.is_nullable ?? null,
|
|
1274
|
+
hasDefault: cellMetaColumn?.column_default != null,
|
|
1293
1275
|
};
|
|
1294
1276
|
})(),
|
|
1295
1277
|
};
|
|
@@ -2483,6 +2465,7 @@ async function withRuntimeSheetProvisioningRetry<T>(
|
|
|
2483
2465
|
playName: string;
|
|
2484
2466
|
tableNamespace: string;
|
|
2485
2467
|
sheetContract: PlaySheetContract;
|
|
2468
|
+
session: RuntimePostgresSession;
|
|
2486
2469
|
timings?: RuntimeSheetTiming[];
|
|
2487
2470
|
},
|
|
2488
2471
|
operation: () => Promise<T>,
|
|
@@ -2505,12 +2488,33 @@ async function withRuntimeSheetProvisioningRetry<T>(
|
|
|
2505
2488
|
});
|
|
2506
2489
|
if (isMissingRelationError(error)) {
|
|
2507
2490
|
const ensureStartedAt = Date.now();
|
|
2508
|
-
await ensureRuntimeSheet(context,
|
|
2491
|
+
await ensureRuntimeSheet(context, {
|
|
2492
|
+
playName: input.playName,
|
|
2493
|
+
tableNamespace: input.tableNamespace,
|
|
2494
|
+
sheetContract: input.sheetContract,
|
|
2495
|
+
});
|
|
2509
2496
|
input.timings?.push({
|
|
2510
2497
|
phase: 'ensure_sheet_after_provisioning_error',
|
|
2511
2498
|
ms: Date.now() - ensureStartedAt,
|
|
2512
2499
|
retried: true,
|
|
2513
2500
|
});
|
|
2501
|
+
} else if (
|
|
2502
|
+
isRuntimeSheetOwnerMetadataConstraintError(error, {
|
|
2503
|
+
table: input.session.postgres.sheetTable,
|
|
2504
|
+
})
|
|
2505
|
+
) {
|
|
2506
|
+
const ensureStartedAt = Date.now();
|
|
2507
|
+
await ensureRuntimeSheet(context, {
|
|
2508
|
+
playName: input.playName,
|
|
2509
|
+
tableNamespace: input.tableNamespace,
|
|
2510
|
+
sheetContract: input.sheetContract,
|
|
2511
|
+
forceRepair: true,
|
|
2512
|
+
});
|
|
2513
|
+
input.timings?.push({
|
|
2514
|
+
phase: 'force_repair_sheet_after_metadata_constraint_error',
|
|
2515
|
+
ms: Date.now() - ensureStartedAt,
|
|
2516
|
+
retried: true,
|
|
2517
|
+
});
|
|
2514
2518
|
} else if (isPostgresPermissionDeniedError(error)) {
|
|
2515
2519
|
const repairStartedAt = Date.now();
|
|
2516
2520
|
await repairRuntimeStorageGrants(context, {
|
|
@@ -2551,7 +2555,7 @@ async function withRuntimeSheetQueryClient<T>(
|
|
|
2551
2555
|
const totalStartedAt = Date.now();
|
|
2552
2556
|
const result = await withRuntimeSheetProvisioningRetry(
|
|
2553
2557
|
context,
|
|
2554
|
-
input,
|
|
2558
|
+
{ ...input, session },
|
|
2555
2559
|
async () => {
|
|
2556
2560
|
if (
|
|
2557
2561
|
!input.transactional &&
|
|
@@ -2865,12 +2869,10 @@ async function withRuntimeWorkReceiptClient<T>(
|
|
|
2865
2869
|
throw new Error('Runtime work receipt query failed after retries.');
|
|
2866
2870
|
}
|
|
2867
2871
|
|
|
2868
|
-
const PLAY_INTERNAL_SHEET_VERSION_SEQUENCE = '_deepline_sheet_version_seq';
|
|
2869
|
-
|
|
2870
2872
|
function nextRuntimeSheetVersionExpression(
|
|
2871
2873
|
session: RuntimePostgresSession,
|
|
2872
2874
|
): string {
|
|
2873
|
-
return `nextval(${quoteLiteral(`${session.postgres.schema}.${
|
|
2875
|
+
return `nextval(${quoteLiteral(`${session.postgres.schema}.${RUNTIME_SHEET_VERSION_SEQUENCE}`)}::regclass)`;
|
|
2874
2876
|
}
|
|
2875
2877
|
|
|
2876
2878
|
function missingOutputCellSql(
|
|
@@ -3476,6 +3478,23 @@ async function writeRuntimeRows(
|
|
|
3476
3478
|
});
|
|
3477
3479
|
}
|
|
3478
3480
|
|
|
3481
|
+
async function writeRuntimeRowsWithProvisioningRetry(
|
|
3482
|
+
context: RuntimeApiContext,
|
|
3483
|
+
session: RuntimePostgresSession,
|
|
3484
|
+
input: Parameters<typeof writeRuntimeRows>[1],
|
|
3485
|
+
): Promise<RowsWriteResponse> {
|
|
3486
|
+
return await withRuntimeSheetProvisioningRetry(
|
|
3487
|
+
context,
|
|
3488
|
+
{
|
|
3489
|
+
playName: session.playName,
|
|
3490
|
+
tableNamespace: input.tableNamespace,
|
|
3491
|
+
sheetContract: input.sheetContract,
|
|
3492
|
+
session,
|
|
3493
|
+
},
|
|
3494
|
+
() => writeRuntimeRows(session, input),
|
|
3495
|
+
);
|
|
3496
|
+
}
|
|
3497
|
+
|
|
3479
3498
|
export async function resolveRuntimeReferencedPlay(
|
|
3480
3499
|
context: RuntimeApiContext,
|
|
3481
3500
|
playRef: string,
|
|
@@ -3509,6 +3528,7 @@ export async function ensureRuntimeSheet(
|
|
|
3509
3528
|
playName: string;
|
|
3510
3529
|
tableNamespace: string;
|
|
3511
3530
|
sheetContract: PlaySheetContract;
|
|
3531
|
+
forceRepair?: boolean;
|
|
3512
3532
|
},
|
|
3513
3533
|
): Promise<void> {
|
|
3514
3534
|
const request = {
|
|
@@ -3516,6 +3536,7 @@ export async function ensureRuntimeSheet(
|
|
|
3516
3536
|
...input,
|
|
3517
3537
|
runId: context.runId ?? null,
|
|
3518
3538
|
userEmail: normalizeRuntimeUserEmail(context.userEmail),
|
|
3539
|
+
...(input.forceRepair === true ? { forceRepair: true } : {}),
|
|
3519
3540
|
};
|
|
3520
3541
|
try {
|
|
3521
3542
|
await postRuntimeApi<{ ok: true }>(context, request);
|
|
@@ -9124,18 +9145,22 @@ export async function upsertRuntimeRows(
|
|
|
9124
9145
|
},
|
|
9125
9146
|
);
|
|
9126
9147
|
return rowsWriteResponseSchema.parse(
|
|
9127
|
-
await
|
|
9128
|
-
|
|
9129
|
-
|
|
9130
|
-
|
|
9131
|
-
|
|
9132
|
-
|
|
9133
|
-
.
|
|
9134
|
-
|
|
9135
|
-
)
|
|
9136
|
-
|
|
9137
|
-
|
|
9138
|
-
|
|
9148
|
+
await writeRuntimeRowsWithProvisioningRetry(
|
|
9149
|
+
context,
|
|
9150
|
+
requireRuntimePostgresSession(session),
|
|
9151
|
+
{
|
|
9152
|
+
tableNamespace: input.tableNamespace,
|
|
9153
|
+
rows: input.rows,
|
|
9154
|
+
runId: input.runId,
|
|
9155
|
+
sheetContract: input.sheetContract,
|
|
9156
|
+
idempotencyKey: createHash('sha1')
|
|
9157
|
+
.update(
|
|
9158
|
+
`${input.playName}:${input.tableNamespace}:${input.runId}:${JSON.stringify(input.rows)}`,
|
|
9159
|
+
)
|
|
9160
|
+
.digest('hex'),
|
|
9161
|
+
mode: 'upsert',
|
|
9162
|
+
},
|
|
9163
|
+
),
|
|
9139
9164
|
);
|
|
9140
9165
|
}
|
|
9141
9166
|
|
|
@@ -9170,14 +9195,18 @@ export async function appendRuntimeRows(
|
|
|
9170
9195
|
},
|
|
9171
9196
|
);
|
|
9172
9197
|
return rowsWriteResponseSchema.parse(
|
|
9173
|
-
await
|
|
9174
|
-
|
|
9175
|
-
|
|
9176
|
-
|
|
9177
|
-
|
|
9178
|
-
|
|
9179
|
-
|
|
9180
|
-
|
|
9198
|
+
await writeRuntimeRowsWithProvisioningRetry(
|
|
9199
|
+
context,
|
|
9200
|
+
requireRuntimePostgresSession(session),
|
|
9201
|
+
{
|
|
9202
|
+
tableNamespace: input.tableNamespace,
|
|
9203
|
+
rows: input.rows,
|
|
9204
|
+
runId: input.runId,
|
|
9205
|
+
sheetContract: input.sheetContract,
|
|
9206
|
+
idempotencyKey: input.idempotencyKey,
|
|
9207
|
+
mode: 'append',
|
|
9208
|
+
},
|
|
9209
|
+
),
|
|
9181
9210
|
);
|
|
9182
9211
|
}
|
|
9183
9212
|
|
|
@@ -9212,14 +9241,18 @@ export async function replaceRuntimeRows(
|
|
|
9212
9241
|
},
|
|
9213
9242
|
);
|
|
9214
9243
|
return rowsWriteResponseSchema.parse(
|
|
9215
|
-
await
|
|
9216
|
-
|
|
9217
|
-
|
|
9218
|
-
|
|
9219
|
-
|
|
9220
|
-
|
|
9221
|
-
|
|
9222
|
-
|
|
9244
|
+
await writeRuntimeRowsWithProvisioningRetry(
|
|
9245
|
+
context,
|
|
9246
|
+
requireRuntimePostgresSession(session),
|
|
9247
|
+
{
|
|
9248
|
+
tableNamespace: input.tableNamespace,
|
|
9249
|
+
rows: input.rows,
|
|
9250
|
+
runId: input.runId,
|
|
9251
|
+
sheetContract: input.sheetContract,
|
|
9252
|
+
idempotencyKey: input.idempotencyKey,
|
|
9253
|
+
mode: 'replace',
|
|
9254
|
+
},
|
|
9255
|
+
),
|
|
9223
9256
|
);
|
|
9224
9257
|
}
|
|
9225
9258
|
|
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.175",
|
|
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
|
|
@@ -6425,6 +6425,16 @@ function resolveTheirstackClientTimeoutMs(endpointId, payload) {
|
|
|
6425
6425
|
return usesExtendedTheirstackJobSearchBudget(endpointId, payload) ? THEIRSTACK_SLOW_JOB_SEARCH_CLIENT_TIMEOUT_MS : null;
|
|
6426
6426
|
}
|
|
6427
6427
|
|
|
6428
|
+
// ../integration-contracts/waterfall/execution-policy.ts
|
|
6429
|
+
var WATERFALL_PROSPECTOR_CLIENT_TIMEOUT_MS = 18e4;
|
|
6430
|
+
var WATERFALL_PROSPECTOR_LAUNCHER_TOOL_IDS = /* @__PURE__ */ new Set([
|
|
6431
|
+
"prospector",
|
|
6432
|
+
"deepline_native_prospector"
|
|
6433
|
+
]);
|
|
6434
|
+
function resolveWaterfallClientTimeoutMs(toolId) {
|
|
6435
|
+
return WATERFALL_PROSPECTOR_LAUNCHER_TOOL_IDS.has(toolId.trim().toLowerCase()) ? WATERFALL_PROSPECTOR_CLIENT_TIMEOUT_MS : null;
|
|
6436
|
+
}
|
|
6437
|
+
|
|
6428
6438
|
// ../integration-contracts/bettercontact/execution-policy.ts
|
|
6429
6439
|
var BETTERCONTACT_LAUNCHER_CLIENT_TIMEOUT_MS = 12e4;
|
|
6430
6440
|
var BETTERCONTACT_LAUNCHER_TOOL_IDS = /* @__PURE__ */ new Set([
|
|
@@ -6835,6 +6845,8 @@ function resolveToolExecuteTimeoutMs(toolId, input2) {
|
|
|
6835
6845
|
input2
|
|
6836
6846
|
);
|
|
6837
6847
|
if (theirstackTimeoutMs !== null) return theirstackTimeoutMs;
|
|
6848
|
+
const waterfallTimeoutMs = resolveWaterfallClientTimeoutMs(normalized);
|
|
6849
|
+
if (waterfallTimeoutMs !== null) return waterfallTimeoutMs;
|
|
6838
6850
|
if (usesExtendedBetterContactLauncherBudget(normalized)) {
|
|
6839
6851
|
return BETTERCONTACT_LAUNCHER_CLIENT_TIMEOUT_MS;
|
|
6840
6852
|
}
|
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.175",
|
|
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
|
|
@@ -6420,6 +6420,16 @@ function resolveTheirstackClientTimeoutMs(endpointId, payload) {
|
|
|
6420
6420
|
return usesExtendedTheirstackJobSearchBudget(endpointId, payload) ? THEIRSTACK_SLOW_JOB_SEARCH_CLIENT_TIMEOUT_MS : null;
|
|
6421
6421
|
}
|
|
6422
6422
|
|
|
6423
|
+
// ../integration-contracts/waterfall/execution-policy.ts
|
|
6424
|
+
var WATERFALL_PROSPECTOR_CLIENT_TIMEOUT_MS = 18e4;
|
|
6425
|
+
var WATERFALL_PROSPECTOR_LAUNCHER_TOOL_IDS = /* @__PURE__ */ new Set([
|
|
6426
|
+
"prospector",
|
|
6427
|
+
"deepline_native_prospector"
|
|
6428
|
+
]);
|
|
6429
|
+
function resolveWaterfallClientTimeoutMs(toolId) {
|
|
6430
|
+
return WATERFALL_PROSPECTOR_LAUNCHER_TOOL_IDS.has(toolId.trim().toLowerCase()) ? WATERFALL_PROSPECTOR_CLIENT_TIMEOUT_MS : null;
|
|
6431
|
+
}
|
|
6432
|
+
|
|
6423
6433
|
// ../integration-contracts/bettercontact/execution-policy.ts
|
|
6424
6434
|
var BETTERCONTACT_LAUNCHER_CLIENT_TIMEOUT_MS = 12e4;
|
|
6425
6435
|
var BETTERCONTACT_LAUNCHER_TOOL_IDS = /* @__PURE__ */ new Set([
|
|
@@ -6830,6 +6840,8 @@ function resolveToolExecuteTimeoutMs(toolId, input2) {
|
|
|
6830
6840
|
input2
|
|
6831
6841
|
);
|
|
6832
6842
|
if (theirstackTimeoutMs !== null) return theirstackTimeoutMs;
|
|
6843
|
+
const waterfallTimeoutMs = resolveWaterfallClientTimeoutMs(normalized);
|
|
6844
|
+
if (waterfallTimeoutMs !== null) return waterfallTimeoutMs;
|
|
6833
6845
|
if (usesExtendedBetterContactLauncherBudget(normalized)) {
|
|
6834
6846
|
return BETTERCONTACT_LAUNCHER_CLIENT_TIMEOUT_MS;
|
|
6835
6847
|
}
|
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.175",
|
|
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
|
|
@@ -4095,6 +4095,16 @@ function resolveTheirstackClientTimeoutMs(endpointId, payload) {
|
|
|
4095
4095
|
return usesExtendedTheirstackJobSearchBudget(endpointId, payload) ? THEIRSTACK_SLOW_JOB_SEARCH_CLIENT_TIMEOUT_MS : null;
|
|
4096
4096
|
}
|
|
4097
4097
|
|
|
4098
|
+
// ../integration-contracts/waterfall/execution-policy.ts
|
|
4099
|
+
var WATERFALL_PROSPECTOR_CLIENT_TIMEOUT_MS = 18e4;
|
|
4100
|
+
var WATERFALL_PROSPECTOR_LAUNCHER_TOOL_IDS = /* @__PURE__ */ new Set([
|
|
4101
|
+
"prospector",
|
|
4102
|
+
"deepline_native_prospector"
|
|
4103
|
+
]);
|
|
4104
|
+
function resolveWaterfallClientTimeoutMs(toolId) {
|
|
4105
|
+
return WATERFALL_PROSPECTOR_LAUNCHER_TOOL_IDS.has(toolId.trim().toLowerCase()) ? WATERFALL_PROSPECTOR_CLIENT_TIMEOUT_MS : null;
|
|
4106
|
+
}
|
|
4107
|
+
|
|
4098
4108
|
// ../integration-contracts/bettercontact/execution-policy.ts
|
|
4099
4109
|
var BETTERCONTACT_LAUNCHER_CLIENT_TIMEOUT_MS = 12e4;
|
|
4100
4110
|
var BETTERCONTACT_LAUNCHER_TOOL_IDS = /* @__PURE__ */ new Set([
|
|
@@ -4505,6 +4515,8 @@ function resolveToolExecuteTimeoutMs(toolId, input) {
|
|
|
4505
4515
|
input
|
|
4506
4516
|
);
|
|
4507
4517
|
if (theirstackTimeoutMs !== null) return theirstackTimeoutMs;
|
|
4518
|
+
const waterfallTimeoutMs = resolveWaterfallClientTimeoutMs(normalized);
|
|
4519
|
+
if (waterfallTimeoutMs !== null) return waterfallTimeoutMs;
|
|
4508
4520
|
if (usesExtendedBetterContactLauncherBudget(normalized)) {
|
|
4509
4521
|
return BETTERCONTACT_LAUNCHER_CLIENT_TIMEOUT_MS;
|
|
4510
4522
|
}
|
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.175",
|
|
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
|
|
@@ -3999,6 +3999,16 @@ function resolveTheirstackClientTimeoutMs(endpointId, payload) {
|
|
|
3999
3999
|
return usesExtendedTheirstackJobSearchBudget(endpointId, payload) ? THEIRSTACK_SLOW_JOB_SEARCH_CLIENT_TIMEOUT_MS : null;
|
|
4000
4000
|
}
|
|
4001
4001
|
|
|
4002
|
+
// ../integration-contracts/waterfall/execution-policy.ts
|
|
4003
|
+
var WATERFALL_PROSPECTOR_CLIENT_TIMEOUT_MS = 18e4;
|
|
4004
|
+
var WATERFALL_PROSPECTOR_LAUNCHER_TOOL_IDS = /* @__PURE__ */ new Set([
|
|
4005
|
+
"prospector",
|
|
4006
|
+
"deepline_native_prospector"
|
|
4007
|
+
]);
|
|
4008
|
+
function resolveWaterfallClientTimeoutMs(toolId) {
|
|
4009
|
+
return WATERFALL_PROSPECTOR_LAUNCHER_TOOL_IDS.has(toolId.trim().toLowerCase()) ? WATERFALL_PROSPECTOR_CLIENT_TIMEOUT_MS : null;
|
|
4010
|
+
}
|
|
4011
|
+
|
|
4002
4012
|
// ../integration-contracts/bettercontact/execution-policy.ts
|
|
4003
4013
|
var BETTERCONTACT_LAUNCHER_CLIENT_TIMEOUT_MS = 12e4;
|
|
4004
4014
|
var BETTERCONTACT_LAUNCHER_TOOL_IDS = /* @__PURE__ */ new Set([
|
|
@@ -4409,6 +4419,8 @@ function resolveToolExecuteTimeoutMs(toolId, input) {
|
|
|
4409
4419
|
input
|
|
4410
4420
|
);
|
|
4411
4421
|
if (theirstackTimeoutMs !== null) return theirstackTimeoutMs;
|
|
4422
|
+
const waterfallTimeoutMs = resolveWaterfallClientTimeoutMs(normalized);
|
|
4423
|
+
if (waterfallTimeoutMs !== null) return waterfallTimeoutMs;
|
|
4412
4424
|
if (usesExtendedBetterContactLauncherBudget(normalized)) {
|
|
4413
4425
|
return BETTERCONTACT_LAUNCHER_CLIENT_TIMEOUT_MS;
|
|
4414
4426
|
}
|
|
@@ -32,6 +32,7 @@
|
|
|
32
32
|
"dist/bundling-sources/shared_libs/integration-contracts/monitor-input-contract.ts",
|
|
33
33
|
"dist/bundling-sources/shared_libs/integration-contracts/README.md",
|
|
34
34
|
"dist/bundling-sources/shared_libs/integration-contracts/theirstack/execution-policy.ts",
|
|
35
|
+
"dist/bundling-sources/shared_libs/integration-contracts/waterfall/execution-policy.ts",
|
|
35
36
|
"dist/bundling-sources/shared_libs/monitors/analytics-install-guides.ts",
|
|
36
37
|
"dist/bundling-sources/shared_libs/monitors/analytics-public.ts",
|
|
37
38
|
"dist/bundling-sources/shared_libs/monitors/billing/charges.ts",
|
|
@@ -114,6 +115,7 @@
|
|
|
114
115
|
"dist/bundling-sources/shared_libs/play-data-plane/index.ts",
|
|
115
116
|
"dist/bundling-sources/shared_libs/play-data-plane/neon-constants.ts",
|
|
116
117
|
"dist/bundling-sources/shared_libs/play-data-plane/r2.ts",
|
|
118
|
+
"dist/bundling-sources/shared_libs/play-data-plane/runtime-sheet-orm.ts",
|
|
117
119
|
"dist/bundling-sources/shared_libs/play-data-plane/runtime-sheet-storage-contract.ts",
|
|
118
120
|
"dist/bundling-sources/shared_libs/play-data-plane/sheet-contract.ts",
|
|
119
121
|
"dist/bundling-sources/shared_libs/play-runtime/activity-observation.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.175";
|
|
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.175";
|
|
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.175",
|
|
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.175",
|
|
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
|