deepline 0.3.187 → 0.3.188
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundling-sources/sdk/src/release.ts +1 -1
- package/dist/bundling-sources/shared_libs/play-runtime/runtime-api.ts +160 -54
- package/dist/bundling-sources/shared_libs/play-runtime/sheet-attempt-sql.ts +5 -5
- 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/release.d.mts +1 -1
- package/dist/release.d.ts +1 -1
- package/dist/release.js +1 -1
- package/dist/release.mjs +1 -1
- package/package.json +1 -1
|
@@ -200,7 +200,7 @@ export const SDK_RELEASE = {
|
|
|
200
200
|
// getters keep their established compatibility behavior.
|
|
201
201
|
// 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
|
|
202
202
|
// 0.3.90 is the first deliberately versioned SDK release for API v3.
|
|
203
|
-
version: '0.3.
|
|
203
|
+
version: '0.3.188',
|
|
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: {
|
|
@@ -88,6 +88,7 @@ import {
|
|
|
88
88
|
activeRuntimeSheetAttemptFenceSql,
|
|
89
89
|
newerTerminalRuntimeSheetRowSql,
|
|
90
90
|
releasableRuntimeSheetAttemptFenceSql,
|
|
91
|
+
sameOwnerTerminalAttemptEpochSql,
|
|
91
92
|
} from './sheet-attempt-sql';
|
|
92
93
|
import type { MapRowOutcome } from './durability-store';
|
|
93
94
|
import { RUNTIME_CAPACITY_POLICY } from './runtime-capacity-policy';
|
|
@@ -7119,6 +7120,7 @@ export type RuntimeMapRowsWriteResult = {
|
|
|
7119
7120
|
type RuntimeMapRowsMutationResult = {
|
|
7120
7121
|
updated: number;
|
|
7121
7122
|
fencedRows: RuntimeMapRowsStaleRow[];
|
|
7123
|
+
conflictKeys: string[];
|
|
7122
7124
|
};
|
|
7123
7125
|
|
|
7124
7126
|
const RUNTIME_MAP_ROWS_STALE_REASONS: ReadonlySet<RuntimeMapRowsStaleReason> =
|
|
@@ -7308,6 +7310,7 @@ async function completeRuntimeMapRowChunks(
|
|
|
7308
7310
|
): Promise<RuntimeMapRowsMutationResult> {
|
|
7309
7311
|
let updated = 0;
|
|
7310
7312
|
const fencedRows: RuntimeMapRowsStaleRow[] = [];
|
|
7313
|
+
const conflictKeys: string[] = [];
|
|
7311
7314
|
for (const chunk of input.chunks) {
|
|
7312
7315
|
const chunkKeys = chunk.map((row) => row.key);
|
|
7313
7316
|
const chunkInputIndexes = chunk.map((row) => row.input_index);
|
|
@@ -7335,6 +7338,7 @@ async function completeRuntimeMapRowChunks(
|
|
|
7335
7338
|
updated: number;
|
|
7336
7339
|
matched_keys: string[];
|
|
7337
7340
|
fenced_rows: unknown;
|
|
7341
|
+
conflict_keys: string[];
|
|
7338
7342
|
}>(
|
|
7339
7343
|
`WITH updates AS (
|
|
7340
7344
|
SELECT key_values._key,
|
|
@@ -7351,7 +7355,6 @@ async function completeRuntimeMapRowChunks(
|
|
|
7351
7355
|
),
|
|
7352
7356
|
matched_updates AS (
|
|
7353
7357
|
SELECT target._key AS matched_key,
|
|
7354
|
-
updates._key AS submitted_key,
|
|
7355
7358
|
target._status AS prev_status,
|
|
7356
7359
|
target._cell_meta AS prev_cell_meta,
|
|
7357
7360
|
updates.input_index,
|
|
@@ -7361,6 +7364,40 @@ async function completeRuntimeMapRowChunks(
|
|
|
7361
7364
|
JOIN ${sheetTable(session)} AS target
|
|
7362
7365
|
ON target._key = updates._key
|
|
7363
7366
|
),
|
|
7367
|
+
same_version_conflicts AS (
|
|
7368
|
+
SELECT updates.matched_key AS _key
|
|
7369
|
+
FROM matched_updates AS updates
|
|
7370
|
+
JOIN ${sheetTable(session)} AS target
|
|
7371
|
+
ON target._key = updates.matched_key
|
|
7372
|
+
WHERE $13::bigint IS NOT NULL
|
|
7373
|
+
AND target._write_version = $13::bigint
|
|
7374
|
+
AND target._run_id = $5::text
|
|
7375
|
+
AND target._status IN ('enriched', 'failed')
|
|
7376
|
+
AND (
|
|
7377
|
+
EXISTS (
|
|
7378
|
+
SELECT 1
|
|
7379
|
+
FROM unnest($8::text[]) AS field_values(field)
|
|
7380
|
+
WHERE target._cell_meta -> field_values.field ->> 'runId' = $5::text
|
|
7381
|
+
)
|
|
7382
|
+
OR (
|
|
7383
|
+
coalesce(target._attempt_owner_run_id, target._run_id) = $10::text
|
|
7384
|
+
AND COALESCE(target._attempt_seq, 0) = $12::integer
|
|
7385
|
+
)
|
|
7386
|
+
)
|
|
7387
|
+
AND (
|
|
7388
|
+
target._status <> 'enriched'
|
|
7389
|
+
OR (${targetChangedPatchedCellSql})
|
|
7390
|
+
)
|
|
7391
|
+
-- First terminal wins: suppress conflict for same owner+epoch already-terminal row.
|
|
7392
|
+
-- Durable replay (omitted_terminal_replay) from same attempt epoch is idempotent.
|
|
7393
|
+
AND NOT (
|
|
7394
|
+
$10::text IS NOT NULL
|
|
7395
|
+
AND $12::integer IS NOT NULL
|
|
7396
|
+
AND target._status = 'enriched'
|
|
7397
|
+
AND coalesce(target._attempt_owner_run_id, target._run_id) = $10::text
|
|
7398
|
+
AND COALESCE(target._attempt_seq, 0) = $12::integer
|
|
7399
|
+
)
|
|
7400
|
+
),
|
|
7364
7401
|
applied_rows AS (
|
|
7365
7402
|
UPDATE ${sheetTable(session)} AS target
|
|
7366
7403
|
SET _status = 'enriched',
|
|
@@ -7377,6 +7414,7 @@ async function completeRuntimeMapRowChunks(
|
|
|
7377
7414
|
_cell_meta = ${mergeRuntimeCellMetaPatchSql('target._cell_meta', 'updates.cell_meta_patch')}${input.physicalUpdateSetSql}
|
|
7378
7415
|
FROM matched_updates AS updates
|
|
7379
7416
|
WHERE target._key = updates.matched_key
|
|
7417
|
+
AND NOT EXISTS (SELECT 1 FROM same_version_conflicts)
|
|
7380
7418
|
AND ($13::bigint IS NULL OR target._write_version = $13::bigint)
|
|
7381
7419
|
AND ($13::bigint IS NOT NULL OR target._status <> 'enriched')
|
|
7382
7420
|
AND NOT (${newerTerminalRuntimeSheetRowSql('target', '$11::timestamptz', '$12::integer', '$9::text', '$10::text')})
|
|
@@ -7386,27 +7424,14 @@ async function completeRuntimeMapRowChunks(
|
|
|
7386
7424
|
OR ($9::text IS NOT NULL AND ${activeRuntimeSheetAttemptFenceSql('target', '$9::text', '$10::text', '$11::timestamptz', '$12::integer')})
|
|
7387
7425
|
OR ($9::text IS NOT NULL AND ${writableEnrichedAttemptSql})
|
|
7388
7426
|
)
|
|
7389
|
-
--
|
|
7390
|
-
--
|
|
7391
|
-
-- timestamp; preserve the first terminal value. Input-index repair
|
|
7392
|
-
-- remains writable when the submitted key itself changed.
|
|
7427
|
+
-- First terminal wins: skip UPDATE for already-terminal same-owner+epoch row.
|
|
7428
|
+
-- Even though we excluded from conflicts, we still no-op here for idempotency.
|
|
7393
7429
|
AND NOT (
|
|
7394
|
-
$
|
|
7395
|
-
AND
|
|
7396
|
-
AND target._run_id = $5::text
|
|
7430
|
+
$10::text IS NOT NULL
|
|
7431
|
+
AND $12::integer IS NOT NULL
|
|
7397
7432
|
AND target._status = 'enriched'
|
|
7398
|
-
AND
|
|
7399
|
-
AND (
|
|
7400
|
-
EXISTS (
|
|
7401
|
-
SELECT 1
|
|
7402
|
-
FROM unnest($8::text[]) AS field_values(field)
|
|
7403
|
-
WHERE target._cell_meta -> field_values.field ->> 'runId' = $5::text
|
|
7404
|
-
)
|
|
7405
|
-
OR (
|
|
7406
|
-
$10::text IS NOT NULL
|
|
7407
|
-
AND target._attempt_owner_run_id IS NOT DISTINCT FROM $10::text
|
|
7408
|
-
)
|
|
7409
|
-
)
|
|
7433
|
+
AND coalesce(target._attempt_owner_run_id, target._run_id) = $10::text
|
|
7434
|
+
AND COALESCE(target._attempt_seq, 0) = $12::integer
|
|
7410
7435
|
)
|
|
7411
7436
|
AND (
|
|
7412
7437
|
target._status <> 'enriched'
|
|
@@ -7539,6 +7564,7 @@ async function completeRuntimeMapRowChunks(
|
|
|
7539
7564
|
(SELECT count(*)::int FROM applied_rows) AS updated,
|
|
7540
7565
|
coalesce((SELECT array_agg(matched_key) FROM matched_updates), '{}'::text[]) AS matched_keys,
|
|
7541
7566
|
coalesce((SELECT jsonb_agg(jsonb_build_object('key', _key, 'reason', reason, 'rowVersionStamp', row_write_version)) FROM fenced_rows), '[]'::jsonb) AS fenced_rows,
|
|
7567
|
+
coalesce((SELECT array_agg(_key) FROM same_version_conflicts), '{}'::text[]) AS conflict_keys,
|
|
7542
7568
|
(SELECT count(*)::int FROM summary_delta) AS summary_delta_count,
|
|
7543
7569
|
(SELECT count(*)::int FROM column_delta) AS column_delta_count`,
|
|
7544
7570
|
[
|
|
@@ -7559,12 +7585,19 @@ async function completeRuntimeMapRowChunks(
|
|
|
7559
7585
|
);
|
|
7560
7586
|
const matchedKeys = new Set(rows[0]?.matched_keys ?? []);
|
|
7561
7587
|
const chunkFencedRows = parseRuntimeMapRowsFencedRows(rows[0]?.fenced_rows);
|
|
7588
|
+
const chunkConflictKeys = rows[0]?.conflict_keys ?? [];
|
|
7562
7589
|
// An exact-version replay that already produced the same terminal value is
|
|
7563
7590
|
// accepted idempotently even when SQL has no physical mutation to apply.
|
|
7564
7591
|
// Stale versions remain excluded through fenced_rows.
|
|
7565
7592
|
const appliedCount = Number(rows[0]?.updated ?? 0);
|
|
7566
7593
|
updated += appliedCount;
|
|
7567
7594
|
fencedRows.push(...chunkFencedRows);
|
|
7595
|
+
conflictKeys.push(...chunkConflictKeys);
|
|
7596
|
+
|
|
7597
|
+
if (chunkConflictKeys.length > 0) {
|
|
7598
|
+
continue;
|
|
7599
|
+
}
|
|
7600
|
+
|
|
7568
7601
|
if (matchedKeys.size === chunk.length) {
|
|
7569
7602
|
continue;
|
|
7570
7603
|
}
|
|
@@ -7582,8 +7615,9 @@ async function completeRuntimeMapRowChunks(
|
|
|
7582
7615
|
);
|
|
7583
7616
|
updated += repaired.updated;
|
|
7584
7617
|
fencedRows.push(...repaired.fencedRows);
|
|
7618
|
+
conflictKeys.push(...repaired.conflictKeys);
|
|
7585
7619
|
}
|
|
7586
|
-
return { updated, fencedRows };
|
|
7620
|
+
return { updated, fencedRows, conflictKeys };
|
|
7587
7621
|
}
|
|
7588
7622
|
|
|
7589
7623
|
async function completeRuntimeMapRowChunksWithInputIndexRepair(
|
|
@@ -7593,6 +7627,7 @@ async function completeRuntimeMapRowChunksWithInputIndexRepair(
|
|
|
7593
7627
|
): Promise<RuntimeMapRowsMutationResult> {
|
|
7594
7628
|
let updated = 0;
|
|
7595
7629
|
const fencedRows: RuntimeMapRowsStaleRow[] = [];
|
|
7630
|
+
const conflictKeys: string[] = [];
|
|
7596
7631
|
for (const chunk of input.chunks) {
|
|
7597
7632
|
const chunkKeys = chunk.map((row) => row.key);
|
|
7598
7633
|
const chunkInputIndexes = chunk.map((row) => row.input_index);
|
|
@@ -7612,6 +7647,7 @@ async function completeRuntimeMapRowChunksWithInputIndexRepair(
|
|
|
7612
7647
|
const { rows } = await client.query<{
|
|
7613
7648
|
_key?: string;
|
|
7614
7649
|
fenced_rows?: unknown;
|
|
7650
|
+
conflict_keys?: string[];
|
|
7615
7651
|
updated?: number;
|
|
7616
7652
|
}>(
|
|
7617
7653
|
`WITH updates AS (
|
|
@@ -7643,6 +7679,40 @@ async function completeRuntimeMapRowChunksWithInputIndexRepair(
|
|
|
7643
7679
|
)
|
|
7644
7680
|
ORDER BY target._key, (target._key = updates._key) DESC
|
|
7645
7681
|
),
|
|
7682
|
+
same_version_conflicts AS (
|
|
7683
|
+
SELECT updates.submitted_key AS _key
|
|
7684
|
+
FROM matched_updates AS updates
|
|
7685
|
+
JOIN ${sheetTable(session)} AS target
|
|
7686
|
+
ON target._key = updates.matched_key
|
|
7687
|
+
WHERE $13::bigint IS NOT NULL
|
|
7688
|
+
AND target._write_version = $13::bigint
|
|
7689
|
+
AND target._run_id = $5::text
|
|
7690
|
+
AND target._status IN ('enriched', 'failed')
|
|
7691
|
+
AND (
|
|
7692
|
+
EXISTS (
|
|
7693
|
+
SELECT 1
|
|
7694
|
+
FROM unnest($8::text[]) AS field_values(field)
|
|
7695
|
+
WHERE target._cell_meta -> field_values.field ->> 'runId' = $5::text
|
|
7696
|
+
)
|
|
7697
|
+
OR (
|
|
7698
|
+
coalesce(target._attempt_owner_run_id, target._run_id) = $10::text
|
|
7699
|
+
AND COALESCE(target._attempt_seq, 0) = $12::integer
|
|
7700
|
+
)
|
|
7701
|
+
)
|
|
7702
|
+
AND (
|
|
7703
|
+
target._status <> 'enriched'
|
|
7704
|
+
OR (${targetChangedPatchedCellSql})
|
|
7705
|
+
)
|
|
7706
|
+
-- First terminal wins: suppress conflict for same owner+epoch already-terminal row.
|
|
7707
|
+
-- Durable replay (omitted_terminal_replay) from same attempt epoch is idempotent.
|
|
7708
|
+
AND NOT (
|
|
7709
|
+
$10::text IS NOT NULL
|
|
7710
|
+
AND $12::integer IS NOT NULL
|
|
7711
|
+
AND target._status = 'enriched'
|
|
7712
|
+
AND coalesce(target._attempt_owner_run_id, target._run_id) = $10::text
|
|
7713
|
+
AND COALESCE(target._attempt_seq, 0) = $12::integer
|
|
7714
|
+
)
|
|
7715
|
+
),
|
|
7646
7716
|
applied_rows AS (
|
|
7647
7717
|
UPDATE ${sheetTable(session)} AS target
|
|
7648
7718
|
SET _status = 'enriched',
|
|
@@ -7660,31 +7730,14 @@ async function completeRuntimeMapRowChunksWithInputIndexRepair(
|
|
|
7660
7730
|
FROM matched_updates AS updates, ${sheetTable(session)} AS prev
|
|
7661
7731
|
WHERE target._key = updates.matched_key
|
|
7662
7732
|
AND prev._key = target._key
|
|
7733
|
+
AND NOT EXISTS (SELECT 1 FROM same_version_conflicts)
|
|
7663
7734
|
AND ($13::bigint IS NULL OR target._write_version = $13::bigint)
|
|
7664
7735
|
AND ($13::bigint IS NOT NULL OR target._status <> 'enriched')
|
|
7665
7736
|
AND NOT (${newerTerminalRuntimeSheetRowSql('target', '$11::timestamptz', '$12::integer', '$9::text', '$10::text')})
|
|
7666
7737
|
AND (
|
|
7667
7738
|
($9::text IS NULL AND target._run_id = $5::text)
|
|
7668
7739
|
OR ($9::text IS NOT NULL AND ${activeRuntimeSheetAttemptFenceSql('target', '$9::text', '$10::text', '$11::timestamptz', '$12::integer')})
|
|
7669
|
-
|
|
7670
|
-
)
|
|
7671
|
-
AND NOT (
|
|
7672
|
-
$13::bigint IS NOT NULL
|
|
7673
|
-
AND target._write_version = $13::bigint
|
|
7674
|
-
AND target._run_id = $5::text
|
|
7675
|
-
AND target._status = 'enriched'
|
|
7676
|
-
AND updates.submitted_key = target._key
|
|
7677
|
-
AND (
|
|
7678
|
-
EXISTS (
|
|
7679
|
-
SELECT 1
|
|
7680
|
-
FROM unnest($8::text[]) AS field_values(field)
|
|
7681
|
-
WHERE target._cell_meta -> field_values.field ->> 'runId' = $5::text
|
|
7682
|
-
)
|
|
7683
|
-
OR (
|
|
7684
|
-
$10::text IS NOT NULL
|
|
7685
|
-
AND target._attempt_owner_run_id IS NOT DISTINCT FROM $10::text
|
|
7686
|
-
)
|
|
7687
|
-
)
|
|
7740
|
+
OR ($9::text IS NOT NULL AND ${writableEnrichedAttemptSql})
|
|
7688
7741
|
)
|
|
7689
7742
|
AND (
|
|
7690
7743
|
target._status <> 'enriched'
|
|
@@ -7813,7 +7866,8 @@ async function completeRuntimeMapRowChunksWithInputIndexRepair(
|
|
|
7813
7866
|
)
|
|
7814
7867
|
SELECT
|
|
7815
7868
|
(SELECT count(*)::int FROM applied_rows) AS updated,
|
|
7816
|
-
coalesce((SELECT jsonb_agg(jsonb_build_object('key', _key, 'reason', reason, 'rowVersionStamp', row_write_version)) FROM fenced_rows), '[]'::jsonb) AS fenced_rows
|
|
7869
|
+
coalesce((SELECT jsonb_agg(jsonb_build_object('key', _key, 'reason', reason, 'rowVersionStamp', row_write_version)) FROM fenced_rows), '[]'::jsonb) AS fenced_rows,
|
|
7870
|
+
coalesce((SELECT array_agg(_key) FROM same_version_conflicts), '{}'::text[]) AS conflict_keys`,
|
|
7817
7871
|
[
|
|
7818
7872
|
chunkKeys,
|
|
7819
7873
|
chunkInputIndexes,
|
|
@@ -7832,8 +7886,9 @@ async function completeRuntimeMapRowChunksWithInputIndexRepair(
|
|
|
7832
7886
|
);
|
|
7833
7887
|
updated += Number(rows[0]?.updated ?? 0);
|
|
7834
7888
|
fencedRows.push(...parseRuntimeMapRowsFencedRows(rows[0]?.fenced_rows));
|
|
7889
|
+
conflictKeys.push(...(rows[0]?.conflict_keys ?? []));
|
|
7835
7890
|
}
|
|
7836
|
-
return { updated, fencedRows };
|
|
7891
|
+
return { updated, fencedRows, conflictKeys };
|
|
7837
7892
|
}
|
|
7838
7893
|
|
|
7839
7894
|
async function insertMissingCompletedMapRowChunks(
|
|
@@ -8029,6 +8084,7 @@ async function failRuntimeMapRowChunks(
|
|
|
8029
8084
|
): Promise<RuntimeMapRowsMutationResult> {
|
|
8030
8085
|
let updated = 0;
|
|
8031
8086
|
const fencedRows: RuntimeMapRowsStaleRow[] = [];
|
|
8087
|
+
const conflictKeys: string[] = [];
|
|
8032
8088
|
for (const chunk of input.chunks) {
|
|
8033
8089
|
const chunkKeys = chunk.map((row) => row.key);
|
|
8034
8090
|
const chunkInputIndexes = chunk.map((row) => row.input_index);
|
|
@@ -8061,6 +8117,7 @@ async function failRuntimeMapRowChunks(
|
|
|
8061
8117
|
const { rows } = await client.query<{
|
|
8062
8118
|
updated?: number;
|
|
8063
8119
|
fenced_rows?: unknown;
|
|
8120
|
+
conflict_keys?: string[];
|
|
8064
8121
|
}>(
|
|
8065
8122
|
`WITH updates AS (
|
|
8066
8123
|
SELECT key_values._key,
|
|
@@ -8081,7 +8138,6 @@ async function failRuntimeMapRowChunks(
|
|
|
8081
8138
|
matched_updates AS (
|
|
8082
8139
|
SELECT DISTINCT ON (target._key)
|
|
8083
8140
|
target._key AS matched_key,
|
|
8084
|
-
updates._key AS submitted_key,
|
|
8085
8141
|
updates.data_patch,
|
|
8086
8142
|
updates.cell_meta_patch,
|
|
8087
8143
|
updates.error
|
|
@@ -8095,6 +8151,42 @@ async function failRuntimeMapRowChunks(
|
|
|
8095
8151
|
)
|
|
8096
8152
|
ORDER BY target._key, (target._key = updates._key) DESC
|
|
8097
8153
|
),
|
|
8154
|
+
same_version_conflicts AS (
|
|
8155
|
+
SELECT updates.matched_key AS _key
|
|
8156
|
+
FROM matched_updates AS updates
|
|
8157
|
+
JOIN ${sheetTable(session)} AS target
|
|
8158
|
+
ON target._key = updates.matched_key
|
|
8159
|
+
WHERE $16::bigint IS NOT NULL
|
|
8160
|
+
AND target._write_version = $16::bigint
|
|
8161
|
+
AND target._run_id = $6::text
|
|
8162
|
+
AND target._status IN ('enriched', 'failed')
|
|
8163
|
+
AND (
|
|
8164
|
+
EXISTS (
|
|
8165
|
+
SELECT 1
|
|
8166
|
+
FROM unnest($9::text[]) AS field_values(field)
|
|
8167
|
+
WHERE target._cell_meta -> field_values.field ->> 'runId' = $6::text
|
|
8168
|
+
)
|
|
8169
|
+
OR (
|
|
8170
|
+
coalesce(target._attempt_owner_run_id, target._run_id) = $12::text
|
|
8171
|
+
AND COALESCE(target._attempt_seq, 0) = $14::integer
|
|
8172
|
+
)
|
|
8173
|
+
)
|
|
8174
|
+
AND (
|
|
8175
|
+
target._status <> 'failed'
|
|
8176
|
+
OR target._error IS DISTINCT FROM updates.error
|
|
8177
|
+
OR (${targetChangedPatchedCellSql})
|
|
8178
|
+
)
|
|
8179
|
+
-- Same-owner terminal replay is not a conflict. Normal replay
|
|
8180
|
+
-- preserves the first value below; explicit force-failure may update it.
|
|
8181
|
+
-- Different owners and attempt epochs still conflict.
|
|
8182
|
+
AND NOT (
|
|
8183
|
+
$12::text IS NOT NULL
|
|
8184
|
+
AND $14::integer IS NOT NULL
|
|
8185
|
+
AND target._status IN ('failed', 'enriched')
|
|
8186
|
+
AND coalesce(target._attempt_owner_run_id, target._run_id) = $12::text
|
|
8187
|
+
AND COALESCE(target._attempt_seq, 0) = $14::integer
|
|
8188
|
+
)
|
|
8189
|
+
),
|
|
8098
8190
|
applied_rows AS (
|
|
8099
8191
|
UPDATE ${sheetTable(session)} AS target
|
|
8100
8192
|
SET _status = 'failed',
|
|
@@ -8111,6 +8203,7 @@ async function failRuntimeMapRowChunks(
|
|
|
8111
8203
|
_cell_meta = ${mergeRuntimeCellMetaPatchSql('target._cell_meta', 'updates.cell_meta_patch')}${input.physicalUpdateSetSql}
|
|
8112
8204
|
FROM matched_updates AS updates, ${sheetTable(session)} AS prev
|
|
8113
8205
|
WHERE target._key = updates.matched_key
|
|
8206
|
+
AND NOT EXISTS (SELECT 1 FROM same_version_conflicts)
|
|
8114
8207
|
AND ($16::bigint IS NULL OR target._write_version = $16::bigint)
|
|
8115
8208
|
AND prev._key = target._key
|
|
8116
8209
|
AND ($15::boolean OR target._status <> 'enriched')
|
|
@@ -8119,16 +8212,15 @@ async function failRuntimeMapRowChunks(
|
|
|
8119
8212
|
($11::text IS NULL AND target._run_id = $6::text)
|
|
8120
8213
|
OR ($11::text IS NOT NULL AND ${activeRuntimeSheetAttemptFenceSql('target', '$11::text', '$12::text', '$13::timestamptz', '$14::integer')})
|
|
8121
8214
|
)
|
|
8122
|
-
--
|
|
8123
|
-
--
|
|
8124
|
-
-- hatch and may still overwrite it.
|
|
8215
|
+
-- First terminal wins for failed rows too, BUT only when NOT force-failing.
|
|
8216
|
+
-- Normal replay: no-op when already-failed OR already-enriched from same owner+epoch.
|
|
8125
8217
|
AND NOT (
|
|
8126
8218
|
$15::boolean = FALSE
|
|
8127
|
-
AND $
|
|
8128
|
-
AND
|
|
8129
|
-
AND target._run_id = $6::text
|
|
8219
|
+
AND $12::text IS NOT NULL
|
|
8220
|
+
AND $14::integer IS NOT NULL
|
|
8130
8221
|
AND target._status IN ('failed', 'enriched')
|
|
8131
|
-
AND
|
|
8222
|
+
AND coalesce(target._attempt_owner_run_id, target._run_id) = $12::text
|
|
8223
|
+
AND COALESCE(target._attempt_seq, 0) = $14::integer
|
|
8132
8224
|
)
|
|
8133
8225
|
RETURNING target._key, prev._status AS prev_status
|
|
8134
8226
|
),
|
|
@@ -8225,7 +8317,8 @@ async function failRuntimeMapRowChunks(
|
|
|
8225
8317
|
)
|
|
8226
8318
|
SELECT
|
|
8227
8319
|
(SELECT count(*)::int FROM applied_rows) AS updated,
|
|
8228
|
-
coalesce((SELECT jsonb_agg(jsonb_build_object('key', _key, 'reason', reason, 'rowVersionStamp', row_write_version)) FROM fenced_rows), '[]'::jsonb) AS fenced_rows
|
|
8320
|
+
coalesce((SELECT jsonb_agg(jsonb_build_object('key', _key, 'reason', reason, 'rowVersionStamp', row_write_version)) FROM fenced_rows), '[]'::jsonb) AS fenced_rows,
|
|
8321
|
+
coalesce((SELECT array_agg(_key) FROM same_version_conflicts), '{}'::text[]) AS conflict_keys`,
|
|
8229
8322
|
[
|
|
8230
8323
|
chunkKeys,
|
|
8231
8324
|
chunkInputIndexes,
|
|
@@ -8247,10 +8340,12 @@ async function failRuntimeMapRowChunks(
|
|
|
8247
8340
|
);
|
|
8248
8341
|
const appliedCount = Number(rows[0]?.updated ?? 0);
|
|
8249
8342
|
const chunkFencedRows = parseRuntimeMapRowsFencedRows(rows[0]?.fenced_rows);
|
|
8343
|
+
const chunkConflictKeys = rows[0]?.conflict_keys ?? [];
|
|
8250
8344
|
updated += appliedCount;
|
|
8251
8345
|
fencedRows.push(...chunkFencedRows);
|
|
8346
|
+
conflictKeys.push(...chunkConflictKeys);
|
|
8252
8347
|
}
|
|
8253
|
-
return { updated, fencedRows };
|
|
8348
|
+
return { updated, fencedRows, conflictKeys };
|
|
8254
8349
|
}
|
|
8255
8350
|
|
|
8256
8351
|
/**
|
|
@@ -8461,9 +8556,10 @@ export async function completeRuntimeMapRows(
|
|
|
8461
8556
|
return {
|
|
8462
8557
|
updated: updated.updated + inserted.inserted,
|
|
8463
8558
|
fencedRows: updated.fencedRows,
|
|
8559
|
+
conflictKeys: updated.conflictKeys,
|
|
8464
8560
|
};
|
|
8465
8561
|
})()
|
|
8466
|
-
: { updated: 0, fencedRows: [] };
|
|
8562
|
+
: { updated: 0, fencedRows: [], conflictKeys: [] };
|
|
8467
8563
|
const failed =
|
|
8468
8564
|
failedRows.length > 0
|
|
8469
8565
|
? await failRuntimeMapRowChunks(client, session, {
|
|
@@ -8482,7 +8578,17 @@ export async function completeRuntimeMapRows(
|
|
|
8482
8578
|
input.tableNamespace,
|
|
8483
8579
|
),
|
|
8484
8580
|
})
|
|
8485
|
-
: { updated: 0, fencedRows: [] };
|
|
8581
|
+
: { updated: 0, fencedRows: [], conflictKeys: [] };
|
|
8582
|
+
const conflictKeys = [...completed.conflictKeys, ...failed.conflictKeys];
|
|
8583
|
+
if (conflictKeys.length > 0) {
|
|
8584
|
+
throw new Error(
|
|
8585
|
+
`Runtime Sheet received the same write version with a different terminal payload for row(s): ${[
|
|
8586
|
+
...new Set(conflictKeys),
|
|
8587
|
+
]
|
|
8588
|
+
.slice(0, 10)
|
|
8589
|
+
.join(', ')}.`,
|
|
8590
|
+
);
|
|
8591
|
+
}
|
|
8486
8592
|
return classifyRuntimeMapRowsWrite({
|
|
8487
8593
|
submittedKeys: uniqueRows.keys(),
|
|
8488
8594
|
updated: completed.updated + failed.updated,
|
|
@@ -41,11 +41,11 @@ export function releasableRuntimeSheetAttemptFenceSql(
|
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
/**
|
|
44
|
-
* Predicate for
|
|
45
|
-
* attempt owner + epoch.
|
|
46
|
-
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
44
|
+
* Predicate for durable replay idempotency: matches rows that are already
|
|
45
|
+
* terminal (enriched or failed) from the same attempt owner + epoch. Used to
|
|
46
|
+
* suppress same-version conflicts when a worker restarts and re-runs map rows
|
|
47
|
+
* that it already completed. First terminal state wins; payload/error drift on
|
|
48
|
+
* replay is accepted as a no-op rather than rejected as a conflict.
|
|
49
49
|
*/
|
|
50
50
|
export function sameOwnerTerminalAttemptEpochSql(
|
|
51
51
|
tableAlias: string,
|
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.188",
|
|
3055
3055
|
updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.",
|
|
3056
3056
|
packageCapabilities: {
|
|
3057
3057
|
updatePreferences: 1
|
package/dist/cli/index.mjs
CHANGED
|
@@ -3046,7 +3046,7 @@ var SDK_RELEASE = {
|
|
|
3046
3046
|
// getters keep their established compatibility behavior.
|
|
3047
3047
|
// 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
|
|
3048
3048
|
// 0.3.90 is the first deliberately versioned SDK release for API v3.
|
|
3049
|
-
version: "0.3.
|
|
3049
|
+
version: "0.3.188",
|
|
3050
3050
|
updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.",
|
|
3051
3051
|
packageCapabilities: {
|
|
3052
3052
|
updatePreferences: 1
|
package/dist/index.js
CHANGED
|
@@ -864,7 +864,7 @@ var SDK_RELEASE = {
|
|
|
864
864
|
// getters keep their established compatibility behavior.
|
|
865
865
|
// 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
|
|
866
866
|
// 0.3.90 is the first deliberately versioned SDK release for API v3.
|
|
867
|
-
version: "0.3.
|
|
867
|
+
version: "0.3.188",
|
|
868
868
|
updateSummary: "Play grep now returns concise results with the matched fields and terms. Automatic CLI updates are enabled by default; use `deepline settings autoupdate off` to opt out, `deepline settings autoupdate on` to re-enable updates, or `deepline settings autoupdate pin <version>` to hold an exact release.",
|
|
869
869
|
packageCapabilities: {
|
|
870
870
|
updatePreferences: 1
|
package/dist/index.mjs
CHANGED
|
@@ -768,7 +768,7 @@ var SDK_RELEASE = {
|
|
|
768
768
|
// getters keep their established compatibility behavior.
|
|
769
769
|
// 0.3.1 deprecated the legacy `deepline enrich` command in favor of Plays.
|
|
770
770
|
// 0.3.90 is the first deliberately versioned SDK release for API v3.
|
|
771
|
-
version: "0.3.
|
|
771
|
+
version: "0.3.188",
|
|
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
|
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.188";
|
|
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.188";
|
|
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.188",
|
|
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.188",
|
|
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
|