@indigoai-us/hq-cloud 6.15.76 → 6.15.78
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-worker.d.ts +3 -0
- package/dist/bin/sync-runner-worker.d.ts.map +1 -0
- package/dist/bin/sync-runner-worker.js +88 -0
- package/dist/bin/sync-runner-worker.js.map +1 -0
- package/dist/bin/sync-runner.d.ts +3 -1
- package/dist/bin/sync-runner.d.ts.map +1 -1
- package/dist/bin/sync-runner.js +31 -13
- package/dist/bin/sync-runner.js.map +1 -1
- package/dist/bin/sync-runner.test.js +117 -1
- package/dist/bin/sync-runner.test.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.test.d.ts +2 -0
- package/dist/index.test.d.ts.map +1 -0
- package/dist/index.test.js +16 -0
- package/dist/index.test.js.map +1 -0
- package/dist/operation-lock.d.ts +31 -28
- package/dist/operation-lock.d.ts.map +1 -1
- package/dist/operation-lock.js +206 -50
- package/dist/operation-lock.js.map +1 -1
- package/dist/operation-lock.test.js +105 -1
- package/dist/operation-lock.test.js.map +1 -1
- package/dist/sync/area-resolver.d.ts +66 -0
- package/dist/sync/area-resolver.d.ts.map +1 -0
- package/dist/sync/area-resolver.js +306 -0
- package/dist/sync/area-resolver.js.map +1 -0
- package/dist/sync/area-resolver.test.d.ts +2 -0
- package/dist/sync/area-resolver.test.d.ts.map +1 -0
- package/dist/sync/area-resolver.test.js +211 -0
- package/dist/sync/area-resolver.test.js.map +1 -0
- package/dist/sync/child-process-sync-worker.d.ts +53 -0
- package/dist/sync/child-process-sync-worker.d.ts.map +1 -0
- package/dist/sync/child-process-sync-worker.js +256 -0
- package/dist/sync/child-process-sync-worker.js.map +1 -0
- package/dist/sync/child-process-sync-worker.test.d.ts +2 -0
- package/dist/sync/child-process-sync-worker.test.d.ts.map +1 -0
- package/dist/sync/child-process-sync-worker.test.js +262 -0
- package/dist/sync/child-process-sync-worker.test.js.map +1 -0
- package/dist/sync/index.d.ts +8 -0
- package/dist/sync/index.d.ts.map +1 -1
- package/dist/sync/index.js +4 -0
- package/dist/sync/index.js.map +1 -1
- package/dist/sync/parallel-sync-coordinator.d.ts +77 -0
- package/dist/sync/parallel-sync-coordinator.d.ts.map +1 -0
- package/dist/sync/parallel-sync-coordinator.js +292 -0
- package/dist/sync/parallel-sync-coordinator.js.map +1 -0
- package/dist/sync/parallel-sync-coordinator.test.d.ts +2 -0
- package/dist/sync/parallel-sync-coordinator.test.d.ts.map +1 -0
- package/dist/sync/parallel-sync-coordinator.test.js +303 -0
- package/dist/sync/parallel-sync-coordinator.test.js.map +1 -0
- package/dist/sync/path-leases.d.ts +31 -0
- package/dist/sync/path-leases.d.ts.map +1 -0
- package/dist/sync/path-leases.js +74 -0
- package/dist/sync/path-leases.js.map +1 -0
- package/dist/sync/path-leases.test.d.ts +2 -0
- package/dist/sync/path-leases.test.d.ts.map +1 -0
- package/dist/sync/path-leases.test.js +51 -0
- package/dist/sync/path-leases.test.js.map +1 -0
- package/dist/sync/state-store.d.ts +13 -0
- package/dist/sync/state-store.d.ts.map +1 -1
- package/dist/sync/state-store.js +158 -51
- package/dist/sync/state-store.js.map +1 -1
- package/dist/sync/state-store.test.js +148 -2
- package/dist/sync/state-store.test.js.map +1 -1
- package/dist/sync/sync-work.d.ts +66 -0
- package/dist/sync/sync-work.d.ts.map +1 -0
- package/dist/sync/sync-work.js +11 -0
- package/dist/sync/sync-work.js.map +1 -0
- package/dist/sync/sync-worker-port.d.ts +59 -0
- package/dist/sync/sync-worker-port.d.ts.map +1 -0
- package/dist/sync/sync-worker-port.js +67 -0
- package/dist/sync/sync-worker-port.js.map +1 -0
- package/dist/watcher.d.ts +6 -0
- package/dist/watcher.d.ts.map +1 -1
- package/dist/watcher.js +94 -9
- package/dist/watcher.js.map +1 -1
- package/dist/watcher.test.js +90 -0
- package/dist/watcher.test.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,303 @@
|
|
|
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("initiates worker shutdown before awaiting an execution that only exits when terminated", async () => {
|
|
165
|
+
let rejectExecution;
|
|
166
|
+
const execution = new Promise((_resolve, reject) => { rejectExecution = reject; });
|
|
167
|
+
const shutdown = vi.fn(async () => { rejectExecution(new Error("worker terminated")); });
|
|
168
|
+
const worker = { execute: vi.fn(async () => execution), shutdown };
|
|
169
|
+
const coordinator = new DefaultParallelSyncCoordinator({
|
|
170
|
+
identifyPath: testIdentity,
|
|
171
|
+
planChorePaths: () => [],
|
|
172
|
+
realtimeWorker: worker,
|
|
173
|
+
choreWorker: worker,
|
|
174
|
+
});
|
|
175
|
+
const outcome = coordinator.submit(realtime("notes/hung"));
|
|
176
|
+
await flush();
|
|
177
|
+
const completed = coordinator.shutdown().then(() => "shutdown-complete");
|
|
178
|
+
await expect(Promise.race([
|
|
179
|
+
completed,
|
|
180
|
+
new Promise((resolve) => setTimeout(() => resolve("timed-out"), 100)),
|
|
181
|
+
])).resolves.toBe("shutdown-complete");
|
|
182
|
+
expect(shutdown).toHaveBeenCalledTimes(1);
|
|
183
|
+
await expect(outcome).resolves.toMatchObject({ paths: [{ status: "retryable", reason: "worker terminated" }] });
|
|
184
|
+
expect(coordinator.inspect().leases).toEqual([]);
|
|
185
|
+
});
|
|
186
|
+
it("keeps a reserved chore worker making progress under realtime load", async () => {
|
|
187
|
+
const starts = [];
|
|
188
|
+
const coordinator = new DefaultParallelSyncCoordinator({
|
|
189
|
+
identifyPath: testIdentity,
|
|
190
|
+
choreWorker: new InlineSyncWorkerAdapter(async (slice) => {
|
|
191
|
+
starts.push("chore");
|
|
192
|
+
return durable(slice);
|
|
193
|
+
}),
|
|
194
|
+
realtimeWorker: new InlineSyncWorkerAdapter(async (slice) => {
|
|
195
|
+
starts.push(`realtime:${slice.paths[0]?.canonicalPath}`);
|
|
196
|
+
return durable(slice);
|
|
197
|
+
}),
|
|
198
|
+
planChorePaths: () => ["chores/progress"],
|
|
199
|
+
});
|
|
200
|
+
const choreOutcome = coordinator.submit(chore());
|
|
201
|
+
const realtimeOutcomes = Array.from({ length: 20 }, (_, index) => coordinator.submit(realtime(`events/${index}`)));
|
|
202
|
+
await expect(choreOutcome).resolves.toMatchObject({ paths: [{ status: "durable" }] });
|
|
203
|
+
await Promise.all(realtimeOutcomes);
|
|
204
|
+
expect(starts).toContain("chore");
|
|
205
|
+
});
|
|
206
|
+
it("requires real ownership resolution and a chore planner", () => {
|
|
207
|
+
const worker = new InlineSyncWorkerAdapter(async (slice) => durable(slice));
|
|
208
|
+
expect(() => new DefaultParallelSyncCoordinator({ realtimeWorker: worker, choreWorker: worker })).toThrow("requires identifyPath");
|
|
209
|
+
expect(() => new DefaultParallelSyncCoordinator({
|
|
210
|
+
realtimeWorker: worker,
|
|
211
|
+
choreWorker: worker,
|
|
212
|
+
identifyPath: testIdentity,
|
|
213
|
+
})).toThrow("requires planChorePaths");
|
|
214
|
+
});
|
|
215
|
+
it("refuses malformed paths before they can block later work", async () => {
|
|
216
|
+
const calls = [];
|
|
217
|
+
const coordinator = new DefaultParallelSyncCoordinator({
|
|
218
|
+
identifyPath: testIdentity,
|
|
219
|
+
planChorePaths: () => [],
|
|
220
|
+
choreWorker: new InlineSyncWorkerAdapter(async (slice) => durable(slice)),
|
|
221
|
+
realtimeWorker: new InlineSyncWorkerAdapter(async (slice) => {
|
|
222
|
+
calls.push(slice.paths[0].canonicalPath);
|
|
223
|
+
return durable(slice);
|
|
224
|
+
}),
|
|
225
|
+
});
|
|
226
|
+
await expect(coordinator.submit(realtime("/notes"))).resolves.toMatchObject({
|
|
227
|
+
paths: [{ path: "/notes", status: "refused" }],
|
|
228
|
+
});
|
|
229
|
+
await expect(coordinator.submit(realtime("notes/today"))).resolves.toMatchObject({
|
|
230
|
+
paths: [{ path: "notes/today", status: "durable" }],
|
|
231
|
+
});
|
|
232
|
+
expect(calls).toEqual(["notes/today"]);
|
|
233
|
+
});
|
|
234
|
+
it("refuses internally conflicting batches instead of leaving them queued", async () => {
|
|
235
|
+
const worker = vi.fn(async (slice) => durable(slice));
|
|
236
|
+
const coordinator = new DefaultParallelSyncCoordinator({
|
|
237
|
+
identifyPath: testIdentity,
|
|
238
|
+
planChorePaths: () => [],
|
|
239
|
+
choreWorker: new InlineSyncWorkerAdapter(worker),
|
|
240
|
+
realtimeWorker: new InlineSyncWorkerAdapter(worker),
|
|
241
|
+
});
|
|
242
|
+
await expect(coordinator.submit({ ...realtime("notes"), paths: ["notes", "notes/today"] })).resolves.toMatchObject({
|
|
243
|
+
paths: [
|
|
244
|
+
{ path: "notes", status: "refused" },
|
|
245
|
+
{ path: "notes/today", status: "refused" },
|
|
246
|
+
],
|
|
247
|
+
});
|
|
248
|
+
expect(worker).not.toHaveBeenCalled();
|
|
249
|
+
expect(coordinator.inspect().realtimeQueued).toBe(0);
|
|
250
|
+
});
|
|
251
|
+
it("refuses a cancelled stale mutation when its worker rejects", async () => {
|
|
252
|
+
const cancelled = deferred();
|
|
253
|
+
const coordinator = new DefaultParallelSyncCoordinator({
|
|
254
|
+
identifyPath: testIdentity,
|
|
255
|
+
planChorePaths: () => ["notes/today"],
|
|
256
|
+
choreWorker: new InlineSyncWorkerAdapter(async (slice) => {
|
|
257
|
+
slice.signal.addEventListener("abort", () => cancelled.resolve(undefined), { once: true });
|
|
258
|
+
await cancelled.promise;
|
|
259
|
+
throw new Error("worker cancelled");
|
|
260
|
+
}),
|
|
261
|
+
realtimeWorker: new InlineSyncWorkerAdapter(async (slice) => durable(slice)),
|
|
262
|
+
});
|
|
263
|
+
const stale = coordinator.submit(chore());
|
|
264
|
+
await flush();
|
|
265
|
+
const latest = coordinator.submit(realtime("notes/today"));
|
|
266
|
+
await expect(latest).resolves.toMatchObject({ paths: [{ status: "durable" }] });
|
|
267
|
+
await expect(stale).resolves.toMatchObject({ paths: [{ status: "refused", reason: "stale path epoch" }] });
|
|
268
|
+
});
|
|
269
|
+
it("returns the same shutdown drain to concurrent callers", async () => {
|
|
270
|
+
const finish = deferred();
|
|
271
|
+
const coordinator = new DefaultParallelSyncCoordinator({
|
|
272
|
+
identifyPath: testIdentity,
|
|
273
|
+
planChorePaths: () => [],
|
|
274
|
+
choreWorker: new InlineSyncWorkerAdapter(async (slice) => durable(slice)),
|
|
275
|
+
realtimeWorker: new InlineSyncWorkerAdapter(async () => finish.promise),
|
|
276
|
+
});
|
|
277
|
+
void coordinator.submit(realtime("notes/today"));
|
|
278
|
+
await flush();
|
|
279
|
+
const first = coordinator.shutdown();
|
|
280
|
+
const second = coordinator.shutdown();
|
|
281
|
+
expect(second).toBe(first);
|
|
282
|
+
finish.resolve({ paths: [] });
|
|
283
|
+
await expect(Promise.all([first, second])).resolves.toEqual([undefined, undefined]);
|
|
284
|
+
});
|
|
285
|
+
it("compacts completed epoch history while retaining a newer realtime fence", async () => {
|
|
286
|
+
const finishChore = deferred();
|
|
287
|
+
const coordinator = new DefaultParallelSyncCoordinator({
|
|
288
|
+
identifyPath: testIdentity,
|
|
289
|
+
planChorePaths: () => ["notes/today"],
|
|
290
|
+
choreWorker: new InlineSyncWorkerAdapter(async () => finishChore.promise),
|
|
291
|
+
realtimeWorker: new InlineSyncWorkerAdapter(async (slice) => durable(slice)),
|
|
292
|
+
});
|
|
293
|
+
const choreOutcome = coordinator.submit(chore());
|
|
294
|
+
await flush();
|
|
295
|
+
const realtimeOutcome = coordinator.submit(realtime("notes/today"));
|
|
296
|
+
expect(coordinator.epochs).toHaveLength(2);
|
|
297
|
+
finishChore.resolve({ paths: [{ path: "notes/today", epoch: 1, status: "durable" }] });
|
|
298
|
+
await expect(realtimeOutcome).resolves.toMatchObject({ paths: [{ status: "durable" }] });
|
|
299
|
+
await expect(choreOutcome).resolves.toMatchObject({ paths: [{ status: "refused" }] });
|
|
300
|
+
expect(coordinator.epochs).toEqual([]);
|
|
301
|
+
});
|
|
302
|
+
});
|
|
303
|
+
//# 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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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { AreaId, CanonicalPath } from "./sync-work.js";
|
|
2
|
+
export type PathLeaseRequest = {
|
|
3
|
+
targetUid: string;
|
|
4
|
+
areaId: AreaId;
|
|
5
|
+
canonicalPath: CanonicalPath;
|
|
6
|
+
mode: "mutation";
|
|
7
|
+
};
|
|
8
|
+
export type PathLeaseSnapshot = PathLeaseRequest & {
|
|
9
|
+
owner: string;
|
|
10
|
+
};
|
|
11
|
+
export declare function assertCanonicalPath(path: CanonicalPath): void;
|
|
12
|
+
export declare function pathsConflict(left: CanonicalPath, right: CanonicalPath): boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Parent-owned mutation claims. Acquisition is intentionally synchronous and
|
|
15
|
+
* all-or-none: callers either own every path in a slice or none of them.
|
|
16
|
+
*/
|
|
17
|
+
export declare class PathLeaseManager {
|
|
18
|
+
private readonly held;
|
|
19
|
+
private nextLeaseId;
|
|
20
|
+
tryAcquire(owner: string, requested: readonly PathLeaseRequest[]): PathLease | undefined;
|
|
21
|
+
inspect(): readonly PathLeaseSnapshot[];
|
|
22
|
+
release(ids: readonly string[]): void;
|
|
23
|
+
}
|
|
24
|
+
export declare class PathLease {
|
|
25
|
+
private readonly manager;
|
|
26
|
+
private readonly ids;
|
|
27
|
+
private released;
|
|
28
|
+
constructor(manager: PathLeaseManager, ids: readonly string[]);
|
|
29
|
+
release(): void;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=path-leases.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-leases.d.ts","sourceRoot":"","sources":["../../src/sync/path-leases.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE5D,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,aAAa,CAAC;IAC7B,IAAI,EAAE,UAAU,CAAC;CAClB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,gBAAgB,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAErE,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,CAU7D;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAEhF;AAeD;;;GAGG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAwC;IAC7D,OAAO,CAAC,WAAW,CAAK;IAExB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,gBAAgB,EAAE,GAAG,SAAS,GAAG,SAAS;IAyBxF,OAAO,IAAI,SAAS,iBAAiB,EAAE;IAIvC,OAAO,CAAC,GAAG,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI;CAGtC;AAED,qBAAa,SAAS;IAIlB,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,GAAG;IAJtB,OAAO,CAAC,QAAQ,CAAS;gBAGN,OAAO,EAAE,gBAAgB,EACzB,GAAG,EAAE,SAAS,MAAM,EAAE;IAGzC,OAAO,IAAI,IAAI;CAKhB"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
export function assertCanonicalPath(path) {
|
|
2
|
+
if (path.length === 0 ||
|
|
3
|
+
path.startsWith("/") ||
|
|
4
|
+
path.endsWith("/") ||
|
|
5
|
+
path.includes("\\") ||
|
|
6
|
+
path.split("/").some((part) => part.length === 0 || part === "." || part === "..")) {
|
|
7
|
+
throw new Error(`path lease requires a canonical relative path: ${path}`);
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
export function pathsConflict(left, right) {
|
|
11
|
+
return left === right || left.startsWith(`${right}/`) || right.startsWith(`${left}/`);
|
|
12
|
+
}
|
|
13
|
+
function sameResource(left, right) {
|
|
14
|
+
return left.targetUid === right.targetUid && left.areaId === right.areaId;
|
|
15
|
+
}
|
|
16
|
+
function compareRequests(left, right) {
|
|
17
|
+
return (left.targetUid.localeCompare(right.targetUid) ||
|
|
18
|
+
left.areaId.localeCompare(right.areaId) ||
|
|
19
|
+
left.canonicalPath.localeCompare(right.canonicalPath) ||
|
|
20
|
+
left.mode.localeCompare(right.mode));
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Parent-owned mutation claims. Acquisition is intentionally synchronous and
|
|
24
|
+
* all-or-none: callers either own every path in a slice or none of them.
|
|
25
|
+
*/
|
|
26
|
+
export class PathLeaseManager {
|
|
27
|
+
held = new Map();
|
|
28
|
+
nextLeaseId = 1;
|
|
29
|
+
tryAcquire(owner, requested) {
|
|
30
|
+
if (owner.length === 0)
|
|
31
|
+
throw new Error("path lease owner is required");
|
|
32
|
+
const normalized = [...requested].sort(compareRequests);
|
|
33
|
+
for (const request of normalized)
|
|
34
|
+
assertCanonicalPath(request.canonicalPath);
|
|
35
|
+
const all = [...this.held.values()];
|
|
36
|
+
for (let index = 0; index < normalized.length; index += 1) {
|
|
37
|
+
const request = normalized[index];
|
|
38
|
+
if (all.some((lease) => sameResource(lease, request) && pathsConflict(lease.canonicalPath, request.canonicalPath)) ||
|
|
39
|
+
normalized.slice(0, index).some((other) => sameResource(other, request) && pathsConflict(other.canonicalPath, request.canonicalPath))) {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
const ids = [];
|
|
44
|
+
for (const request of normalized) {
|
|
45
|
+
const id = `${this.nextLeaseId++}`;
|
|
46
|
+
this.held.set(id, { ...request, owner });
|
|
47
|
+
ids.push(id);
|
|
48
|
+
}
|
|
49
|
+
return new PathLease(this, ids);
|
|
50
|
+
}
|
|
51
|
+
inspect() {
|
|
52
|
+
return [...this.held.values()].sort((left, right) => compareRequests(left, right));
|
|
53
|
+
}
|
|
54
|
+
release(ids) {
|
|
55
|
+
for (const id of ids)
|
|
56
|
+
this.held.delete(id);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
export class PathLease {
|
|
60
|
+
manager;
|
|
61
|
+
ids;
|
|
62
|
+
released = false;
|
|
63
|
+
constructor(manager, ids) {
|
|
64
|
+
this.manager = manager;
|
|
65
|
+
this.ids = ids;
|
|
66
|
+
}
|
|
67
|
+
release() {
|
|
68
|
+
if (this.released)
|
|
69
|
+
return;
|
|
70
|
+
this.released = true;
|
|
71
|
+
this.manager.release(this.ids);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=path-leases.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-leases.js","sourceRoot":"","sources":["../../src/sync/path-leases.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-leases.test.d.ts","sourceRoot":"","sources":["../../src/sync/path-leases.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import { PathLeaseManager, pathsConflict } from "./path-leases.js";
|
|
3
|
+
const request = (canonicalPath) => ({
|
|
4
|
+
targetUid: "personal",
|
|
5
|
+
areaId: "root:notes",
|
|
6
|
+
canonicalPath,
|
|
7
|
+
mode: "mutation",
|
|
8
|
+
});
|
|
9
|
+
describe("PathLeaseManager", () => {
|
|
10
|
+
it("acquires all paths atomically in deterministic order", () => {
|
|
11
|
+
const leases = new PathLeaseManager();
|
|
12
|
+
const first = leases.tryAcquire("first", [request("notes/b"), request("notes/a")]);
|
|
13
|
+
expect(first).toBeDefined();
|
|
14
|
+
expect(leases.inspect().map((entry) => entry.canonicalPath)).toEqual(["notes/a", "notes/b"]);
|
|
15
|
+
expect(leases.tryAcquire("second", [request("elsewhere"), request("notes/a/today")])).toBeUndefined();
|
|
16
|
+
expect(leases.inspect().map((entry) => entry.canonicalPath)).toEqual(["notes/a", "notes/b"]);
|
|
17
|
+
first?.release();
|
|
18
|
+
expect(leases.tryAcquire("second", [request("elsewhere"), request("notes/a/today")])).toBeDefined();
|
|
19
|
+
const empty = new PathLeaseManager();
|
|
20
|
+
expect(empty.tryAcquire("invalid-slice", [request("folder"), request("folder/child")])).toBeUndefined();
|
|
21
|
+
expect(empty.inspect()).toEqual([]);
|
|
22
|
+
});
|
|
23
|
+
it("uses exact ancestor-prefix semantics", () => {
|
|
24
|
+
expect(pathsConflict("a", "a")).toBe(true);
|
|
25
|
+
expect(pathsConflict("a", "a/b")).toBe(true);
|
|
26
|
+
expect(pathsConflict("a/b", "a")).toBe(true);
|
|
27
|
+
expect(pathsConflict("a", "ab")).toBe(false);
|
|
28
|
+
});
|
|
29
|
+
it("matches a randomized prefix model", () => {
|
|
30
|
+
let seed = 0x51c0ffee;
|
|
31
|
+
const next = () => {
|
|
32
|
+
seed = (seed * 1_664_525 + 1_013_904_223) >>> 0;
|
|
33
|
+
return seed;
|
|
34
|
+
};
|
|
35
|
+
const segment = () => String.fromCharCode(97 + (next() % 5));
|
|
36
|
+
const makePath = () => Array.from({ length: 1 + (next() % 4) }, segment).join("/");
|
|
37
|
+
for (let trial = 0; trial < 100; trial += 1) {
|
|
38
|
+
const manager = new PathLeaseManager();
|
|
39
|
+
const held = [];
|
|
40
|
+
for (let attempt = 0; attempt < 30; attempt += 1) {
|
|
41
|
+
const path = makePath();
|
|
42
|
+
const expected = !held.some((other) => pathsConflict(path, other));
|
|
43
|
+
const lease = manager.tryAcquire(`owner-${trial}-${attempt}`, [request(path)]);
|
|
44
|
+
expect(lease !== undefined).toBe(expected);
|
|
45
|
+
if (lease)
|
|
46
|
+
held.push(path);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
//# sourceMappingURL=path-leases.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-leases.test.js","sourceRoot":"","sources":["../../src/sync/path-leases.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -18,6 +18,12 @@ export declare function setStateStoreReflinkCopyHookForTest(hook: (() => void) |
|
|
|
18
18
|
export declare function setStateStorePositionalWriteForTest(write: ((fd: number, bytes: Buffer, offset: number, length: number, position: number) => number) | undefined): void;
|
|
19
19
|
/** Test-only seam for rotation-claim PID write failures. */
|
|
20
20
|
export declare function setStateStoreRotationClaimWriteHookForTest(hook: (() => void) | undefined): void;
|
|
21
|
+
/** Test-only seam for proving same-process async lock waiters queue cooperatively. */
|
|
22
|
+
export declare function setStateStoreScopeLockAcquiredHookForTest(hook: (() => void | Promise<void>) | undefined): void;
|
|
23
|
+
/** Test-only seam for exercising async lock deadlines without a minute-long wait. */
|
|
24
|
+
export declare function setStateStoreAsyncLockTimeoutForTest(timeoutMs: number | undefined): void;
|
|
25
|
+
/** Test-only seam for exercising synchronous lock contention without a five-second wait. */
|
|
26
|
+
export declare function setStateStoreSyncLockTimeoutForTest(timeoutMs: number | undefined): void;
|
|
21
27
|
export interface StateStoreRecord<T = unknown> {
|
|
22
28
|
sequence: number;
|
|
23
29
|
type: number;
|
|
@@ -81,6 +87,13 @@ export interface StateStoreMaintenanceOptions {
|
|
|
81
87
|
export declare class StateStoreCorruptionError extends Error {
|
|
82
88
|
constructor(message: string, options?: ErrorOptions);
|
|
83
89
|
}
|
|
90
|
+
export type StateStoreLockErrorReason = "in-process-async-holder";
|
|
91
|
+
export declare class StateStoreLockError extends Error {
|
|
92
|
+
readonly reason?: StateStoreLockErrorReason;
|
|
93
|
+
constructor(message: string, options?: ErrorOptions & {
|
|
94
|
+
reason?: StateStoreLockErrorReason;
|
|
95
|
+
});
|
|
96
|
+
}
|
|
84
97
|
/** A recovered v3 store. `append` is the ordinary hot path. */
|
|
85
98
|
export declare class StateStore<T> {
|
|
86
99
|
private readonly options;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state-store.d.ts","sourceRoot":"","sources":["../../src/sync/state-store.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"state-store.d.ts","sourceRoot":"","sources":["../../src/sync/state-store.ts"],"names":[],"mappings":"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"}
|