@indigoai-us/hq-cloud 6.15.75 → 6.15.77

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.
Files changed (73) hide show
  1. package/dist/bin/sync-runner-watch-loop.d.ts.map +1 -1
  2. package/dist/bin/sync-runner-watch-loop.js +12 -2
  3. package/dist/bin/sync-runner-watch-loop.js.map +1 -1
  4. package/dist/bin/sync-runner.d.ts +4 -0
  5. package/dist/bin/sync-runner.d.ts.map +1 -1
  6. package/dist/bin/sync-runner.js.map +1 -1
  7. package/dist/bin/sync-runner.test.js +95 -4
  8. package/dist/bin/sync-runner.test.js.map +1 -1
  9. package/dist/index.d.ts +2 -2
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +1 -1
  12. package/dist/index.js.map +1 -1
  13. package/dist/index.test.d.ts +2 -0
  14. package/dist/index.test.d.ts.map +1 -0
  15. package/dist/index.test.js +16 -0
  16. package/dist/index.test.js.map +1 -0
  17. package/dist/operation-lock.d.ts +31 -28
  18. package/dist/operation-lock.d.ts.map +1 -1
  19. package/dist/operation-lock.js +206 -50
  20. package/dist/operation-lock.js.map +1 -1
  21. package/dist/operation-lock.test.js +105 -1
  22. package/dist/operation-lock.test.js.map +1 -1
  23. package/dist/sync/area-resolver.d.ts +66 -0
  24. package/dist/sync/area-resolver.d.ts.map +1 -0
  25. package/dist/sync/area-resolver.js +306 -0
  26. package/dist/sync/area-resolver.js.map +1 -0
  27. package/dist/sync/area-resolver.test.d.ts +2 -0
  28. package/dist/sync/area-resolver.test.d.ts.map +1 -0
  29. package/dist/sync/area-resolver.test.js +211 -0
  30. package/dist/sync/area-resolver.test.js.map +1 -0
  31. package/dist/sync/event-sync.d.ts +5 -1
  32. package/dist/sync/event-sync.d.ts.map +1 -1
  33. package/dist/sync/event-sync.js +3 -0
  34. package/dist/sync/event-sync.js.map +1 -1
  35. package/dist/sync/event-sync.test.js +45 -0
  36. package/dist/sync/event-sync.test.js.map +1 -1
  37. package/dist/sync/index.d.ts +4 -0
  38. package/dist/sync/index.d.ts.map +1 -1
  39. package/dist/sync/index.js +2 -0
  40. package/dist/sync/index.js.map +1 -1
  41. package/dist/sync/parallel-sync-coordinator.d.ts +77 -0
  42. package/dist/sync/parallel-sync-coordinator.d.ts.map +1 -0
  43. package/dist/sync/parallel-sync-coordinator.js +287 -0
  44. package/dist/sync/parallel-sync-coordinator.js.map +1 -0
  45. package/dist/sync/parallel-sync-coordinator.test.d.ts +2 -0
  46. package/dist/sync/parallel-sync-coordinator.test.d.ts.map +1 -0
  47. package/dist/sync/parallel-sync-coordinator.test.js +281 -0
  48. package/dist/sync/parallel-sync-coordinator.test.js.map +1 -0
  49. package/dist/sync/path-leases.d.ts +31 -0
  50. package/dist/sync/path-leases.d.ts.map +1 -0
  51. package/dist/sync/path-leases.js +74 -0
  52. package/dist/sync/path-leases.js.map +1 -0
  53. package/dist/sync/path-leases.test.d.ts +2 -0
  54. package/dist/sync/path-leases.test.d.ts.map +1 -0
  55. package/dist/sync/path-leases.test.js +51 -0
  56. package/dist/sync/path-leases.test.js.map +1 -0
  57. package/dist/sync/state-store.d.ts +7 -0
  58. package/dist/sync/state-store.d.ts.map +1 -1
  59. package/dist/sync/state-store.js +104 -43
  60. package/dist/sync/state-store.js.map +1 -1
  61. package/dist/sync/state-store.test.js +62 -1
  62. package/dist/sync/state-store.test.js.map +1 -1
  63. package/dist/sync/sync-work.d.ts +64 -0
  64. package/dist/sync/sync-work.d.ts.map +1 -0
  65. package/dist/sync/sync-work.js +11 -0
  66. package/dist/sync/sync-work.js.map +1 -0
  67. package/dist/watcher.d.ts +65 -0
  68. package/dist/watcher.d.ts.map +1 -1
  69. package/dist/watcher.js +280 -24
  70. package/dist/watcher.js.map +1 -1
  71. package/dist/watcher.test.js +401 -3
  72. package/dist/watcher.test.js.map +1 -1
  73. package/package.json +1 -1
