@indigoai-us/hq-cloud 6.15.87 → 6.15.88
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-watch-loop.d.ts.map +1 -1
- package/dist/bin/sync-runner-watch-loop.js +56 -26
- package/dist/bin/sync-runner-watch-loop.js.map +1 -1
- package/dist/bin/sync-runner.test.js +241 -0
- package/dist/bin/sync-runner.test.js.map +1 -1
- package/dist/cli/reindex.d.ts.map +1 -1
- package/dist/cli/reindex.js +34 -9
- package/dist/cli/reindex.js.map +1 -1
- package/dist/cli/reindex.test.js +39 -7
- package/dist/cli/reindex.test.js.map +1 -1
- package/dist/sync/parallel-sync-coordinator.d.ts +2 -1
- package/dist/sync/parallel-sync-coordinator.d.ts.map +1 -1
- package/dist/sync/parallel-sync-coordinator.js +29 -11
- package/dist/sync/parallel-sync-coordinator.js.map +1 -1
- package/dist/sync/parallel-sync-coordinator.test.js +76 -1
- package/dist/sync/parallel-sync-coordinator.test.js.map +1 -1
- package/dist/sync/push-receiver.test.js +12 -2
- package/dist/sync/push-receiver.test.js.map +1 -1
- package/dist/sync/sync-work.d.ts +2 -0
- package/dist/sync/sync-work.d.ts.map +1 -1
- package/dist/sync/sync-work.js.map +1 -1
- package/package.json +1 -1
|
@@ -4859,6 +4859,10 @@ describe("runRunnerWithLoop — event-push wiring", () => {
|
|
|
4859
4859
|
"/tmp/hq/companies/indigo/warmup-superseded.md",
|
|
4860
4860
|
"companies/indigo/warmup-superseded.md",
|
|
4861
4861
|
]]),
|
|
4862
|
+
changes: new Map([[
|
|
4863
|
+
"/tmp/hq/companies/indigo/warmup-superseded.md",
|
|
4864
|
+
{ kind: "unlinkDir" },
|
|
4865
|
+
]]),
|
|
4862
4866
|
},
|
|
4863
4867
|
scannedPaths: 1,
|
|
4864
4868
|
}));
|
|
@@ -5503,6 +5507,243 @@ describe("runRunnerWithLoop — event-push wiring", () => {
|
|
|
5503
5507
|
fs.rmSync(hqRoot, { recursive: true, force: true });
|
|
5504
5508
|
}
|
|
5505
5509
|
});
|
|
5510
|
+
it("parallel coordinator partitions receiver events into fast and slow realtime lanes", async () => {
|
|
5511
|
+
const previous = process.env.HQ_SYNC_PARALLEL_COORDINATOR;
|
|
5512
|
+
process.env.HQ_SYNC_PARALLEL_COORDINATOR = "1";
|
|
5513
|
+
const hqRoot = fs.mkdtempSync(path.join(os.tmpdir(), "hq-parallel-receiver-lanes-"));
|
|
5514
|
+
const watcher = makeBatchWatcherStub();
|
|
5515
|
+
let receiverSync;
|
|
5516
|
+
let triggerShutdown = () => { };
|
|
5517
|
+
let releaseSlow = () => { };
|
|
5518
|
+
const slowGate = new Promise((resolve) => { releaseSlow = resolve; });
|
|
5519
|
+
const order = [];
|
|
5520
|
+
const journal = readJournal("indigo");
|
|
5521
|
+
journal.files["small.md"] = {
|
|
5522
|
+
hash: "sha256:small",
|
|
5523
|
+
size: 16,
|
|
5524
|
+
syncedAt: "2026-08-28T00:00:00.000Z",
|
|
5525
|
+
direction: "down",
|
|
5526
|
+
};
|
|
5527
|
+
writeJournal("indigo", journal);
|
|
5528
|
+
const runPass = vi.fn(async (argv) => {
|
|
5529
|
+
if (argv.includes("held-unknown.md")) {
|
|
5530
|
+
order.push("slow-held");
|
|
5531
|
+
await slowGate;
|
|
5532
|
+
}
|
|
5533
|
+
else if (argv.includes("small.md")) {
|
|
5534
|
+
order.push("fast-small");
|
|
5535
|
+
}
|
|
5536
|
+
else if (argv.includes("unknown.md")) {
|
|
5537
|
+
order.push("slow-unknown");
|
|
5538
|
+
}
|
|
5539
|
+
return completedPassOutcome();
|
|
5540
|
+
});
|
|
5541
|
+
const event = (relativePath) => ({
|
|
5542
|
+
kind: "upsert",
|
|
5543
|
+
relativePath,
|
|
5544
|
+
contentHash: "sha256:remote",
|
|
5545
|
+
mtime: "2026-08-28T00:00:00.000Z",
|
|
5546
|
+
originDeviceId: "peer-device",
|
|
5547
|
+
originTenantId: "tenant-indigo",
|
|
5548
|
+
sequenceNumber: 1,
|
|
5549
|
+
eventTimestamp: "2026-08-28T00:00:00.000Z",
|
|
5550
|
+
});
|
|
5551
|
+
const loop = runRunnerWithLoop(["--companies", "--watch", "--event-push", "--direction", "pull", "--hq-root", hqRoot], {
|
|
5552
|
+
runPass,
|
|
5553
|
+
createWatcher: () => watcher,
|
|
5554
|
+
createReceiver: ({ syncBatchFn }) => {
|
|
5555
|
+
receiverSync = syncBatchFn;
|
|
5556
|
+
return { connected: true, start: async () => { }, dispose: async () => { } };
|
|
5557
|
+
},
|
|
5558
|
+
sleep: () => new Promise(() => { }),
|
|
5559
|
+
onShutdownSignal: (handler) => {
|
|
5560
|
+
triggerShutdown = handler;
|
|
5561
|
+
return () => { };
|
|
5562
|
+
},
|
|
5563
|
+
});
|
|
5564
|
+
try {
|
|
5565
|
+
await flushLoopMicrotasks(30);
|
|
5566
|
+
runPass.mockClear();
|
|
5567
|
+
const held = receiverSync({
|
|
5568
|
+
events: [event("companies/indigo/held-unknown.md")],
|
|
5569
|
+
signal: new AbortController().signal,
|
|
5570
|
+
});
|
|
5571
|
+
await flushLoopMicrotasks(20);
|
|
5572
|
+
expect(order).toEqual(["slow-held"]);
|
|
5573
|
+
const partitioned = receiverSync({
|
|
5574
|
+
events: [
|
|
5575
|
+
event("companies/indigo/small.md"),
|
|
5576
|
+
event("companies/indigo/unknown.md"),
|
|
5577
|
+
],
|
|
5578
|
+
signal: new AbortController().signal,
|
|
5579
|
+
});
|
|
5580
|
+
await flushLoopMicrotasks(20);
|
|
5581
|
+
expect(order).toEqual(["slow-held", "fast-small"]);
|
|
5582
|
+
releaseSlow();
|
|
5583
|
+
await held;
|
|
5584
|
+
await partitioned;
|
|
5585
|
+
expect(order).toEqual(["slow-held", "fast-small", "slow-unknown"]);
|
|
5586
|
+
}
|
|
5587
|
+
finally {
|
|
5588
|
+
releaseSlow();
|
|
5589
|
+
triggerShutdown();
|
|
5590
|
+
await loop;
|
|
5591
|
+
if (previous === undefined)
|
|
5592
|
+
delete process.env.HQ_SYNC_PARALLEL_COORDINATOR;
|
|
5593
|
+
else
|
|
5594
|
+
process.env.HQ_SYNC_PARALLEL_COORDINATOR = previous;
|
|
5595
|
+
fs.rmSync(hqRoot, { recursive: true, force: true });
|
|
5596
|
+
}
|
|
5597
|
+
});
|
|
5598
|
+
it("parallel coordinator submits a later route's fast receiver work before an earlier route's slow pull completes", async () => {
|
|
5599
|
+
const previous = process.env.HQ_SYNC_PARALLEL_COORDINATOR;
|
|
5600
|
+
process.env.HQ_SYNC_PARALLEL_COORDINATOR = "1";
|
|
5601
|
+
const hqRoot = fs.mkdtempSync(path.join(os.tmpdir(), "hq-parallel-receiver-route-order-"));
|
|
5602
|
+
const watcher = makeBatchWatcherStub();
|
|
5603
|
+
let receiverSync;
|
|
5604
|
+
let triggerShutdown = () => { };
|
|
5605
|
+
let releaseSlow = () => { };
|
|
5606
|
+
const slowGate = new Promise((resolve) => { releaseSlow = resolve; });
|
|
5607
|
+
const order = [];
|
|
5608
|
+
const journal = readJournal("indigo");
|
|
5609
|
+
journal.files["fast.md"] = {
|
|
5610
|
+
hash: "sha256:fast",
|
|
5611
|
+
size: 16,
|
|
5612
|
+
syncedAt: "2026-08-28T00:00:00.000Z",
|
|
5613
|
+
direction: "down",
|
|
5614
|
+
};
|
|
5615
|
+
writeJournal("indigo", journal);
|
|
5616
|
+
const runPass = vi.fn(async (argv) => {
|
|
5617
|
+
if (argv.includes("slow.md")) {
|
|
5618
|
+
order.push("slow-acme");
|
|
5619
|
+
await slowGate;
|
|
5620
|
+
}
|
|
5621
|
+
else if (argv.includes("fast.md")) {
|
|
5622
|
+
order.push("fast-indigo");
|
|
5623
|
+
}
|
|
5624
|
+
return completedPassOutcome();
|
|
5625
|
+
});
|
|
5626
|
+
const event = (relativePath) => ({
|
|
5627
|
+
kind: "upsert",
|
|
5628
|
+
relativePath,
|
|
5629
|
+
contentHash: "sha256:remote",
|
|
5630
|
+
mtime: "2026-08-28T00:00:00.000Z",
|
|
5631
|
+
originDeviceId: "peer-device",
|
|
5632
|
+
originTenantId: "tenant-indigo",
|
|
5633
|
+
sequenceNumber: 1,
|
|
5634
|
+
eventTimestamp: "2026-08-28T00:00:00.000Z",
|
|
5635
|
+
});
|
|
5636
|
+
const loop = runRunnerWithLoop(["--companies", "--watch", "--event-push", "--direction", "pull", "--hq-root", hqRoot], {
|
|
5637
|
+
runPass,
|
|
5638
|
+
createWatcher: () => watcher,
|
|
5639
|
+
createReceiver: ({ syncBatchFn }) => {
|
|
5640
|
+
receiverSync = syncBatchFn;
|
|
5641
|
+
return { connected: true, start: async () => { }, dispose: async () => { } };
|
|
5642
|
+
},
|
|
5643
|
+
sleep: () => new Promise(() => { }),
|
|
5644
|
+
onShutdownSignal: (handler) => {
|
|
5645
|
+
triggerShutdown = handler;
|
|
5646
|
+
return () => { };
|
|
5647
|
+
},
|
|
5648
|
+
});
|
|
5649
|
+
try {
|
|
5650
|
+
await flushLoopMicrotasks(30);
|
|
5651
|
+
runPass.mockClear();
|
|
5652
|
+
const delivery = receiverSync({
|
|
5653
|
+
events: [
|
|
5654
|
+
event("companies/acme/slow.md"),
|
|
5655
|
+
event("companies/indigo/fast.md"),
|
|
5656
|
+
],
|
|
5657
|
+
signal: new AbortController().signal,
|
|
5658
|
+
});
|
|
5659
|
+
await flushLoopMicrotasks(20);
|
|
5660
|
+
// Regression: the old per-route loop started slow-acme and awaited it
|
|
5661
|
+
// before it even submitted fast-indigo.
|
|
5662
|
+
expect(order).toEqual(["fast-indigo", "slow-acme"]);
|
|
5663
|
+
releaseSlow();
|
|
5664
|
+
await delivery;
|
|
5665
|
+
}
|
|
5666
|
+
finally {
|
|
5667
|
+
releaseSlow();
|
|
5668
|
+
triggerShutdown();
|
|
5669
|
+
await loop;
|
|
5670
|
+
if (previous === undefined)
|
|
5671
|
+
delete process.env.HQ_SYNC_PARALLEL_COORDINATOR;
|
|
5672
|
+
else
|
|
5673
|
+
process.env.HQ_SYNC_PARALLEL_COORDINATOR = previous;
|
|
5674
|
+
fs.rmSync(hqRoot, { recursive: true, force: true });
|
|
5675
|
+
}
|
|
5676
|
+
});
|
|
5677
|
+
it("parallel coordinator exposes delivery-wide fast and slow receiver batches", async () => {
|
|
5678
|
+
const previousCoordinator = process.env.HQ_SYNC_PARALLEL_COORDINATOR;
|
|
5679
|
+
const previousFastFiles = process.env[FAST_LANE_MAX_FILES_ENV];
|
|
5680
|
+
process.env.HQ_SYNC_PARALLEL_COORDINATOR = "1";
|
|
5681
|
+
process.env[FAST_LANE_MAX_FILES_ENV] = "1";
|
|
5682
|
+
const hqRoot = fs.mkdtempSync(path.join(os.tmpdir(), "hq-parallel-receiver-delivery-cap-"));
|
|
5683
|
+
const watcher = makeBatchWatcherStub();
|
|
5684
|
+
let receiverSync;
|
|
5685
|
+
let triggerShutdown = () => { };
|
|
5686
|
+
const event = (relativePath) => ({
|
|
5687
|
+
kind: "upsert",
|
|
5688
|
+
relativePath,
|
|
5689
|
+
contentHash: "sha256:remote",
|
|
5690
|
+
mtime: "2026-08-28T00:00:00.000Z",
|
|
5691
|
+
originDeviceId: "peer-device",
|
|
5692
|
+
originTenantId: "tenant-indigo",
|
|
5693
|
+
sequenceNumber: 1,
|
|
5694
|
+
eventTimestamp: "2026-08-28T00:00:00.000Z",
|
|
5695
|
+
});
|
|
5696
|
+
for (const [slug, key] of [["acme", "small.md"], ["indigo", "small.md"]]) {
|
|
5697
|
+
const journal = readJournal(slug);
|
|
5698
|
+
journal.files[key] = {
|
|
5699
|
+
hash: `sha256:${slug}`,
|
|
5700
|
+
size: 16,
|
|
5701
|
+
syncedAt: "2026-08-28T00:00:00.000Z",
|
|
5702
|
+
direction: "down",
|
|
5703
|
+
};
|
|
5704
|
+
writeJournal(slug, journal);
|
|
5705
|
+
}
|
|
5706
|
+
const loop = runRunnerWithLoop(["--companies", "--watch", "--event-push", "--direction", "pull", "--hq-root", hqRoot], {
|
|
5707
|
+
runPass: vi.fn(async () => completedPassOutcome()),
|
|
5708
|
+
createWatcher: () => watcher,
|
|
5709
|
+
createReceiver: ({ syncBatchFn }) => {
|
|
5710
|
+
receiverSync = syncBatchFn;
|
|
5711
|
+
return { connected: true, start: async () => { }, dispose: async () => { } };
|
|
5712
|
+
},
|
|
5713
|
+
sleep: () => new Promise(() => { }),
|
|
5714
|
+
onShutdownSignal: (handler) => {
|
|
5715
|
+
triggerShutdown = handler;
|
|
5716
|
+
return () => { };
|
|
5717
|
+
},
|
|
5718
|
+
});
|
|
5719
|
+
try {
|
|
5720
|
+
await flushLoopMicrotasks(30);
|
|
5721
|
+
const batches = receiverSync.partition([
|
|
5722
|
+
event("companies/acme/small.md"),
|
|
5723
|
+
event("companies/indigo/small.md"),
|
|
5724
|
+
]);
|
|
5725
|
+
// The cap applies once to the whole delivery, not once per route. The
|
|
5726
|
+
// returned batches are receiver-visible, so its existing per-batch
|
|
5727
|
+
// acknowledgement contract retains only a failed slow receipt.
|
|
5728
|
+
expect(batches.map((batch) => batch.map((event) => event.relativePath))).toEqual([
|
|
5729
|
+
["companies/acme/small.md"],
|
|
5730
|
+
["companies/indigo/small.md"],
|
|
5731
|
+
]);
|
|
5732
|
+
}
|
|
5733
|
+
finally {
|
|
5734
|
+
triggerShutdown();
|
|
5735
|
+
await loop;
|
|
5736
|
+
if (previousCoordinator === undefined)
|
|
5737
|
+
delete process.env.HQ_SYNC_PARALLEL_COORDINATOR;
|
|
5738
|
+
else
|
|
5739
|
+
process.env.HQ_SYNC_PARALLEL_COORDINATOR = previousCoordinator;
|
|
5740
|
+
if (previousFastFiles === undefined)
|
|
5741
|
+
delete process.env[FAST_LANE_MAX_FILES_ENV];
|
|
5742
|
+
else
|
|
5743
|
+
process.env[FAST_LANE_MAX_FILES_ENV] = previousFastFiles;
|
|
5744
|
+
fs.rmSync(hqRoot, { recursive: true, force: true });
|
|
5745
|
+
}
|
|
5746
|
+
});
|
|
5506
5747
|
it("fast lane: peels a tiny watcher path from mixed multi-megabyte residue", async () => {
|
|
5507
5748
|
const hqRoot = fs.mkdtempSync(path.join(os.tmpdir(), "hq-fast-lane-mixed-watch-"));
|
|
5508
5749
|
const tinyRel = "companies/indigo/realtime.md";
|