@indigoai-us/hq-cloud 6.15.79 → 6.15.81
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/area-ledger-migration.d.ts +13 -0
- package/dist/bin/area-ledger-migration.d.ts.map +1 -0
- package/dist/bin/area-ledger-migration.js +64 -0
- package/dist/bin/area-ledger-migration.js.map +1 -0
- package/dist/bin/area-ledger-migration.test.d.ts +2 -0
- package/dist/bin/area-ledger-migration.test.d.ts.map +1 -0
- package/dist/bin/area-ledger-migration.test.js +55 -0
- package/dist/bin/area-ledger-migration.test.js.map +1 -0
- package/dist/bin/sync-runner-company.d.ts +6 -0
- package/dist/bin/sync-runner-company.d.ts.map +1 -1
- package/dist/bin/sync-runner-company.js +21 -0
- package/dist/bin/sync-runner-company.js.map +1 -1
- package/dist/bin/sync-runner-company.test.js +112 -0
- package/dist/bin/sync-runner-company.test.js.map +1 -1
- package/dist/bin/sync-runner-events.test.js +20 -0
- package/dist/bin/sync-runner-events.test.js.map +1 -1
- package/dist/bin/sync-runner-watch-loop.d.ts +7 -0
- package/dist/bin/sync-runner-watch-loop.d.ts.map +1 -1
- package/dist/bin/sync-runner-watch-loop.js +308 -20
- package/dist/bin/sync-runner-watch-loop.js.map +1 -1
- package/dist/bin/sync-runner.d.ts +5 -0
- package/dist/bin/sync-runner.d.ts.map +1 -1
- package/dist/bin/sync-runner.js.map +1 -1
- package/dist/bin/sync-runner.test.js +144 -1
- package/dist/bin/sync-runner.test.js.map +1 -1
- package/dist/cli/share.d.ts +8 -0
- package/dist/cli/share.d.ts.map +1 -1
- package/dist/cli/share.js +213 -15
- package/dist/cli/share.js.map +1 -1
- package/dist/cli/share.test.js +461 -31
- package/dist/cli/share.test.js.map +1 -1
- package/dist/cli/sync.d.ts +30 -0
- package/dist/cli/sync.d.ts.map +1 -1
- package/dist/cli/sync.js +83 -8
- package/dist/cli/sync.js.map +1 -1
- package/dist/cli/sync.test.js +224 -0
- package/dist/cli/sync.test.js.map +1 -1
- package/dist/cli/watch-event-push-conflict.test.js +22 -11
- package/dist/cli/watch-event-push-conflict.test.js.map +1 -1
- package/dist/journal-store.test.js +42 -1
- package/dist/journal-store.test.js.map +1 -1
- package/dist/journal.d.ts +12 -1
- package/dist/journal.d.ts.map +1 -1
- package/dist/journal.js +103 -6
- package/dist/journal.js.map +1 -1
- package/dist/s3.d.ts +62 -0
- package/dist/s3.d.ts.map +1 -1
- package/dist/s3.js +91 -1
- package/dist/s3.js.map +1 -1
- package/dist/s3.rename-retry.test.d.ts +2 -0
- package/dist/s3.rename-retry.test.d.ts.map +1 -0
- package/dist/s3.rename-retry.test.js +153 -0
- package/dist/s3.rename-retry.test.js.map +1 -0
- package/dist/sync/area-ledger-migration.d.ts +116 -0
- package/dist/sync/area-ledger-migration.d.ts.map +1 -0
- package/dist/sync/area-ledger-migration.js +505 -0
- package/dist/sync/area-ledger-migration.js.map +1 -0
- package/dist/sync/area-ledger-migration.test.d.ts +2 -0
- package/dist/sync/area-ledger-migration.test.d.ts.map +1 -0
- package/dist/sync/area-ledger-migration.test.js +274 -0
- package/dist/sync/area-ledger-migration.test.js.map +1 -0
- package/dist/sync/feature-flags.d.ts +9 -0
- package/dist/sync/feature-flags.d.ts.map +1 -1
- package/dist/sync/feature-flags.js +19 -0
- package/dist/sync/feature-flags.js.map +1 -1
- package/dist/sync/feature-flags.test.js +11 -1
- package/dist/sync/feature-flags.test.js.map +1 -1
- package/dist/sync/index.d.ts +2 -0
- package/dist/sync/index.d.ts.map +1 -1
- package/dist/sync/index.js +1 -0
- package/dist/sync/index.js.map +1 -1
- package/dist/sync/parallel-sync-coordinator.d.ts.map +1 -1
- package/dist/sync/parallel-sync-coordinator.js +19 -4
- package/dist/sync/parallel-sync-coordinator.js.map +1 -1
- package/dist/sync/parallel-sync-coordinator.test.js +59 -0
- package/dist/sync/parallel-sync-coordinator.test.js.map +1 -1
- package/dist/sync/reconcile-cursor.d.ts +97 -0
- package/dist/sync/reconcile-cursor.d.ts.map +1 -0
- package/dist/sync/reconcile-cursor.js +215 -0
- package/dist/sync/reconcile-cursor.js.map +1 -0
- package/dist/sync/reconcile-cursor.test.d.ts +2 -0
- package/dist/sync/reconcile-cursor.test.d.ts.map +1 -0
- package/dist/sync/reconcile-cursor.test.js +139 -0
- package/dist/sync/reconcile-cursor.test.js.map +1 -0
- package/dist/sync/state-store.d.ts +37 -0
- package/dist/sync/state-store.d.ts.map +1 -1
- package/dist/sync/state-store.js +109 -1
- package/dist/sync/state-store.js.map +1 -1
- package/dist/sync/sync-work.d.ts +2 -1
- package/dist/sync/sync-work.d.ts.map +1 -1
- package/dist/sync/sync-work.js.map +1 -1
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/vault-client.d.ts +9 -2
- package/dist/vault-client.d.ts.map +1 -1
- package/dist/vault-client.js +3 -2
- package/dist/vault-client.js.map +1 -1
- package/dist/vault-client.test.js +26 -0
- package/dist/vault-client.test.js.map +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as os from "node:os";
|
|
3
|
+
import * as path from "node:path";
|
|
4
|
+
import { afterEach, describe, expect, it } from "vitest";
|
|
5
|
+
import { ReconcileCursorStore, checkpointReconcileApply, takeBoundedReconcileSlice, } from "./reconcile-cursor.js";
|
|
6
|
+
const roots = [];
|
|
7
|
+
afterEach(() => {
|
|
8
|
+
for (const root of roots.splice(0))
|
|
9
|
+
fs.rmSync(root, { recursive: true, force: true });
|
|
10
|
+
});
|
|
11
|
+
function root() {
|
|
12
|
+
const value = fs.mkdtempSync(path.join(os.tmpdir(), "hq-reconcile-cursor-test-"));
|
|
13
|
+
roots.push(value);
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
function cursor(phase, overrides = {}) {
|
|
17
|
+
return { routerVersion: 1, epoch: "epoch-1", areaId: "root:notes", phase, ...overrides };
|
|
18
|
+
}
|
|
19
|
+
function open(dir) {
|
|
20
|
+
return ReconcileCursorStore.open({ rootDir: dir, journalSlug: "personal", layoutEpoch: 1, areaId: "root:notes" });
|
|
21
|
+
}
|
|
22
|
+
describe("ReconcileCursorStore", () => {
|
|
23
|
+
it("resumes each discovery phase and does not revisit a completed area", () => {
|
|
24
|
+
const dir = root();
|
|
25
|
+
const first = open(dir);
|
|
26
|
+
first.checkpointDiscovery(cursor("local-discovery", { localDirectoryStack: ["notes"], localAfterPath: "notes/a.md" }));
|
|
27
|
+
expect(open(dir).read().cursor).toMatchObject({ phase: "local-discovery", localAfterPath: "notes/a.md" });
|
|
28
|
+
open(dir).checkpointDiscovery(cursor("remote-list", { remotePrefix: "notes/", remoteContinuation: "page-2" }));
|
|
29
|
+
expect(open(dir).read().cursor).toMatchObject({ phase: "remote-list", remoteContinuation: "page-2" });
|
|
30
|
+
open(dir).checkpointDiscovery(cursor("diff", { journalAfterKey: "notes/a.md", remoteHighWater: "etag-9" }));
|
|
31
|
+
expect(open(dir).read().cursor).toMatchObject({ phase: "diff", journalAfterKey: "notes/a.md" });
|
|
32
|
+
open(dir).complete("epoch-1");
|
|
33
|
+
expect(open(dir).read()).toEqual({ format: 1, completedEpoch: "epoch-1" });
|
|
34
|
+
});
|
|
35
|
+
it("only advances apply after each delete/tombstone outcome is durable", () => {
|
|
36
|
+
const dir = root();
|
|
37
|
+
const store = open(dir);
|
|
38
|
+
expect(() => store.checkpointApply(cursor("apply", { journalAfterKey: "notes/deleted.md" }), [
|
|
39
|
+
{ path: "notes/deleted.md", durable: false },
|
|
40
|
+
])).toThrow("before every path outcome is durable");
|
|
41
|
+
expect(store.read().cursor).toBeUndefined();
|
|
42
|
+
store.checkpointApply(cursor("apply", { journalAfterKey: "notes/deleted.md" }), [
|
|
43
|
+
{ path: "notes/deleted.md", durable: true },
|
|
44
|
+
{ path: "notes/tombstone.md", durable: true },
|
|
45
|
+
]);
|
|
46
|
+
expect(open(dir).read().cursor).toMatchObject({ phase: "apply", journalAfterKey: "notes/deleted.md" });
|
|
47
|
+
});
|
|
48
|
+
it("advances an entrypoint apply cursor only after the caller reports durable paths", () => {
|
|
49
|
+
const dir = root();
|
|
50
|
+
const store = open(dir);
|
|
51
|
+
checkpointReconcileApply({ store, cursor: cursor("apply", { journalAfterKey: "notes/tombstone.md" }) }, ["notes/upload.md", "notes/tombstone.md"]);
|
|
52
|
+
expect(open(dir).read().cursor).toMatchObject({ phase: "apply", journalAfterKey: "notes/tombstone.md" });
|
|
53
|
+
});
|
|
54
|
+
it("invalidates a remote continuation when a later inventory epoch supersedes it", () => {
|
|
55
|
+
const dir = root();
|
|
56
|
+
const store = open(dir);
|
|
57
|
+
store.checkpointDiscovery(cursor("remote-list", { remotePrefix: "notes/", remoteContinuation: "page-8", remoteHighWater: "old" }));
|
|
58
|
+
expect(store.invalidateRemoteContinuation("epoch-1", "new")).toMatchObject({
|
|
59
|
+
phase: "remote-list",
|
|
60
|
+
remoteHighWater: "new",
|
|
61
|
+
});
|
|
62
|
+
const resumed = open(dir).read().cursor;
|
|
63
|
+
expect(resumed).not.toHaveProperty("remoteContinuation");
|
|
64
|
+
expect(resumed.remoteHighWater).toBe("new");
|
|
65
|
+
});
|
|
66
|
+
it("keeps cursor state isolated per area", () => {
|
|
67
|
+
const dir = root();
|
|
68
|
+
const alpha = ReconcileCursorStore.open({ rootDir: dir, journalSlug: "personal", layoutEpoch: 1, areaId: "root:alpha" });
|
|
69
|
+
const beta = ReconcileCursorStore.open({ rootDir: dir, journalSlug: "personal", layoutEpoch: 1, areaId: "root:beta" });
|
|
70
|
+
alpha.checkpointDiscovery({ routerVersion: 1, epoch: "one", areaId: "root:alpha", phase: "diff" });
|
|
71
|
+
expect(beta.read().cursor).toBeUndefined();
|
|
72
|
+
});
|
|
73
|
+
it("ignores stale checkpoints and completion records from an older epoch", () => {
|
|
74
|
+
const dir = root();
|
|
75
|
+
const current = open(dir);
|
|
76
|
+
const stale = open(dir);
|
|
77
|
+
current.checkpointDiscovery(cursor("diff"));
|
|
78
|
+
current.complete("epoch-1");
|
|
79
|
+
current.checkpointDiscovery({ ...cursor("diff"), epoch: "epoch-2" });
|
|
80
|
+
stale.checkpointDiscovery(cursor("remote-list", { remoteContinuation: "late" }));
|
|
81
|
+
stale.complete("epoch-1");
|
|
82
|
+
expect(open(dir).read()).toMatchObject({
|
|
83
|
+
cursor: { epoch: "epoch-2", phase: "diff" },
|
|
84
|
+
});
|
|
85
|
+
current.complete("epoch-2");
|
|
86
|
+
expect(open(dir).read()).toEqual({ format: 1, completedEpoch: "epoch-2" });
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
describe("takeBoundedReconcileSlice", () => {
|
|
90
|
+
it("yields by count, bytes, and wall-clock without materializing the inventory", () => {
|
|
91
|
+
function* inventory() {
|
|
92
|
+
for (let index = 0; index < 562_000; index += 1)
|
|
93
|
+
yield { path: `notes/${index}.md`, bytes: 1 };
|
|
94
|
+
}
|
|
95
|
+
const largeInventoryResult = takeBoundedReconcileSlice(inventory(), { maxEntries: 512 });
|
|
96
|
+
expect(largeInventoryResult.entries).toHaveLength(512);
|
|
97
|
+
expect(largeInventoryResult).toMatchObject({ bytes: 512, yielded: true });
|
|
98
|
+
expect(takeBoundedReconcileSlice([{ path: "one", bytes: 8 }, { path: "two", bytes: 8 }], { maxBytes: 10 })).toMatchObject({ entries: [{ path: "one", bytes: 8 }], bytes: 8, yielded: true });
|
|
99
|
+
let time = 0;
|
|
100
|
+
const result = takeBoundedReconcileSlice([{ path: "one", bytes: 1 }, { path: "two", bytes: 1 }], {
|
|
101
|
+
maxWallClockMs: 50,
|
|
102
|
+
now: () => (time += 50),
|
|
103
|
+
});
|
|
104
|
+
expect(result).toMatchObject({ entries: [{ path: "one", bytes: 1 }], yielded: true });
|
|
105
|
+
});
|
|
106
|
+
it("checks cancellation between every file and returns the completed prefix", () => {
|
|
107
|
+
let checks = 0;
|
|
108
|
+
const result = takeBoundedReconcileSlice([
|
|
109
|
+
{ path: "notes/one", bytes: 1 },
|
|
110
|
+
{ path: "notes/two", bytes: 1 },
|
|
111
|
+
], { isCancelled: () => ++checks === 2 });
|
|
112
|
+
expect(result).toEqual({
|
|
113
|
+
entries: [{ path: "notes/one", bytes: 1 }],
|
|
114
|
+
bytes: 1,
|
|
115
|
+
yielded: true,
|
|
116
|
+
cancelled: true,
|
|
117
|
+
deferred: { path: "notes/two", bytes: 1 },
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
it("retains a generator remainder after yielding a bounded slice", () => {
|
|
121
|
+
function* inventory() {
|
|
122
|
+
yield { path: "notes/one", bytes: 1 };
|
|
123
|
+
yield { path: "notes/two", bytes: 1 };
|
|
124
|
+
yield { path: "notes/three", bytes: 1 };
|
|
125
|
+
}
|
|
126
|
+
const source = inventory();
|
|
127
|
+
const first = takeBoundedReconcileSlice(source, { maxEntries: 1 });
|
|
128
|
+
expect(first.deferred).toEqual({ path: "notes/two", bytes: 1 });
|
|
129
|
+
function* resumed() {
|
|
130
|
+
yield first.deferred;
|
|
131
|
+
yield* source;
|
|
132
|
+
}
|
|
133
|
+
expect(takeBoundedReconcileSlice(resumed(), { maxEntries: 10 }).entries).toEqual([
|
|
134
|
+
{ path: "notes/two", bytes: 1 },
|
|
135
|
+
{ path: "notes/three", bytes: 1 },
|
|
136
|
+
]);
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
//# sourceMappingURL=reconcile-cursor.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reconcile-cursor.test.js","sourceRoot":"","sources":["../../src/sync/reconcile-cursor.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -80,6 +80,30 @@ export interface StateStoreRecoveryStats {
|
|
|
80
80
|
/** Largest single snapshot payload or WAL frame buffered during recovery. */
|
|
81
81
|
maxReadBytes: number;
|
|
82
82
|
}
|
|
83
|
+
/** A stable identity for one complete snapshot/WAL generation. */
|
|
84
|
+
export interface StateStoreGenerationIdentity {
|
|
85
|
+
generation: number;
|
|
86
|
+
lastRecordSequence: number;
|
|
87
|
+
walBytes: number;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* A durable lease on an immutable source generation.
|
|
91
|
+
*
|
|
92
|
+
* Rotation normally keeps only a short rollback history. Migration uses this
|
|
93
|
+
* lease to make an older source generation part of that history until the
|
|
94
|
+
* copy/catch-up transaction has finished (or has explicitly been abandoned).
|
|
95
|
+
*/
|
|
96
|
+
export interface StateStoreGenerationPin {
|
|
97
|
+
readonly identity: StateStoreGenerationIdentity;
|
|
98
|
+
/** Durable pin file, persisted by long-running migration control state. */
|
|
99
|
+
readonly path: string;
|
|
100
|
+
release(): void;
|
|
101
|
+
}
|
|
102
|
+
/** One bounded value yielded from a keyed state projection. */
|
|
103
|
+
export interface StateStoreStateEntry {
|
|
104
|
+
key: string;
|
|
105
|
+
value: unknown;
|
|
106
|
+
}
|
|
83
107
|
export interface StateStoreRepairResult {
|
|
84
108
|
recoveredGeneration: number;
|
|
85
109
|
recoveredWalBytes: number;
|
|
@@ -153,6 +177,19 @@ export declare class StateStore<T> {
|
|
|
153
177
|
getGeneration(): number;
|
|
154
178
|
getLastRecordSequence(): number;
|
|
155
179
|
getRecoveryStats(): StateStoreRecoveryStats;
|
|
180
|
+
getGenerationIdentity(): StateStoreGenerationIdentity;
|
|
181
|
+
/**
|
|
182
|
+
* Persist a generation pin while holding append.lock. The pin is a tiny
|
|
183
|
+
* checksummed file in the store directory, so a concurrent compactor sees it
|
|
184
|
+
* before deciding which immutable generations may be pruned.
|
|
185
|
+
*/
|
|
186
|
+
pinCurrentGeneration(): StateStoreGenerationPin;
|
|
187
|
+
/**
|
|
188
|
+
* Iterate a keyed projection without exposing its mutable backing object.
|
|
189
|
+
* Each yielded row is cloned independently, allowing migration clients to
|
|
190
|
+
* keep projected WAL records bounded even when the source journal is huge.
|
|
191
|
+
*/
|
|
192
|
+
iterateStateEntries(path: readonly string[]): IterableIterator<StateStoreStateEntry>;
|
|
156
193
|
append(type: number, payload: unknown, flags?: number): StateStoreAppendResult;
|
|
157
194
|
/**
|
|
158
195
|
* Async lock acquisition for callback-originated work. The write itself
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state-store.d.ts","sourceRoot":"","sources":["../../src/sync/state-store.ts"],"names":[],"mappings":"AAoEA,wBAAgB,2CAA2C,IAAI,IAAI,CAElE;AAED,wBAAgB,yCAAyC,IAAI,MAAM,CAElE;AAED,wBAAgB,kDAAkD,IAAI,IAAI,CAEzE;AAED,wBAAgB,gDAAgD,IAAI,MAAM,CAEzE;AAED,wBAAgB,yCAAyC,IAAI,IAAI,CAEhE;AAED,wBAAgB,uCAAuC,IAAI,MAAM,CAEhE;AAED,6EAA6E;AAC7E,wBAAgB,qCAAqC,CAAC,IAAI,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,GAAG,IAAI,CAE1F;AAED,kFAAkF;AAClF,wBAAgB,oCAAoC,CAAC,IAAI,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,GAAG,IAAI,CAEzF;AAED,2EAA2E;AAC3E,wBAAgB,+BAA+B,CAAC,IAAI,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,GAAG,IAAI,CAEpF;AAED,oFAAoF;AACpF,wBAAgB,4CAA4C,CAAC,IAAI,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,GAAG,IAAI,CAEjG;AAED,0EAA0E;AAC1E,wBAAgB,mCAAmC,CAAC,IAAI,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,GAAG,IAAI,CAExF;AAED,2DAA2D;AAC3D,wBAAgB,mCAAmC,CACjD,KAAK,EAAE,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC,GAAG,SAAS,GAC3G,IAAI,CAEN;AAED,4DAA4D;AAC5D,wBAAgB,0CAA0C,CAAC,IAAI,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,GAAG,IAAI,CAE/F;AAED,sFAAsF;AACtF,wBAAgB,yCAAyC,CACvD,IAAI,EAAE,CAAC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,GAC7C,IAAI,CAEN;AAED,6EAA6E;AAC7E,wBAAgB,sCAAsC,CAAC,IAAI,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,GAAG,IAAI,CAE3F;AAED,qFAAqF;AACrF,wBAAgB,oCAAoC,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAExF;AAED,4FAA4F;AAC5F,wBAAgB,mCAAmC,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAEvF;AAED,MAAM,WAAW,gBAAgB,CAAC,CAAC,GAAG,OAAO;IAC3C,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,CAAC,CAAC;CACZ;AAED,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,CAAC,CAAC;IAChB,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,gBAAgB,KAAK,CAAC,CAAC;IAClD;;;;OAIG;IACH,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,gBAAgB,KAAK,IAAI,CAAC;IACpD,4DAA4D;IAC5D,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,gFAAgF;IAChF,2BAA2B,CAAC,EAAE,MAAM,CAAC;CACtC;AAED,MAAM,WAAW,uBAAuB;IACtC,iEAAiE;IACjE,OAAO,EAAE,gBAAgB,EAAE,CAAC;IAC5B,4EAA4E;IAC5E,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,sBAAuB,SAAQ,gBAAgB;IAC9D,OAAO,EAAE,uBAAuB,CAAC;CAClC;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,qBAAqB,CAAC,CAAC;IACtC,sEAAsE;IACtE,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,uBAAuB;IACtC,oEAAoE;IACpE,QAAQ,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,sBAAsB;IACrC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,sBAAsB,EAAE,MAAM,CAAC;IAC/B,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,0BAA0B;IACzC,uEAAuE;IACvE,SAAS,EAAE,MAAM,CAAC;IAClB,mDAAmD;IACnD,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,2BAA2B,GACnC;IAAE,MAAM,EAAE,SAAS,GAAG,YAAY,CAAA;CAAE,GACpC,CAAC;IAAE,MAAM,EAAE,UAAU,CAAA;CAAE,GAAG,sBAAsB,CAAC,CAAC;AAEtD,MAAM,WAAW,4BAA4B;IAC3C,yEAAyE;IACzE,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,uEAAuE;IACvE,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,0BAA0B,KAAK,IAAI,CAAC;CAC1D;AAiCD,qBAAa,yBAA0B,SAAQ,KAAK;gBACtC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY;CAIpD;AAED,MAAM,MAAM,yBAAyB,GAAG,yBAAyB,CAAC;AAElE,qBAAa,mBAAoB,SAAQ,KAAK;IAC5C,QAAQ,CAAC,MAAM,CAAC,EAAE,yBAAyB,CAAC;gBAEhC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG;QAAE,MAAM,CAAC,EAAE,yBAAyB,CAAA;KAAE;CAK7F;AAYD,+DAA+D;AAC/D,qBAAa,UAAU,CAAC,CAAC;IAarB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAZ1B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,KAAK,CAAI;IACjB,OAAO,CAAC,kBAAkB,CAAS;IACnC,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,oBAAoB,CAAS;IACrC,OAAO,CAAC,iCAAiC,CAAS;IAElD,OAAO;IAiBP,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO;IAUxD,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC;IA+B5D,uEAAuE;WAC1D,SAAS,CAAC,CAAC,EAAE,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IA+BhF;;;;;;;;;OASG;IACH,MAAM,CAAC,WAAW,CAAC,CAAC,EAAE,OAAO,EAAE,SAAS,qBAAqB,CAAC,CAAC,CAAC,EAAE,GAAG,sBAAsB,EAAE;IA2D7F;;;;;OAKG;IACH,MAAM,CAAC,cAAc,CAAC,CAAC,EACrB,OAAO,EAAE,iBAAiB,CAAC,CAAC,CAAC,EAC7B,WAAW,GAAE,4BAAiC,GAC7C,2BAA2B;IAqG9B,QAAQ,IAAI,CAAC;IAIb,aAAa,IAAI,MAAM;IAIvB,qBAAqB,IAAI,MAAM;IAI/B,gBAAgB,IAAI,uBAAuB;IAI3C,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,SAAI,GAAG,sBAAsB;IA4BzE;;;;OAIG;IACG,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,SAAI,GAAG,OAAO,CAAC,sBAAsB,CAAC;IA4B7F,iEAAiE;IAC3D,aAAa,CACjB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,MAAM,OAAO,EAC3B,KAAK,SAAI,GACR,OAAO,CAAC,sBAAsB,GAAG,SAAS,CAAC;IA6B9C,sEAAsE;IACtE,OAAO,IAAI,uBAAuB;IAUlC,6DAA6D;IACvD,YAAY,IAAI,OAAO,CAAC,uBAAuB,CAAC;IAUtD,OAAO,CAAC,cAAc;IAiCtB;;;;;;;;OAQG;IACH,YAAY,CAAC,SAAS,EAAE,CAAC,GAAG,IAAI;IAIhC;;;;;;;OAOG;IACH,gBAAgB,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,IAAI;IASlD,OAAO,CAAC,mBAAmB;IAgE3B,uEAAuE;IACvE,OAAO,IAAI,IAAI;IAmBf,OAAO,CAAC,eAAe;IA+BvB,OAAO,CAAC,kCAAkC;YAU5B,uCAAuC;IAUrD,OAAO,CAAC,eAAe;IAKvB,OAAO,CAAC,cAAc;IAqBtB,gFAAgF;IAChF,OAAO,CAAC,qBAAqB;IAsB7B,OAAO,CAAC,iBAAiB;CAS1B"}
|
|
1
|
+
{"version":3,"file":"state-store.d.ts","sourceRoot":"","sources":["../../src/sync/state-store.ts"],"names":[],"mappings":"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"}
|
package/dist/sync/state-store.js
CHANGED
|
@@ -434,6 +434,70 @@ export class StateStore {
|
|
|
434
434
|
getRecoveryStats() {
|
|
435
435
|
return { walBytes: this.walBytes, maxReadBytes: this.maxRecoveryReadBytes };
|
|
436
436
|
}
|
|
437
|
+
getGenerationIdentity() {
|
|
438
|
+
return {
|
|
439
|
+
generation: this.generation,
|
|
440
|
+
lastRecordSequence: this.lastRecordSequence,
|
|
441
|
+
walBytes: this.walBytes,
|
|
442
|
+
};
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Persist a generation pin while holding append.lock. The pin is a tiny
|
|
446
|
+
* checksummed file in the store directory, so a concurrent compactor sees it
|
|
447
|
+
* before deciding which immutable generations may be pruned.
|
|
448
|
+
*/
|
|
449
|
+
pinCurrentGeneration() {
|
|
450
|
+
while (true) {
|
|
451
|
+
const pin = withScopeLock(this.stateDir, () => {
|
|
452
|
+
const refresh = this.refreshFromDisk();
|
|
453
|
+
if (!refresh)
|
|
454
|
+
return undefined;
|
|
455
|
+
const identity = this.getGenerationIdentity();
|
|
456
|
+
const pinPath = writeGenerationPin(this.stateDir, this.scopeDigest, identity);
|
|
457
|
+
let released = false;
|
|
458
|
+
return {
|
|
459
|
+
identity,
|
|
460
|
+
path: pinPath,
|
|
461
|
+
release: () => {
|
|
462
|
+
if (released)
|
|
463
|
+
return;
|
|
464
|
+
released = true;
|
|
465
|
+
try {
|
|
466
|
+
fs.unlinkSync(pinPath);
|
|
467
|
+
fsyncDirectory(this.stateDir);
|
|
468
|
+
}
|
|
469
|
+
catch (error) {
|
|
470
|
+
if (!isMissing(error))
|
|
471
|
+
throw new Error(`state-store: cannot release generation pin ${pinPath}`, { cause: error });
|
|
472
|
+
}
|
|
473
|
+
},
|
|
474
|
+
};
|
|
475
|
+
});
|
|
476
|
+
if (pin)
|
|
477
|
+
return pin;
|
|
478
|
+
this.recoverNewestGenerationOutsideLock();
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Iterate a keyed projection without exposing its mutable backing object.
|
|
483
|
+
* Each yielded row is cloned independently, allowing migration clients to
|
|
484
|
+
* keep projected WAL records bounded even when the source journal is huge.
|
|
485
|
+
*/
|
|
486
|
+
*iterateStateEntries(path) {
|
|
487
|
+
let current = this.state;
|
|
488
|
+
for (const segment of path) {
|
|
489
|
+
if (typeof current !== "object" || current === null || Array.isArray(current) || !Object.hasOwn(current, segment)) {
|
|
490
|
+
throw new Error(`state-store: state path ${JSON.stringify(path)} is not an object map`);
|
|
491
|
+
}
|
|
492
|
+
current = current[segment];
|
|
493
|
+
}
|
|
494
|
+
if (typeof current !== "object" || current === null || Array.isArray(current)) {
|
|
495
|
+
throw new Error(`state-store: state path ${JSON.stringify(path)} is not an object map`);
|
|
496
|
+
}
|
|
497
|
+
for (const [key, value] of Object.entries(current)) {
|
|
498
|
+
yield { key, value: structuredClone(value) };
|
|
499
|
+
}
|
|
500
|
+
}
|
|
437
501
|
append(type, payload, flags = 0) {
|
|
438
502
|
assertUint16(type, "record type");
|
|
439
503
|
assertUint16(flags, "record flags");
|
|
@@ -2172,7 +2236,7 @@ function retainedGenerationHistoryNeedsRepair(dir, newestGeneration, currentGene
|
|
|
2172
2236
|
return false;
|
|
2173
2237
|
}
|
|
2174
2238
|
function pruneGenerations(dir, retain) {
|
|
2175
|
-
const retained = new Set(retain);
|
|
2239
|
+
const retained = new Set([...retain, ...pinnedGenerations(dir)]);
|
|
2176
2240
|
for (const name of fs.readdirSync(dir)) {
|
|
2177
2241
|
const match = /^(?:snapshot|wal)-(\d+)\.bin$/.exec(name);
|
|
2178
2242
|
if (!match)
|
|
@@ -2189,6 +2253,50 @@ function pruneGenerations(dir, retain) {
|
|
|
2189
2253
|
}
|
|
2190
2254
|
fsyncDirectory(dir);
|
|
2191
2255
|
}
|
|
2256
|
+
function writeGenerationPin(dir, scopeDigest, identity) {
|
|
2257
|
+
const body = {
|
|
2258
|
+
generation: identity.generation,
|
|
2259
|
+
lastRecordSequence: identity.lastRecordSequence,
|
|
2260
|
+
walBytes: identity.walBytes,
|
|
2261
|
+
scopeDigest: scopeDigest.toString("hex"),
|
|
2262
|
+
};
|
|
2263
|
+
const checksum = sha256(Buffer.from(canonicalJson(body), "utf8")).toString("hex");
|
|
2264
|
+
const pinPath = path.join(dir, `generation-pin-${process.pid}-${crypto.randomBytes(8).toString("hex")}.json`);
|
|
2265
|
+
writeNewDurably(pinPath, Buffer.from(`${canonicalJson({ ...body, checksum })}\n`, "utf8"));
|
|
2266
|
+
fsyncDirectory(dir);
|
|
2267
|
+
return pinPath;
|
|
2268
|
+
}
|
|
2269
|
+
/** Invalid pins are retained conservatively: pruning is never allowed to win a crash race. */
|
|
2270
|
+
function pinnedGenerations(dir) {
|
|
2271
|
+
const pins = new Set();
|
|
2272
|
+
for (const name of fs.readdirSync(dir)) {
|
|
2273
|
+
if (!/^generation-pin-[A-Za-z0-9-]+\.json$/.test(name))
|
|
2274
|
+
continue;
|
|
2275
|
+
try {
|
|
2276
|
+
const raw = JSON.parse(fs.readFileSync(path.join(dir, name), "utf8"));
|
|
2277
|
+
const { checksum, ...body } = raw;
|
|
2278
|
+
if (typeof checksum !== "string" ||
|
|
2279
|
+
checksum !== sha256(Buffer.from(canonicalJson(body), "utf8")).toString("hex") ||
|
|
2280
|
+
!Number.isSafeInteger(body.generation) ||
|
|
2281
|
+
body.generation < 1) {
|
|
2282
|
+
// A torn pin represents an in-flight migration; retain every local
|
|
2283
|
+
// generation rather than guessing which source it meant to protect.
|
|
2284
|
+
return fs.readdirSync(dir)
|
|
2285
|
+
.map((candidate) => /^(?:snapshot|wal)-(\d+)\.bin$/.exec(candidate)?.[1])
|
|
2286
|
+
.filter((value) => value !== undefined)
|
|
2287
|
+
.map(Number);
|
|
2288
|
+
}
|
|
2289
|
+
pins.add(body.generation);
|
|
2290
|
+
}
|
|
2291
|
+
catch {
|
|
2292
|
+
return fs.readdirSync(dir)
|
|
2293
|
+
.map((candidate) => /^(?:snapshot|wal)-(\d+)\.bin$/.exec(candidate)?.[1])
|
|
2294
|
+
.filter((value) => value !== undefined)
|
|
2295
|
+
.map(Number);
|
|
2296
|
+
}
|
|
2297
|
+
}
|
|
2298
|
+
return [...pins];
|
|
2299
|
+
}
|
|
2192
2300
|
function cleanupUnpublishedInitialGeneration(dir) {
|
|
2193
2301
|
if (fs.existsSync(path.join(dir, "current")))
|
|
2194
2302
|
return;
|