@@ -0,0 +1,287 @@
1
+ import { assertCanonicalPath, PathLeaseManager, pathsConflict } from "./path-leases.js";
2
+ function identityKey(path) {
3
+ return `${path.targetUid}\u0000${path.areaId}\u0000${path.canonicalPath}`;
4
+ }
5
+ function overlaps(left, right) {
6
+ return left.targetUid === right.targetUid && left.areaId === right.areaId && pathsConflict(left.canonicalPath, right.canonicalPath);
7
+ }
8
+ class SubmissionValidationError extends Error {
9
+ paths;
10
+ constructor(paths, message) {
11
+ super(message);
12
+ this.paths = paths;
13
+ }
14
+ }
15
+ /**
16
+ * Scheduler and fencing authority for semantic sync work. It deliberately owns
17
+ * mailboxes, lease acquisition, path epochs, and adapter selection so callers
18
+ * cannot smuggle in a lane, lock, argv, or worker choice.
19
+ */
20
+ export class DefaultParallelSyncCoordinator {
21
+ options;
22
+ leases = new PathLeaseManager();
23
+ realtimeQueue = [];
24
+ choreQueue = [];
25
+ epochs = [];
26
+ clock;
27
+ identifyPath;
28
+ planChorePaths;
29
+ nextId = 1;
30
+ nextEpoch = 1;
31
+ realtimeRunning;
32
+ choreRunning;
33
+ stopping = false;
34
+ shutdownPromise;
35
+ constructor(options) {
36
+ this.options = options;
37
+ this.clock = options.clock ?? { now: () => Date.now() };
38
+ if (typeof options.identifyPath !== "function")
39
+ throw new Error("parallel sync coordinator requires identifyPath");
40
+ if (typeof options.planChorePaths !== "function")
41
+ throw new Error("parallel sync coordinator requires planChorePaths");
42
+ this.identifyPath = options.identifyPath;
43
+ this.planChorePaths = options.planChorePaths;
44
+ }
45
+ submit(work) {
46
+ if (this.stopping)
47
+ return Promise.resolve(this.retryableOutcome(this.pathsFor(work), "coordinator is shutting down"));
48
+ return new Promise((resolve) => {
49
+ let submission;
50
+ try {
51
+ submission = this.createSubmission(work, resolve);
52
+ }
53
+ catch (error) {
54
+ const message = error instanceof Error ? error.message : String(error);
55
+ const paths = error instanceof SubmissionValidationError ? error.paths : [];
56
+ resolve({
57
+ paths: paths.map((path) => ({ path, epoch: 0, status: "refused", reason: message })),
58
+ error: message,
59
+ });
60
+ return;
61
+ }
62
+ if (this.hasInternallyConflictingPaths(submission.paths)) {
63
+ resolve(this.refusedOutcome(submission.paths, "submission contains internally conflicting paths"));
64
+ return;
65
+ }
66
+ this.registerEpochs(submission);
67
+ if (work.class === "realtime")
68
+ this.preemptForRealtime(submission);
69
+ const queue = work.class === "realtime" ? this.realtimeQueue : this.choreQueue;
70
+ queue.push(submission);
71
+ this.finishIfEmpty(submission);
72
+ this.drain();
73
+ });
74
+ }
75
+ inspect() {
76
+ return {
77
+ realtimeQueued: this.realtimeQueue.filter((submission) => !submission.finished).length,
78
+ choreQueued: this.choreQueue.filter((submission) => !submission.finished).length,
79
+ realtimeRunning: this.realtimeRunning !== undefined,
80
+ choreRunning: this.choreRunning !== undefined,
81
+ leases: this.leases.inspect(),
82
+ now: this.clock.now(),
83
+ };
84
+ }
85
+ shutdown() {
86
+ if (this.shutdownPromise)
87
+ return this.shutdownPromise;
88
+ this.stopping = true;
89
+ for (const submission of [...this.realtimeQueue, ...this.choreQueue]) {
90
+ this.completeRemaining(submission, "retryable", "coordinator is shutting down");
91
+ }
92
+ this.realtimeQueue.length = 0;
93
+ this.choreQueue.length = 0;
94
+ this.realtimeRunning?.controller.abort();
95
+ this.choreRunning?.controller.abort();
96
+ this.shutdownPromise = Promise.allSettled([this.realtimeRunning?.execution, this.choreRunning?.execution]
97
+ .filter((execution) => execution !== undefined)).then(() => undefined);
98
+ return this.shutdownPromise;
99
+ }
100
+ createSubmission(work, resolve) {
101
+ const paths = this.pathsFor(work);
102
+ return {
103
+ id: `sync-${this.nextId++}`,
104
+ work,
105
+ paths,
106
+ results: new Map(),
107
+ resolve,
108
+ controller: new AbortController(),
109
+ running: false,
110
+ finished: false,
111
+ };
112
+ }
113
+ pathsFor(work) {
114
+ const source = work.class === "realtime" ? work.paths : this.planChorePaths(work);
115
+ try {
116
+ for (const canonicalPath of source)
117
+ assertCanonicalPath(canonicalPath);
118
+ }
119
+ catch (error) {
120
+ throw new SubmissionValidationError(source, error instanceof Error ? error.message : String(error));
121
+ }
122
+ const unique = new Map();
123
+ for (const canonicalPath of source) {
124
+ let identity;
125
+ try {
126
+ identity = this.identifyPath(canonicalPath);
127
+ }
128
+ catch (error) {
129
+ throw new SubmissionValidationError(source, error instanceof Error ? error.message : String(error));
130
+ }
131
+ const scheduled = { canonicalPath, ...identity, epoch: this.nextEpoch++ };
132
+ unique.set(identityKey(scheduled), scheduled);
133
+ }
134
+ return [...unique.values()];
135
+ }
136
+ registerEpochs(submission) {
137
+ this.epochs.push(...submission.paths.map((path) => ({ ...path, class: submission.work.class })));
138
+ }
139
+ hasInternallyConflictingPaths(paths) {
140
+ return paths.some((path, index) => paths.slice(index + 1).some((other) => overlaps(path, other)));
141
+ }
142
+ preemptForRealtime(incoming) {
143
+ for (const queued of [...this.realtimeQueue, ...this.choreQueue]) {
144
+ const revoked = queued.paths.filter((path) => incoming.paths.some((candidate) => overlaps(path, candidate)));
145
+ if (revoked.length === 0)
146
+ continue;
147
+ for (const path of revoked)
148
+ this.setResult(queued, path, "refused", "superseded by newer realtime work");
149
+ queued.paths = queued.paths.filter((path) => !revoked.includes(path));
150
+ this.finishIfEmpty(queued);
151
+ }
152
+ for (const running of [this.realtimeRunning, this.choreRunning]) {
153
+ if (running && running.paths.some((path) => incoming.paths.some((candidate) => overlaps(path, candidate)))) {
154
+ running.controller.abort();
155
+ }
156
+ }
157
+ }
158
+ drain() {
159
+ if (this.stopping)
160
+ return;
161
+ if (!this.realtimeRunning)
162
+ this.startNext("realtime");
163
+ if (!this.choreRunning)
164
+ this.startNext("chore");
165
+ }
166
+ startNext(kind) {
167
+ const queue = kind === "realtime" ? this.realtimeQueue : this.choreQueue;
168
+ for (let index = 0; index < queue.length; index += 1) {
169
+ const submission = queue[index];
170
+ if (submission.finished)
171
+ continue;
172
+ const lease = this.leases.tryAcquire(submission.id, this.requestsFor(submission.paths));
173
+ if (!lease)
174
+ continue;
175
+ queue.splice(index, 1);
176
+ submission.lease = lease;
177
+ submission.running = true;
178
+ if (kind === "realtime")
179
+ this.realtimeRunning = submission;
180
+ else
181
+ this.choreRunning = submission;
182
+ submission.execution = this.execute(kind, submission);
183
+ return;
184
+ }
185
+ }
186
+ requestsFor(paths) {
187
+ return paths.map(({ targetUid, areaId, canonicalPath }) => ({ targetUid, areaId, canonicalPath, mode: "mutation" }));
188
+ }
189
+ async execute(kind, submission) {
190
+ const worker = kind === "realtime" ? this.options.realtimeWorker : this.options.choreWorker;
191
+ try {
192
+ const outcome = await worker.execute({
193
+ id: submission.id,
194
+ work: submission.work,
195
+ paths: submission.paths,
196
+ signal: submission.controller.signal,
197
+ });
198
+ this.applyWorkerOutcome(submission, outcome);
199
+ }
200
+ catch (error) {
201
+ this.completeAfterWorkerFailure(submission, error instanceof Error ? error.message : String(error));
202
+ }
203
+ finally {
204
+ submission.lease?.release();
205
+ submission.running = false;
206
+ if (kind === "realtime")
207
+ this.realtimeRunning = undefined;
208
+ else
209
+ this.choreRunning = undefined;
210
+ this.finishIfEmpty(submission);
211
+ this.drain();
212
+ }
213
+ }
214
+ applyWorkerOutcome(submission, outcome) {
215
+ if (this.stopping) {
216
+ this.completeRemaining(submission, "retryable", "coordinator is shutting down");
217
+ return;
218
+ }
219
+ const byPath = new Map(outcome.paths.map((result) => [result.path, result]));
220
+ for (const path of submission.paths) {
221
+ if (this.isStale(path)) {
222
+ this.setResult(submission, path, "refused", "stale path epoch");
223
+ continue;
224
+ }
225
+ const result = byPath.get(path.canonicalPath);
226
+ if (!result || result.epoch !== path.epoch) {
227
+ this.setResult(submission, path, "retryable", outcome.error ?? "worker omitted or mismatched a path outcome");
228
+ continue;
229
+ }
230
+ this.setResult(submission, path, result.status, result.reason);
231
+ }
232
+ }
233
+ isStale(path) {
234
+ return this.epochs.some((intent) => intent.targetUid === path.targetUid &&
235
+ intent.areaId === path.areaId &&
236
+ intent.epoch > path.epoch &&
237
+ pathsConflict(intent.canonicalPath, path.canonicalPath) &&
238
+ intent.class === "realtime");
239
+ }
240
+ completeAfterWorkerFailure(submission, reason) {
241
+ for (const path of submission.paths) {
242
+ if (submission.results.has(identityKey(path)))
243
+ continue;
244
+ if (this.isStale(path))
245
+ this.setResult(submission, path, "refused", "stale path epoch");
246
+ else
247
+ this.setResult(submission, path, "retryable", reason);
248
+ }
249
+ this.finishIfEmpty(submission);
250
+ }
251
+ setResult(submission, path, status, reason) {
252
+ submission.results.set(identityKey(path), { path: path.canonicalPath, status, epoch: path.epoch, ...(reason ? { reason } : {}) });
253
+ }
254
+ completeRemaining(submission, status, reason) {
255
+ for (const path of submission.paths) {
256
+ if (!submission.results.has(identityKey(path)))
257
+ this.setResult(submission, path, status, reason);
258
+ }
259
+ this.finishIfEmpty(submission);
260
+ }
261
+ finishIfEmpty(submission) {
262
+ if (submission.finished || submission.running)
263
+ return;
264
+ if (submission.paths.some((path) => !submission.results.has(identityKey(path))))
265
+ return;
266
+ submission.finished = true;
267
+ submission.resolve({ paths: [...submission.results.values()] });
268
+ this.pruneEpochs();
269
+ }
270
+ pruneEpochs() {
271
+ const livePaths = [
272
+ ...this.realtimeQueue,
273
+ ...this.choreQueue,
274
+ this.realtimeRunning,
275
+ this.choreRunning,
276
+ ].flatMap((submission) => submission && !submission.finished ? submission.paths : []);
277
+ this.epochs = this.epochs.filter((intent) => livePaths.some((path) => identityKey(path) === identityKey(intent) && path.epoch === intent.epoch) ||
278
+ (intent.class === "realtime" && livePaths.some((path) => path.epoch < intent.epoch && overlaps(path, intent))));
279
+ }
280
+ refusedOutcome(paths, reason) {
281
+ return { paths: paths.map((path) => ({ path: path.canonicalPath, epoch: path.epoch, status: "refused", reason })) };
282
+ }
283
+ retryableOutcome(paths, reason) {
284
+ return { paths: paths.map((path) => ({ path: path.canonicalPath, epoch: path.epoch, status: "retryable", reason })) };
285
+ }
286
+ }
287
+ //# sourceMappingURL=parallel-sync-coordinator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parallel-sync-coordinator.js","sourceRoot":"","sources":["../../src/sync/parallel-sync-coordinator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=parallel-sync-coordinator.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parallel-sync-coordinator.test.d.ts","sourceRoot":"","sources":["../../src/sync/parallel-sync-coordinator.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,281 @@
1
+ import { describe, expect, it, vi } from "vitest";
2
+ import { DefaultParallelSyncCoordinator } from "./parallel-sync-coordinator.js";
3
+ import { InlineSyncWorkerAdapter } from "./sync-work.js";
4
+ function realtime(path, causality = path) {
5
+ return { class: "realtime", source: "watcher", direction: "push", paths: [path], causality };
6
+ }
7
+ function chore(kind = "full-reconcile") {
8
+ return { class: "chore", kind, areas: ["root:notes"] };
9
+ }
10
+ function durable(slice) {
11
+ return { paths: slice.paths.map((path) => ({ path: path.canonicalPath, epoch: path.epoch, status: "durable" })) };
12
+ }
13
+ function testIdentity(path) {
14
+ return { targetUid: "test-target", areaId: `root:${path.split("/")[0] ?? "files"}` };
15
+ }
16
+ function deferred() {
17
+ let resolve;
18
+ const promise = new Promise((done) => { resolve = done; });
19
+ return { promise, resolve };
20
+ }
21
+ async function flush() {
22
+ await Promise.resolve();
23
+ await Promise.resolve();
24
+ }
25
+ describe("DefaultParallelSyncCoordinator", () => {
26
+ it("starts realtime while an unrelated chore is indefinitely blocked", async () => {
27
+ vi.useFakeTimers();
28
+ vi.setSystemTime(new Date("2026-08-27T12:00:00.000Z"));
29
+ const starts = [];
30
+ const never = new Promise(() => undefined);
31
+ const coordinator = new DefaultParallelSyncCoordinator({
32
+ identifyPath: testIdentity,
33
+ choreWorker: new InlineSyncWorkerAdapter(async (slice) => {
34
+ starts.push(`chore:${slice.paths[0]?.canonicalPath}`);
35
+ return never;
36
+ }),
37
+ realtimeWorker: new InlineSyncWorkerAdapter(async (slice) => {
38
+ starts.push(`realtime:${slice.paths[0]?.canonicalPath}`);
39
+ return durable(slice);
40
+ }),
41
+ planChorePaths: () => ["slow/report"],
42
+ clock: { now: () => Date.now() },
43
+ });
44
+ void coordinator.submit(chore());
45
+ await flush();
46
+ await expect(coordinator.submit(realtime("fresh/file"))).resolves.toMatchObject({ paths: [{ path: "fresh/file", status: "durable" }] });
47
+ expect(starts).toEqual(["chore:slow/report", "realtime:fresh/file"]);
48
+ expect(coordinator.inspect().now).toBe(Date.parse("2026-08-27T12:00:00.000Z"));
49
+ vi.useRealTimers();
50
+ });
51
+ it("serializes ancestor conflicts and runs realtime immediately after the active chore", async () => {
52
+ const events = [];
53
+ const finishChore = deferred();
54
+ const coordinator = new DefaultParallelSyncCoordinator({
55
+ identifyPath: testIdentity,
56
+ choreWorker: new InlineSyncWorkerAdapter(async (slice) => {
57
+ events.push("chore:start");
58
+ slice.signal.addEventListener("abort", () => events.push("chore:cancel"), { once: true });
59
+ return finishChore.promise;
60
+ }),
61
+ realtimeWorker: new InlineSyncWorkerAdapter(async (slice) => {
62
+ events.push("realtime:start");
63
+ return durable(slice);
64
+ }),
65
+ planChorePaths: () => ["notes/today"],
66
+ });
67
+ const choreOutcome = coordinator.submit(chore());
68
+ await flush();
69
+ const realtimeOutcome = coordinator.submit(realtime("notes"));
70
+ await flush();
71
+ expect(events).toEqual(["chore:start", "chore:cancel"]);
72
+ finishChore.resolve({ paths: [{ path: "notes/today", epoch: 1, status: "durable" }] });
73
+ await expect(realtimeOutcome).resolves.toMatchObject({ paths: [{ path: "notes", status: "durable" }] });
74
+ await expect(choreOutcome).resolves.toMatchObject({ paths: [{ path: "notes/today", status: "refused", reason: "stale path epoch" }] });
75
+ expect(events).toEqual(["chore:start", "chore:cancel", "realtime:start"]);
76
+ });
77
+ it("revokes unstarted chore paths and lets only the newest realtime event commit", async () => {
78
+ const firstRealtime = deferred();
79
+ const starts = [];
80
+ let realtimeCalls = 0;
81
+ const coordinator = new DefaultParallelSyncCoordinator({
82
+ identifyPath: testIdentity,
83
+ choreWorker: new InlineSyncWorkerAdapter(async (slice) => {
84
+ starts.push(`chore:${slice.paths[0]?.canonicalPath}`);
85
+ if (slice.paths[0]?.canonicalPath === "unrelated")
86
+ return new Promise(() => undefined);
87
+ return durable(slice);
88
+ }),
89
+ realtimeWorker: new InlineSyncWorkerAdapter(async (slice) => {
90
+ realtimeCalls += 1;
91
+ starts.push(`realtime:${realtimeCalls}`);
92
+ return realtimeCalls === 1 ? firstRealtime.promise : durable(slice);
93
+ }),
94
+ planChorePaths: (work) => work.kind === "cadence" ? ["unrelated"] : ["notes/today"],
95
+ });
96
+ void coordinator.submit(chore("cadence"));
97
+ await flush();
98
+ const queuedChore = coordinator.submit(chore());
99
+ const older = coordinator.submit(realtime("notes/today", "older"));
100
+ await flush();
101
+ const newest = coordinator.submit(realtime("notes/today", "newest"));
102
+ await flush();
103
+ firstRealtime.resolve({ paths: [{ path: "notes/today", epoch: 2, status: "durable" }] });
104
+ await expect(queuedChore).resolves.toMatchObject({ paths: [{ status: "refused", reason: "superseded by newer realtime work" }] });
105
+ await expect(older).resolves.toMatchObject({ paths: [{ status: "refused", reason: "stale path epoch" }] });
106
+ await expect(newest).resolves.toMatchObject({ paths: [{ status: "durable" }] });
107
+ expect(starts).toEqual(["chore:unrelated", "realtime:1", "realtime:2"]);
108
+ });
109
+ it("returns retryable outcomes and releases leases after worker failure", async () => {
110
+ let calls = 0;
111
+ const coordinator = new DefaultParallelSyncCoordinator({
112
+ identifyPath: testIdentity,
113
+ planChorePaths: () => [],
114
+ choreWorker: new InlineSyncWorkerAdapter(async (slice) => durable(slice)),
115
+ realtimeWorker: new InlineSyncWorkerAdapter(async (slice) => {
116
+ calls += 1;
117
+ if (calls === 1)
118
+ throw new Error("worker lost");
119
+ return durable(slice);
120
+ }),
121
+ });
122
+ await expect(coordinator.submit(realtime("notes/today"))).resolves.toMatchObject({ paths: [{ status: "retryable", reason: "worker lost" }] });
123
+ expect(coordinator.inspect().leases).toEqual([]);
124
+ await expect(coordinator.submit(realtime("notes/today"))).resolves.toMatchObject({ paths: [{ status: "durable" }] });
125
+ });
126
+ it("refuses a worker result that is not fenced by the scheduled path epoch", async () => {
127
+ const coordinator = new DefaultParallelSyncCoordinator({
128
+ identifyPath: testIdentity,
129
+ planChorePaths: () => [],
130
+ choreWorker: new InlineSyncWorkerAdapter(async (slice) => durable(slice)),
131
+ realtimeWorker: new InlineSyncWorkerAdapter(async (slice) => ({
132
+ paths: slice.paths.map((path) => ({ path: path.canonicalPath, epoch: path.epoch + 1, status: "durable" })),
133
+ })),
134
+ });
135
+ await expect(coordinator.submit(realtime("notes/today"))).resolves.toMatchObject({
136
+ paths: [{ status: "retryable", reason: "worker omitted or mismatched a path outcome" }],
137
+ });
138
+ });
139
+ it("waits for the cancellation boundary before shutdown releases an active lease", async () => {
140
+ const finish = deferred();
141
+ let cancelled = false;
142
+ const coordinator = new DefaultParallelSyncCoordinator({
143
+ identifyPath: testIdentity,
144
+ planChorePaths: () => [],
145
+ choreWorker: new InlineSyncWorkerAdapter(async (slice) => durable(slice)),
146
+ realtimeWorker: new InlineSyncWorkerAdapter(async (slice) => {
147
+ slice.signal.addEventListener("abort", () => { cancelled = true; }, { once: true });
148
+ return finish.promise;
149
+ }),
150
+ });
151
+ const outcome = coordinator.submit(realtime("notes/today"));
152
+ await flush();
153
+ let shutdownDone = false;
154
+ const shuttingDown = coordinator.shutdown().then(() => { shutdownDone = true; });
155
+ await flush();
156
+ expect(cancelled).toBe(true);
157
+ expect(shutdownDone).toBe(false);
158
+ expect(coordinator.inspect().leases).toHaveLength(1);
159
+ finish.resolve({ paths: [{ path: "notes/today", epoch: 1, status: "durable" }] });
160
+ await shuttingDown;
161
+ await expect(outcome).resolves.toMatchObject({ paths: [{ status: "retryable", reason: "coordinator is shutting down" }] });
162
+ expect(coordinator.inspect().leases).toEqual([]);
163
+ });
164
+ it("keeps a reserved chore worker making progress under realtime load", async () => {
165
+ const starts = [];
166
+ const coordinator = new DefaultParallelSyncCoordinator({
167
+ identifyPath: testIdentity,
168
+ choreWorker: new InlineSyncWorkerAdapter(async (slice) => {
169
+ starts.push("chore");
170
+ return durable(slice);
171
+ }),
172
+ realtimeWorker: new InlineSyncWorkerAdapter(async (slice) => {
173
+ starts.push(`realtime:${slice.paths[0]?.canonicalPath}`);
174
+ return durable(slice);
175
+ }),
176
+ planChorePaths: () => ["chores/progress"],
177
+ });
178
+ const choreOutcome = coordinator.submit(chore());
179
+ const realtimeOutcomes = Array.from({ length: 20 }, (_, index) => coordinator.submit(realtime(`events/${index}`)));
180
+ await expect(choreOutcome).resolves.toMatchObject({ paths: [{ status: "durable" }] });
181
+ await Promise.all(realtimeOutcomes);
182
+ expect(starts).toContain("chore");
183
+ });
184
+ it("requires real ownership resolution and a chore planner", () => {
185
+ const worker = new InlineSyncWorkerAdapter(async (slice) => durable(slice));
186
+ expect(() => new DefaultParallelSyncCoordinator({ realtimeWorker: worker, choreWorker: worker })).toThrow("requires identifyPath");
187
+ expect(() => new DefaultParallelSyncCoordinator({
188
+ realtimeWorker: worker,
189
+ choreWorker: worker,
190
+ identifyPath: testIdentity,
191
+ })).toThrow("requires planChorePaths");
192
+ });
193
+ it("refuses malformed paths before they can block later work", async () => {
194
+ const calls = [];
195
+ const coordinator = new DefaultParallelSyncCoordinator({
196
+ identifyPath: testIdentity,
197
+ planChorePaths: () => [],
198
+ choreWorker: new InlineSyncWorkerAdapter(async (slice) => durable(slice)),
199
+ realtimeWorker: new InlineSyncWorkerAdapter(async (slice) => {
200
+ calls.push(slice.paths[0].canonicalPath);
201
+ return durable(slice);
202
+ }),
203
+ });
204
+ await expect(coordinator.submit(realtime("/notes"))).resolves.toMatchObject({
205
+ paths: [{ path: "/notes", status: "refused" }],
206
+ });
207
+ await expect(coordinator.submit(realtime("notes/today"))).resolves.toMatchObject({
208
+ paths: [{ path: "notes/today", status: "durable" }],
209
+ });
210
+ expect(calls).toEqual(["notes/today"]);
211
+ });
212
+ it("refuses internally conflicting batches instead of leaving them queued", async () => {
213
+ const worker = vi.fn(async (slice) => durable(slice));
214
+ const coordinator = new DefaultParallelSyncCoordinator({
215
+ identifyPath: testIdentity,
216
+ planChorePaths: () => [],
217
+ choreWorker: new InlineSyncWorkerAdapter(worker),
218
+ realtimeWorker: new InlineSyncWorkerAdapter(worker),
219
+ });
220
+ await expect(coordinator.submit({ ...realtime("notes"), paths: ["notes", "notes/today"] })).resolves.toMatchObject({
221
+ paths: [
222
+ { path: "notes", status: "refused" },
223
+ { path: "notes/today", status: "refused" },
224
+ ],
225
+ });
226
+ expect(worker).not.toHaveBeenCalled();
227
+ expect(coordinator.inspect().realtimeQueued).toBe(0);
228
+ });
229
+ it("refuses a cancelled stale mutation when its worker rejects", async () => {
230
+ const cancelled = deferred();
231
+ const coordinator = new DefaultParallelSyncCoordinator({
232
+ identifyPath: testIdentity,
233
+ planChorePaths: () => ["notes/today"],
234
+ choreWorker: new InlineSyncWorkerAdapter(async (slice) => {
235
+ slice.signal.addEventListener("abort", () => cancelled.resolve(undefined), { once: true });
236
+ await cancelled.promise;
237
+ throw new Error("worker cancelled");
238
+ }),
239
+ realtimeWorker: new InlineSyncWorkerAdapter(async (slice) => durable(slice)),
240
+ });
241
+ const stale = coordinator.submit(chore());
242
+ await flush();
243
+ const latest = coordinator.submit(realtime("notes/today"));
244
+ await expect(latest).resolves.toMatchObject({ paths: [{ status: "durable" }] });
245
+ await expect(stale).resolves.toMatchObject({ paths: [{ status: "refused", reason: "stale path epoch" }] });
246
+ });
247
+ it("returns the same shutdown drain to concurrent callers", async () => {
248
+ const finish = deferred();
249
+ const coordinator = new DefaultParallelSyncCoordinator({
250
+ identifyPath: testIdentity,
251
+ planChorePaths: () => [],
252
+ choreWorker: new InlineSyncWorkerAdapter(async (slice) => durable(slice)),
253
+ realtimeWorker: new InlineSyncWorkerAdapter(async () => finish.promise),
254
+ });
255
+ void coordinator.submit(realtime("notes/today"));
256
+ await flush();
257
+ const first = coordinator.shutdown();
258
+ const second = coordinator.shutdown();
259
+ expect(second).toBe(first);
260
+ finish.resolve({ paths: [] });
261
+ await expect(Promise.all([first, second])).resolves.toEqual([undefined, undefined]);
262
+ });
263
+ it("compacts completed epoch history while retaining a newer realtime fence", async () => {
264
+ const finishChore = deferred();
265
+ const coordinator = new DefaultParallelSyncCoordinator({
266
+ identifyPath: testIdentity,
267
+ planChorePaths: () => ["notes/today"],
268
+ choreWorker: new InlineSyncWorkerAdapter(async () => finishChore.promise),
269
+ realtimeWorker: new InlineSyncWorkerAdapter(async (slice) => durable(slice)),
270
+ });
271
+ const choreOutcome = coordinator.submit(chore());
272
+ await flush();
273
+ const realtimeOutcome = coordinator.submit(realtime("notes/today"));
274
+ expect(coordinator.epochs).toHaveLength(2);
275
+ finishChore.resolve({ paths: [{ path: "notes/today", epoch: 1, status: "durable" }] });
276
+ await expect(realtimeOutcome).resolves.toMatchObject({ paths: [{ status: "durable" }] });
277
+ await expect(choreOutcome).resolves.toMatchObject({ paths: [{ status: "refused" }] });
278
+ expect(coordinator.epochs).toEqual([]);
279
+ });
280
+ });
281
+ //# sourceMappingURL=parallel-sync-coordinator.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parallel-sync-coordinator.test.js","sourceRoot":"","sources":["../../src/sync/parallel-sync-coordinator.test.ts"],"names":[],"mappings":"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"}