@indigoai-us/hq-cloud 6.18.53 → 6.18.54
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/bin/sync-runner-audit.d.ts +26 -0
- package/dist/bin/sync-runner-audit.d.ts.map +1 -0
- package/dist/bin/sync-runner-audit.js +51 -0
- package/dist/bin/sync-runner-audit.js.map +1 -0
- package/dist/bin/sync-runner-company.d.ts +18 -0
- package/dist/bin/sync-runner-company.d.ts.map +1 -1
- package/dist/bin/sync-runner-company.js +186 -9
- package/dist/bin/sync-runner-company.js.map +1 -1
- package/dist/bin/sync-runner-watch-loop.d.ts +107 -5
- package/dist/bin/sync-runner-watch-loop.d.ts.map +1 -1
- package/dist/bin/sync-runner-watch-loop.js +1382 -183
- package/dist/bin/sync-runner-watch-loop.js.map +1 -1
- package/dist/bin/sync-runner.d.ts +63 -11
- package/dist/bin/sync-runner.d.ts.map +1 -1
- package/dist/bin/sync-runner.js +350 -95
- package/dist/bin/sync-runner.js.map +1 -1
- package/dist/bin/watcher-catchup-skip-store.d.ts +60 -0
- package/dist/bin/watcher-catchup-skip-store.d.ts.map +1 -0
- package/dist/bin/watcher-catchup-skip-store.js +282 -0
- package/dist/bin/watcher-catchup-skip-store.js.map +1 -0
- package/dist/cli/conflict.d.ts +6 -0
- package/dist/cli/conflict.d.ts.map +1 -1
- package/dist/cli/conflict.js +3 -1
- package/dist/cli/conflict.js.map +1 -1
- package/dist/cli/reindex.d.ts.map +1 -1
- package/dist/cli/reindex.js +95 -5
- package/dist/cli/reindex.js.map +1 -1
- package/dist/cli/rescue-core.d.ts +25 -1
- package/dist/cli/rescue-core.d.ts.map +1 -1
- package/dist/cli/rescue-core.js +69 -4
- package/dist/cli/rescue-core.js.map +1 -1
- package/dist/cli/share.d.ts +27 -0
- package/dist/cli/share.d.ts.map +1 -1
- package/dist/cli/share.js +140 -23
- package/dist/cli/share.js.map +1 -1
- package/dist/cli/sync.d.ts +18 -2
- package/dist/cli/sync.d.ts.map +1 -1
- package/dist/cli/sync.js +90 -25
- package/dist/cli/sync.js.map +1 -1
- package/dist/ignore.d.ts +1 -1
- package/dist/ignore.d.ts.map +1 -1
- package/dist/ignore.js +2 -2
- package/dist/ignore.js.map +1 -1
- package/dist/journal-row-store.d.ts.map +1 -1
- package/dist/journal-row-store.js +6 -0
- package/dist/journal-row-store.js.map +1 -1
- package/dist/journal-snapshot-v4.d.ts +8 -0
- package/dist/journal-snapshot-v4.d.ts.map +1 -1
- package/dist/journal-snapshot-v4.js +208 -17
- package/dist/journal-snapshot-v4.js.map +1 -1
- package/dist/journal.d.ts +18 -2
- package/dist/journal.d.ts.map +1 -1
- package/dist/journal.js +248 -17
- package/dist/journal.js.map +1 -1
- package/dist/lib/cloud-authoritative.d.ts +9 -2
- package/dist/lib/cloud-authoritative.d.ts.map +1 -1
- package/dist/lib/cloud-authoritative.js +34 -2
- package/dist/lib/cloud-authoritative.js.map +1 -1
- package/dist/lib/exit-codes.d.ts +2 -0
- package/dist/lib/exit-codes.d.ts.map +1 -1
- package/dist/lib/exit-codes.js +2 -0
- package/dist/lib/exit-codes.js.map +1 -1
- package/dist/personal-vault-exclusions.d.ts +2 -2
- package/dist/personal-vault-exclusions.d.ts.map +1 -1
- package/dist/personal-vault-exclusions.js +5 -3
- package/dist/personal-vault-exclusions.js.map +1 -1
- package/dist/personal-vault.d.ts +7 -0
- package/dist/personal-vault.d.ts.map +1 -1
- package/dist/personal-vault.js +10 -0
- package/dist/personal-vault.js.map +1 -1
- package/dist/qmd-runner-admission.d.ts +22 -0
- package/dist/qmd-runner-admission.d.ts.map +1 -0
- package/dist/qmd-runner-admission.js +107 -0
- package/dist/qmd-runner-admission.js.map +1 -0
- package/dist/symlink-target-policy.d.ts +11 -0
- package/dist/symlink-target-policy.d.ts.map +1 -1
- package/dist/symlink-target-policy.js +110 -0
- package/dist/symlink-target-policy.js.map +1 -1
- package/dist/sync/area-ledger-migration.d.ts +3 -1
- package/dist/sync/area-ledger-migration.d.ts.map +1 -1
- package/dist/sync/area-ledger-migration.js +3 -0
- package/dist/sync/area-ledger-migration.js.map +1 -1
- package/dist/sync/area-ledger.d.ts +3 -0
- package/dist/sync/area-ledger.d.ts.map +1 -1
- package/dist/sync/area-ledger.js +29 -6
- package/dist/sync/area-ledger.js.map +1 -1
- package/dist/sync/mutation-session.d.ts.map +1 -1
- package/dist/sync/mutation-session.js +4 -0
- package/dist/sync/mutation-session.js.map +1 -1
- package/dist/sync/parallel-sync-coordinator.d.ts +29 -0
- package/dist/sync/parallel-sync-coordinator.d.ts.map +1 -1
- package/dist/sync/parallel-sync-coordinator.js +229 -16
- package/dist/sync/parallel-sync-coordinator.js.map +1 -1
- package/dist/sync/push-receiver.d.ts +5 -0
- package/dist/sync/push-receiver.d.ts.map +1 -1
- package/dist/sync/push-receiver.js +32 -10
- package/dist/sync/push-receiver.js.map +1 -1
- package/dist/sync/state-store.d.ts +7 -0
- package/dist/sync/state-store.d.ts.map +1 -1
- package/dist/sync/state-store.js +113 -6
- package/dist/sync/state-store.js.map +1 -1
- package/dist/watch-owner-lease.d.ts +4 -0
- package/dist/watch-owner-lease.d.ts.map +1 -1
- package/dist/watch-owner-lease.js +40 -6
- package/dist/watch-owner-lease.js.map +1 -1
- package/dist/watcher.d.ts +16 -3
- package/dist/watcher.d.ts.map +1 -1
- package/dist/watcher.js +114 -21
- package/dist/watcher.js.map +1 -1
- package/package.json +4 -3
package/dist/sync/state-store.js
CHANGED
|
@@ -70,6 +70,8 @@ const COMPACTION_RETRY_BACKOFF_MAX_MS = 250;
|
|
|
70
70
|
const COMPACTION_RETRY_MIN_ATTEMPTS = 3;
|
|
71
71
|
/** Safety cap so a frozen test clock cannot spin forever. */
|
|
72
72
|
const COMPACTION_RETRY_MAX_ATTEMPTS = 10_000;
|
|
73
|
+
/** Keep a live synchronous writer from invalidating async snapshots forever. */
|
|
74
|
+
const ASYNC_COMPACTION_MAX_STALE_ATTEMPTS = 3;
|
|
73
75
|
// Test instrumentation for materialisation regressions. Kept at the storage
|
|
74
76
|
// seam so a fixture counts actual snapshot JSON decodes, not API invocations.
|
|
75
77
|
let snapshotRecoveryCount = 0;
|
|
@@ -309,6 +311,7 @@ export class StateStore {
|
|
|
309
311
|
walBytes;
|
|
310
312
|
maxRecoveryReadBytes;
|
|
311
313
|
observedHighestSnapshotGeneration;
|
|
314
|
+
deferredCompactionScheduled = false;
|
|
312
315
|
constructor(options, recovered, wasCreated) {
|
|
313
316
|
this.options = options;
|
|
314
317
|
this.scopeDigest = digestScope(options.scopeId);
|
|
@@ -345,8 +348,16 @@ export class StateStore {
|
|
|
345
348
|
// A process can die after its durable append but before append() gets
|
|
346
349
|
// to its post-lock compaction. Repair that crash window before handing
|
|
347
350
|
// an already-over-budget WAL to the caller, otherwise restart loops
|
|
348
|
-
// can grow a WAL without bound.
|
|
349
|
-
|
|
351
|
+
// can grow a WAL without bound. Large domain encoders defer that
|
|
352
|
+
// repair so opening a journal on a watcher pass does not serialize its
|
|
353
|
+
// full snapshot on the runner's event loop.
|
|
354
|
+
if (normalized.snapshotEncoderAsync) {
|
|
355
|
+
if (store.needsCompaction())
|
|
356
|
+
store.scheduleAsyncCompaction();
|
|
357
|
+
}
|
|
358
|
+
else {
|
|
359
|
+
store.compactIfNeeded();
|
|
360
|
+
}
|
|
350
361
|
return store;
|
|
351
362
|
}
|
|
352
363
|
const created = withScopeLock(dir, () => {
|
|
@@ -619,12 +630,29 @@ export class StateStore {
|
|
|
619
630
|
return this.needsCompaction();
|
|
620
631
|
}
|
|
621
632
|
/** Async counterpart used by callback-originated recovery paths. */
|
|
633
|
+
scheduleAsyncCompaction() {
|
|
634
|
+
if (this.deferredCompactionScheduled)
|
|
635
|
+
return;
|
|
636
|
+
this.deferredCompactionScheduled = true;
|
|
637
|
+
setImmediate(() => {
|
|
638
|
+
void this.compactIfNeededAsync().catch((error) => {
|
|
639
|
+
process.stderr.write(`${JSON.stringify({
|
|
640
|
+
type: "state-store-async-compaction-failed",
|
|
641
|
+
stateDir: this.stateDir,
|
|
642
|
+
error: error instanceof Error ? error.message : String(error),
|
|
643
|
+
})}\n`);
|
|
644
|
+
}).finally(() => {
|
|
645
|
+
this.deferredCompactionScheduled = false;
|
|
646
|
+
});
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
/** Async counterpart used by callback-originated recovery paths. */
|
|
622
650
|
async compactIfNeededAsync() {
|
|
623
651
|
const compacted = await withRotationClaimAsync(this.stateDir, async () => {
|
|
624
652
|
const startedAt = currentTimeMs();
|
|
625
653
|
const budget = this.generationPublishRetryBudgetMs();
|
|
626
654
|
let attempts = 0;
|
|
627
|
-
while (attempts <
|
|
655
|
+
while (attempts < ASYNC_COMPACTION_MAX_STALE_ATTEMPTS) {
|
|
628
656
|
let resolveStaged;
|
|
629
657
|
let rejectStaged;
|
|
630
658
|
const stagedReady = new Promise((resolve, reject) => {
|
|
@@ -680,7 +708,7 @@ export class StateStore {
|
|
|
680
708
|
return false;
|
|
681
709
|
attempts += 1;
|
|
682
710
|
try {
|
|
683
|
-
const staged =
|
|
711
|
+
const staged = await stageGenerationAsync(this.stateDir, this.scopeDigest, plan.next, this.options.snapshotEncoder, this.options.snapshotEncoderAsync);
|
|
684
712
|
try {
|
|
685
713
|
afterGenerationStageHookForTest?.();
|
|
686
714
|
}
|
|
@@ -705,6 +733,12 @@ export class StateStore {
|
|
|
705
733
|
}
|
|
706
734
|
return false;
|
|
707
735
|
});
|
|
736
|
+
if (compacted === false && this.needsCompaction()) {
|
|
737
|
+
// A synchronous append can keep advancing the WAL while an async
|
|
738
|
+
// snapshot yields. After three rejected captures, finish one bounded
|
|
739
|
+
// rotation synchronously instead of letting the WAL grow indefinitely.
|
|
740
|
+
return this.compactIfNeeded();
|
|
741
|
+
}
|
|
708
742
|
return compacted ?? false;
|
|
709
743
|
}
|
|
710
744
|
getGenerationIdentity() {
|
|
@@ -810,8 +844,12 @@ export class StateStore {
|
|
|
810
844
|
recovered = true;
|
|
811
845
|
continue;
|
|
812
846
|
}
|
|
813
|
-
if (compact)
|
|
814
|
-
this.
|
|
847
|
+
if (compact) {
|
|
848
|
+
if (this.options.snapshotEncoderAsync)
|
|
849
|
+
this.scheduleAsyncCompaction();
|
|
850
|
+
else
|
|
851
|
+
this.compact();
|
|
852
|
+
}
|
|
815
853
|
return result;
|
|
816
854
|
}
|
|
817
855
|
}
|
|
@@ -1394,6 +1432,75 @@ function stageGeneration(dir, scopeDigest, generation, snapshotEncoder) {
|
|
|
1394
1432
|
throw error;
|
|
1395
1433
|
}
|
|
1396
1434
|
}
|
|
1435
|
+
async function stageGenerationAsync(dir, scopeDigest, generation, snapshotEncoder, snapshotEncoderAsync) {
|
|
1436
|
+
snapshotMaterializationCount++;
|
|
1437
|
+
const payload = {
|
|
1438
|
+
lastRecordSequence: generation.lastRecordSequence,
|
|
1439
|
+
state: generation.state,
|
|
1440
|
+
};
|
|
1441
|
+
const snapshot = snapshotEncoderAsync
|
|
1442
|
+
? await snapshotEncoderAsync(generation.generation, scopeDigest, payload)
|
|
1443
|
+
: encodeGenerationSnapshot(generation, scopeDigest, snapshotEncoder);
|
|
1444
|
+
let snapshotTemporary;
|
|
1445
|
+
let walTemporary;
|
|
1446
|
+
try {
|
|
1447
|
+
snapshotTemporary = await writeDurableTemporaryAsync(dir, `snapshot-${generation.generation}`, snapshot.chunks);
|
|
1448
|
+
walTemporary = await writeDurableTemporaryAsync(dir, `wal-${generation.generation}`, encodeWalHeader(generation.generation, scopeDigest));
|
|
1449
|
+
return { generation, snapshotTemporary, walTemporary };
|
|
1450
|
+
}
|
|
1451
|
+
catch (error) {
|
|
1452
|
+
if (snapshotTemporary !== undefined) {
|
|
1453
|
+
try {
|
|
1454
|
+
await fs.promises.rm(snapshotTemporary, { force: true });
|
|
1455
|
+
}
|
|
1456
|
+
catch { /* preserve primary staging error */ }
|
|
1457
|
+
}
|
|
1458
|
+
if (walTemporary !== undefined) {
|
|
1459
|
+
try {
|
|
1460
|
+
await fs.promises.rm(walTemporary, { force: true });
|
|
1461
|
+
}
|
|
1462
|
+
catch { /* preserve primary staging error */ }
|
|
1463
|
+
}
|
|
1464
|
+
throw error;
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
async function writeDurableTemporaryAsync(dir, label, bytes) {
|
|
1468
|
+
const temporary = temporaryPath(dir, label);
|
|
1469
|
+
let handle;
|
|
1470
|
+
try {
|
|
1471
|
+
handle = await fs.promises.open(temporary, "wx");
|
|
1472
|
+
if (label.startsWith("snapshot-"))
|
|
1473
|
+
snapshotWriteHookForTest?.();
|
|
1474
|
+
const chunks = Buffer.isBuffer(bytes) ? [bytes] : bytes;
|
|
1475
|
+
for (const chunk of chunks) {
|
|
1476
|
+
let offset = 0;
|
|
1477
|
+
while (offset < chunk.length) {
|
|
1478
|
+
const { bytesWritten } = await handle.write(chunk, offset, chunk.length - offset, null);
|
|
1479
|
+
if (bytesWritten <= 0)
|
|
1480
|
+
throw new Error("state-store: async durable write made no progress");
|
|
1481
|
+
offset += bytesWritten;
|
|
1482
|
+
}
|
|
1483
|
+
await new Promise((resolve) => setImmediate(resolve));
|
|
1484
|
+
}
|
|
1485
|
+
await handle.datasync();
|
|
1486
|
+
await handle.close();
|
|
1487
|
+
handle = undefined;
|
|
1488
|
+
return temporary;
|
|
1489
|
+
}
|
|
1490
|
+
catch (error) {
|
|
1491
|
+
if (handle !== undefined) {
|
|
1492
|
+
try {
|
|
1493
|
+
await handle.close();
|
|
1494
|
+
}
|
|
1495
|
+
catch { /* preserve primary durable-write error */ }
|
|
1496
|
+
}
|
|
1497
|
+
try {
|
|
1498
|
+
await fs.promises.rm(temporary, { force: true });
|
|
1499
|
+
}
|
|
1500
|
+
catch { /* preserve primary durable-write error */ }
|
|
1501
|
+
throw new Error(`state-store: async staged write failed for ${label}`, { cause: error });
|
|
1502
|
+
}
|
|
1503
|
+
}
|
|
1397
1504
|
function encodeGenerationSnapshot(generation, scopeDigest, snapshotEncoder) {
|
|
1398
1505
|
const payload = {
|
|
1399
1506
|
lastRecordSequence: generation.lastRecordSequence,
|