@indigoai-us/hq-cloud 6.16.65 → 6.16.67
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-company.d.ts +14 -0
- package/dist/bin/sync-runner-company.d.ts.map +1 -1
- package/dist/bin/sync-runner-company.js +42 -8
- package/dist/bin/sync-runner-company.js.map +1 -1
- package/dist/bin/sync-runner-company.test.js +62 -7
- package/dist/bin/sync-runner-company.test.js.map +1 -1
- package/dist/bin/sync-runner-planning.d.ts +12 -3
- package/dist/bin/sync-runner-planning.d.ts.map +1 -1
- package/dist/bin/sync-runner-planning.js +65 -3
- package/dist/bin/sync-runner-planning.js.map +1 -1
- package/dist/bin/sync-runner-planning.test.js +172 -1
- package/dist/bin/sync-runner-planning.test.js.map +1 -1
- package/dist/bin/sync-runner-watch-loop.d.ts +51 -2
- package/dist/bin/sync-runner-watch-loop.d.ts.map +1 -1
- package/dist/bin/sync-runner-watch-loop.js +409 -165
- package/dist/bin/sync-runner-watch-loop.js.map +1 -1
- package/dist/bin/sync-runner-watch-routes.d.ts +19 -2
- package/dist/bin/sync-runner-watch-routes.d.ts.map +1 -1
- package/dist/bin/sync-runner-watch-routes.js +40 -5
- package/dist/bin/sync-runner-watch-routes.js.map +1 -1
- package/dist/bin/sync-runner-watch-routes.test.js +47 -0
- package/dist/bin/sync-runner-watch-routes.test.js.map +1 -1
- package/dist/bin/sync-runner.d.ts +59 -5
- package/dist/bin/sync-runner.d.ts.map +1 -1
- package/dist/bin/sync-runner.js +48 -4
- package/dist/bin/sync-runner.js.map +1 -1
- package/dist/bin/sync-runner.test.js +1553 -192
- package/dist/bin/sync-runner.test.js.map +1 -1
- package/dist/cli/onepass-pull-planner-regressions.test.d.ts +2 -0
- package/dist/cli/onepass-pull-planner-regressions.test.d.ts.map +1 -0
- package/dist/cli/onepass-pull-planner-regressions.test.js +300 -0
- package/dist/cli/onepass-pull-planner-regressions.test.js.map +1 -0
- package/dist/cli/onepass-pull-planner.test.d.ts +2 -0
- package/dist/cli/onepass-pull-planner.test.d.ts.map +1 -0
- package/dist/cli/onepass-pull-planner.test.js +266 -0
- package/dist/cli/onepass-pull-planner.test.js.map +1 -0
- package/dist/cli/push-scan-exclusions.test.js +4 -4
- package/dist/cli/push-scan-exclusions.test.js.map +1 -1
- package/dist/cli/share.d.ts +31 -1
- package/dist/cli/share.d.ts.map +1 -1
- package/dist/cli/share.js +143 -8
- package/dist/cli/share.js.map +1 -1
- package/dist/cli/share.test.js +350 -5
- package/dist/cli/share.test.js.map +1 -1
- package/dist/cli/streaming-pull-planner.bench.test.d.ts +15 -0
- package/dist/cli/streaming-pull-planner.bench.test.d.ts.map +1 -0
- package/dist/cli/streaming-pull-planner.bench.test.js +273 -0
- package/dist/cli/streaming-pull-planner.bench.test.js.map +1 -0
- package/dist/cli/sync-scope.test.js +8 -0
- package/dist/cli/sync-scope.test.js.map +1 -1
- package/dist/cli/sync.d.ts +12 -0
- package/dist/cli/sync.d.ts.map +1 -1
- package/dist/cli/sync.js +297 -125
- package/dist/cli/sync.js.map +1 -1
- package/dist/cli/sync.test.js +255 -2
- package/dist/cli/sync.test.js.map +1 -1
- package/dist/journal-row-store.d.ts +40 -5
- package/dist/journal-row-store.d.ts.map +1 -1
- package/dist/journal-row-store.js +240 -21
- package/dist/journal-row-store.js.map +1 -1
- package/dist/journal-row-store.test.js +54 -0
- package/dist/journal-row-store.test.js.map +1 -1
- package/dist/journal-snapshot-v4.d.ts.map +1 -1
- package/dist/journal-snapshot-v4.js +11 -6
- package/dist/journal-snapshot-v4.js.map +1 -1
- package/dist/journal-store.test.js +324 -7
- package/dist/journal-store.test.js.map +1 -1
- package/dist/journal.d.ts +51 -16
- package/dist/journal.d.ts.map +1 -1
- package/dist/journal.js +303 -79
- package/dist/journal.js.map +1 -1
- package/dist/lib/exit-codes.d.ts +15 -0
- package/dist/lib/exit-codes.d.ts.map +1 -1
- package/dist/lib/exit-codes.js +15 -0
- package/dist/lib/exit-codes.js.map +1 -1
- package/dist/personal-vault.d.ts.map +1 -1
- package/dist/personal-vault.js +10 -3
- package/dist/personal-vault.js.map +1 -1
- package/dist/personal-vault.test.js +35 -0
- package/dist/personal-vault.test.js.map +1 -1
- package/dist/remote-pull.d.ts.map +1 -1
- package/dist/remote-pull.js +9 -2
- package/dist/remote-pull.js.map +1 -1
- package/dist/remote-pull.test.js +59 -2
- package/dist/remote-pull.test.js.map +1 -1
- package/dist/s3.d.ts +1 -0
- package/dist/s3.d.ts.map +1 -1
- package/dist/s3.js +20 -2
- package/dist/s3.js.map +1 -1
- package/dist/s3.list-cost.test.d.ts +2 -0
- package/dist/s3.list-cost.test.d.ts.map +1 -0
- package/dist/s3.list-cost.test.js +51 -0
- package/dist/s3.list-cost.test.js.map +1 -0
- package/dist/sync/area-ledger.d.ts +27 -3
- package/dist/sync/area-ledger.d.ts.map +1 -1
- package/dist/sync/area-ledger.js +149 -39
- package/dist/sync/area-ledger.js.map +1 -1
- package/dist/sync/area-ledger.test.js +192 -5
- package/dist/sync/area-ledger.test.js.map +1 -1
- package/dist/sync/parallel-sync-coordinator.test.js +29 -0
- package/dist/sync/parallel-sync-coordinator.test.js.map +1 -1
- package/dist/sync/realtime-telemetry.d.ts +1 -1
- package/dist/sync/realtime-telemetry.d.ts.map +1 -1
- package/dist/sync/realtime-telemetry.js +14 -6
- package/dist/sync/realtime-telemetry.js.map +1 -1
- package/dist/sync/realtime-telemetry.test.js +136 -16
- package/dist/sync/realtime-telemetry.test.js.map +1 -1
- package/dist/sync/remote-file-spool.d.ts +16 -0
- package/dist/sync/remote-file-spool.d.ts.map +1 -0
- package/dist/sync/remote-file-spool.js +91 -0
- package/dist/sync/remote-file-spool.js.map +1 -0
- package/dist/sync/remote-file-spool.test.d.ts +2 -0
- package/dist/sync/remote-file-spool.test.d.ts.map +1 -0
- package/dist/sync/remote-file-spool.test.js +77 -0
- package/dist/sync/remote-file-spool.test.js.map +1 -0
- package/dist/sync/state-store.d.ts +6 -0
- package/dist/sync/state-store.d.ts.map +1 -1
- package/dist/sync/state-store.js +14 -2
- package/dist/sync/state-store.js.map +1 -1
- package/dist/watcher.d.ts +12 -0
- package/dist/watcher.d.ts.map +1 -1
- package/dist/watcher.js +131 -0
- package/dist/watcher.js.map +1 -1
- package/dist/watcher.test.js +63 -0
- package/dist/watcher.test.js.map +1 -1
- package/package.json +2 -1
|
@@ -28,6 +28,19 @@ export interface JournalRowStoreOptions {
|
|
|
28
28
|
/** Retain row-level before-images so callers can derive a delta. Defaults to true. */
|
|
29
29
|
trackChanges?: boolean;
|
|
30
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* A compact, insertion-ordered directory-prefix index. The immutable bulk is
|
|
33
|
+
* stored in packed row-id ranges; only rows structurally changed after the
|
|
34
|
+
* index was built need JavaScript sets.
|
|
35
|
+
*/
|
|
36
|
+
interface JournalPrefixIndex {
|
|
37
|
+
readonly prefixIds: Map<string, number>;
|
|
38
|
+
readonly offsets: Uint32Array;
|
|
39
|
+
readonly rowIds: Uint32Array;
|
|
40
|
+
readonly changedRows: Set<number>;
|
|
41
|
+
readonly appendedRows: Map<number, Set<number>>;
|
|
42
|
+
nextPrefixId: number;
|
|
43
|
+
}
|
|
31
44
|
/**
|
|
32
45
|
* The packed row sections carried by HQSNAP4. Typed arrays are intentionally
|
|
33
46
|
* views: the snapshot decoder installs them without decoding rows into objects.
|
|
@@ -117,6 +130,8 @@ export interface JournalRowOverlayChange {
|
|
|
117
130
|
export declare class JournalRowOverlay implements JournalRowsView {
|
|
118
131
|
private readonly base;
|
|
119
132
|
private readonly changes;
|
|
133
|
+
/** Base keys deleted then reinserted must move to the record's tail. */
|
|
134
|
+
private readonly moved;
|
|
120
135
|
private readonly dirtyPaths;
|
|
121
136
|
private dirtyLog;
|
|
122
137
|
constructor(base: JournalRowSource);
|
|
@@ -128,17 +143,19 @@ export declare class JournalRowOverlay implements JournalRowsView {
|
|
|
128
143
|
keys(): IterableIterator<string>;
|
|
129
144
|
entries(): IterableIterator<[string, Readonly<JournalEntry>]>;
|
|
130
145
|
values(): IterableIterator<Readonly<JournalEntry>>;
|
|
146
|
+
entriesForPrefix(prefix: string): IterableIterator<[string, Readonly<JournalEntry>]>;
|
|
131
147
|
toRecord(): Record<string, JournalEntry>;
|
|
132
148
|
dirtyLogSnapshot(): readonly JournalRowOverlayChange[];
|
|
133
149
|
drainDirtyLog(): JournalRowOverlayChange[];
|
|
134
150
|
/**
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
* copy over a long full-sync pass.
|
|
151
|
+
* Return a new durable view without adding the delta to this caller-owned
|
|
152
|
+
* dirty log. The source overlay stays immutable for a full pass that already
|
|
153
|
+
* borrowed it as its read baseline.
|
|
139
154
|
*/
|
|
140
|
-
|
|
155
|
+
withCommittedDelta(upserts: Readonly<Record<string, JournalEntry>>, deletes: readonly string[]): JournalRowOverlay;
|
|
156
|
+
private entriesForPrefixByKey;
|
|
141
157
|
private recordDirty;
|
|
158
|
+
private setReplacement;
|
|
142
159
|
}
|
|
143
160
|
/**
|
|
144
161
|
* A struct-of-arrays store for resident journal rows. It deliberately owns no
|
|
@@ -163,6 +180,15 @@ export declare class JournalRowStore {
|
|
|
163
180
|
private buckets;
|
|
164
181
|
private readonly directories;
|
|
165
182
|
private readonly directoryIds;
|
|
183
|
+
/**
|
|
184
|
+
* Prefix candidates are valuable only to a prefix scan. Snapshot recovery
|
|
185
|
+
* also constructs row stores for whole-journal writers (notably the short
|
|
186
|
+
* reverse shadow), where building this index would add an O(rows) pause to
|
|
187
|
+
* an operation that never queries a prefix. Build its packed ranges at an
|
|
188
|
+
* explicit warm boundary or on the first scan, then retain only structural
|
|
189
|
+
* changes in the small mutable overlay.
|
|
190
|
+
*/
|
|
191
|
+
private prefixRows;
|
|
166
192
|
private readonly authors;
|
|
167
193
|
private readonly authorIds;
|
|
168
194
|
private readonly freeRows;
|
|
@@ -211,6 +237,8 @@ export declare class JournalRowStore {
|
|
|
211
237
|
entriesForPrefix(prefix: string): IterableIterator<[string, Readonly<JournalEntry>]>;
|
|
212
238
|
values(): IterableIterator<Readonly<JournalEntry>>;
|
|
213
239
|
toRecord(): Record<string, JournalEntry>;
|
|
240
|
+
/** Build packed prefix candidates before a latency-sensitive targeted-pull phase. */
|
|
241
|
+
preparePrefixIndex(): JournalPrefixIndex;
|
|
214
242
|
/**
|
|
215
243
|
* Returns and clears changes since the prior checkpoint.
|
|
216
244
|
*
|
|
@@ -246,6 +274,12 @@ export declare class JournalRowStore {
|
|
|
246
274
|
static fromSnapshot(snapshot: JournalRowStoreSnapshot): JournalRowStore;
|
|
247
275
|
private reset;
|
|
248
276
|
private insertWithoutDirtyLog;
|
|
277
|
+
private addRowToPrefixIndex;
|
|
278
|
+
private removeRowFromPrefixIndex;
|
|
279
|
+
private ensurePrefixId;
|
|
280
|
+
private addDynamicPrefixRow;
|
|
281
|
+
private removeDynamicPrefixRow;
|
|
282
|
+
private prefixesForPath;
|
|
249
283
|
private recordDirty;
|
|
250
284
|
private allocateRow;
|
|
251
285
|
private ensureRowCapacity;
|
|
@@ -261,6 +295,7 @@ export declare class JournalRowStore {
|
|
|
261
295
|
private storeLeafFallback;
|
|
262
296
|
private leafBytes;
|
|
263
297
|
private pathForRow;
|
|
298
|
+
private pathForRowForPrefixIndex;
|
|
264
299
|
private findRowId;
|
|
265
300
|
private findIndexedRow;
|
|
266
301
|
private ensureBucketCapacity;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"journal-row-store.d.ts","sourceRoot":"","sources":["../src/journal-row-store.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"journal-row-store.d.ts","sourceRoot":"","sources":["../src/journal-row-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -195,12 +195,25 @@ export class JournalRows {
|
|
|
195
195
|
export class JournalRowOverlay {
|
|
196
196
|
base;
|
|
197
197
|
changes = new Map();
|
|
198
|
+
/** Base keys deleted then reinserted must move to the record's tail. */
|
|
199
|
+
moved = new Set();
|
|
198
200
|
dirtyPaths = new Set();
|
|
199
201
|
dirtyLog = [];
|
|
200
202
|
constructor(base) {
|
|
201
203
|
this.base = base;
|
|
202
204
|
}
|
|
203
205
|
get size() {
|
|
206
|
+
if ("size" in this.base && typeof this.base.size === "number") {
|
|
207
|
+
let size = this.base.size;
|
|
208
|
+
for (const [key, entry] of this.changes) {
|
|
209
|
+
const baseHasKey = this.base.has(key);
|
|
210
|
+
if (entry === undefined && baseHasKey)
|
|
211
|
+
size -= 1;
|
|
212
|
+
else if (entry !== undefined && !baseHasKey)
|
|
213
|
+
size += 1;
|
|
214
|
+
}
|
|
215
|
+
return size;
|
|
216
|
+
}
|
|
204
217
|
let size = 0;
|
|
205
218
|
for (const _ of this.keys())
|
|
206
219
|
size += 1;
|
|
@@ -214,7 +227,7 @@ export class JournalRowOverlay {
|
|
|
214
227
|
}
|
|
215
228
|
set(path, entry) {
|
|
216
229
|
this.recordDirty(path);
|
|
217
|
-
this.
|
|
230
|
+
this.setReplacement(path, freezeEntry(structuredClone(entry)));
|
|
218
231
|
}
|
|
219
232
|
delete(path) {
|
|
220
233
|
if (!this.has(path))
|
|
@@ -225,12 +238,14 @@ export class JournalRowOverlay {
|
|
|
225
238
|
}
|
|
226
239
|
*keys() {
|
|
227
240
|
for (const key of this.base.keys()) {
|
|
241
|
+
if (this.moved.has(key))
|
|
242
|
+
continue;
|
|
228
243
|
if (this.changes.get(key) === undefined && this.changes.has(key))
|
|
229
244
|
continue;
|
|
230
245
|
yield key;
|
|
231
246
|
}
|
|
232
247
|
for (const [key, entry] of this.changes) {
|
|
233
|
-
if (entry !== undefined && !this.base.has(key))
|
|
248
|
+
if (entry !== undefined && (!this.base.has(key) || this.moved.has(key)))
|
|
234
249
|
yield key;
|
|
235
250
|
}
|
|
236
251
|
}
|
|
@@ -245,6 +260,24 @@ export class JournalRowOverlay {
|
|
|
245
260
|
for (const [, entry] of this.entries())
|
|
246
261
|
yield entry;
|
|
247
262
|
}
|
|
263
|
+
*entriesForPrefix(prefix) {
|
|
264
|
+
const normalizedPrefix = prefix.replace(/\/+$/, "");
|
|
265
|
+
const base = this.base;
|
|
266
|
+
const baseEntries = base.entriesForPrefix?.(normalizedPrefix) ?? this.entriesForPrefixByKey(normalizedPrefix);
|
|
267
|
+
for (const [key, entry] of baseEntries) {
|
|
268
|
+
if (this.moved.has(key))
|
|
269
|
+
continue;
|
|
270
|
+
const replacement = this.changes.has(key) ? this.changes.get(key) : entry;
|
|
271
|
+
if (replacement !== undefined)
|
|
272
|
+
yield [key, replacement];
|
|
273
|
+
}
|
|
274
|
+
for (const [key, entry] of this.changes) {
|
|
275
|
+
if (entry === undefined || (this.base.has(key) && !this.moved.has(key)))
|
|
276
|
+
continue;
|
|
277
|
+
if (isPrefixMatch(key, normalizedPrefix))
|
|
278
|
+
yield [key, entry];
|
|
279
|
+
}
|
|
280
|
+
}
|
|
248
281
|
toRecord() {
|
|
249
282
|
const record = {};
|
|
250
283
|
for (const [key, entry] of this.entries())
|
|
@@ -261,15 +294,31 @@ export class JournalRowOverlay {
|
|
|
261
294
|
return drained;
|
|
262
295
|
}
|
|
263
296
|
/**
|
|
264
|
-
*
|
|
265
|
-
*
|
|
266
|
-
*
|
|
267
|
-
* copy over a long full-sync pass.
|
|
297
|
+
* Return a new durable view without adding the delta to this caller-owned
|
|
298
|
+
* dirty log. The source overlay stays immutable for a full pass that already
|
|
299
|
+
* borrowed it as its read baseline.
|
|
268
300
|
*/
|
|
269
|
-
|
|
270
|
-
this.
|
|
271
|
-
|
|
272
|
-
|
|
301
|
+
withCommittedDelta(upserts, deletes) {
|
|
302
|
+
const next = new JournalRowOverlay(this.base);
|
|
303
|
+
for (const [key, entry] of this.changes)
|
|
304
|
+
next.changes.set(key, entry);
|
|
305
|
+
for (const key of this.moved)
|
|
306
|
+
next.moved.add(key);
|
|
307
|
+
for (const key of deletes)
|
|
308
|
+
next.changes.set(key, undefined);
|
|
309
|
+
for (const [key, entry] of Object.entries(upserts)) {
|
|
310
|
+
next.setReplacement(key, freezeEntry(structuredClone(entry)));
|
|
311
|
+
}
|
|
312
|
+
return next;
|
|
313
|
+
}
|
|
314
|
+
*entriesForPrefixByKey(prefix) {
|
|
315
|
+
for (const key of this.base.keys()) {
|
|
316
|
+
if (!isPrefixMatch(key, prefix))
|
|
317
|
+
continue;
|
|
318
|
+
const entry = this.base.get(key);
|
|
319
|
+
if (entry !== undefined)
|
|
320
|
+
yield [key, entry];
|
|
321
|
+
}
|
|
273
322
|
}
|
|
274
323
|
recordDirty(path) {
|
|
275
324
|
if (this.dirtyPaths.has(path))
|
|
@@ -282,6 +331,17 @@ export class JournalRowOverlay {
|
|
|
282
331
|
previousFingerprint: previous === undefined ? undefined : journalEntryFingerprint(previous),
|
|
283
332
|
}));
|
|
284
333
|
}
|
|
334
|
+
setReplacement(path, entry) {
|
|
335
|
+
if (this.changes.get(path) === undefined && this.changes.has(path)) {
|
|
336
|
+
this.changes.delete(path);
|
|
337
|
+
if (this.base.has(path))
|
|
338
|
+
this.moved.add(path);
|
|
339
|
+
}
|
|
340
|
+
this.changes.set(path, entry);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
function isPrefixMatch(key, normalizedPrefix) {
|
|
344
|
+
return normalizedPrefix === "" || key === normalizedPrefix || key.startsWith(`${normalizedPrefix}/`);
|
|
285
345
|
}
|
|
286
346
|
/**
|
|
287
347
|
* A struct-of-arrays store for resident journal rows. It deliberately owns no
|
|
@@ -306,6 +366,15 @@ export class JournalRowStore {
|
|
|
306
366
|
buckets;
|
|
307
367
|
directories = [""];
|
|
308
368
|
directoryIds = new Map([["", 0]]);
|
|
369
|
+
/**
|
|
370
|
+
* Prefix candidates are valuable only to a prefix scan. Snapshot recovery
|
|
371
|
+
* also constructs row stores for whole-journal writers (notably the short
|
|
372
|
+
* reverse shadow), where building this index would add an O(rows) pause to
|
|
373
|
+
* an operation that never queries a prefix. Build its packed ranges at an
|
|
374
|
+
* explicit warm boundary or on the first scan, then retain only structural
|
|
375
|
+
* changes in the small mutable overlay.
|
|
376
|
+
*/
|
|
377
|
+
prefixRows;
|
|
309
378
|
authors = [""];
|
|
310
379
|
authorIds = new Map();
|
|
311
380
|
freeRows = [];
|
|
@@ -425,6 +494,7 @@ export class JournalRowStore {
|
|
|
425
494
|
this.storeLeafFallback(rowId, leaf, leafBytes);
|
|
426
495
|
this.insertIndex(rowId);
|
|
427
496
|
this.appendIterationRow(rowId);
|
|
497
|
+
this.addRowToPrefixIndex(rowId, path);
|
|
428
498
|
this.liveRows++;
|
|
429
499
|
}
|
|
430
500
|
delete(path) {
|
|
@@ -433,6 +503,7 @@ export class JournalRowStore {
|
|
|
433
503
|
return false;
|
|
434
504
|
if (this.trackChanges)
|
|
435
505
|
this.recordDirty(rowId, path, true, journalEntryFingerprint(this.materialize(rowId)));
|
|
506
|
+
this.removeRowFromPrefixIndex(rowId, path);
|
|
436
507
|
this.deleteIndex(rowId);
|
|
437
508
|
this.removeIterationRow(rowId);
|
|
438
509
|
this.clearRow(rowId);
|
|
@@ -461,17 +532,33 @@ export class JournalRowStore {
|
|
|
461
532
|
yield* this.entries();
|
|
462
533
|
return;
|
|
463
534
|
}
|
|
464
|
-
const
|
|
465
|
-
const
|
|
466
|
-
|
|
467
|
-
const
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
535
|
+
const index = this.preparePrefixIndex();
|
|
536
|
+
const prefixId = index.prefixIds.get(normalizedPrefix);
|
|
537
|
+
if (prefixId === undefined) {
|
|
538
|
+
const exactRowId = this.findRowId(normalizedPrefix);
|
|
539
|
+
if (exactRowId !== undefined)
|
|
540
|
+
yield [this.pathForRow(exactRowId), this.materialize(exactRowId)];
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
543
|
+
const start = prefixId + 1 < index.offsets.length ? index.offsets[prefixId] : 0;
|
|
544
|
+
const end = prefixId + 1 < index.offsets.length ? index.offsets[prefixId + 1] : 0;
|
|
545
|
+
for (let offset = start; offset < end; offset += 1) {
|
|
546
|
+
const rowId = index.rowIds[offset];
|
|
547
|
+
if (index.changedRows.has(rowId))
|
|
548
|
+
continue;
|
|
549
|
+
yield [this.pathForRow(rowId), this.materialize(rowId)];
|
|
550
|
+
}
|
|
551
|
+
const appended = index.appendedRows.get(prefixId);
|
|
552
|
+
if (appended === undefined)
|
|
553
|
+
return;
|
|
554
|
+
for (const rowId of appended) {
|
|
555
|
+
if (this.freeRowSet.has(rowId))
|
|
556
|
+
continue;
|
|
557
|
+
const path = this.pathForRow(rowId);
|
|
558
|
+
// A reused row id may still occur in an older dynamic bucket. The
|
|
559
|
+
// immutable index never has that ambiguity because changed rows skip it.
|
|
560
|
+
if (isPrefixMatch(path, normalizedPrefix))
|
|
561
|
+
yield [path, this.materialize(rowId)];
|
|
475
562
|
}
|
|
476
563
|
}
|
|
477
564
|
*values() {
|
|
@@ -490,6 +577,52 @@ export class JournalRowStore {
|
|
|
490
577
|
}
|
|
491
578
|
return record;
|
|
492
579
|
}
|
|
580
|
+
/** Build packed prefix candidates before a latency-sensitive targeted-pull phase. */
|
|
581
|
+
preparePrefixIndex() {
|
|
582
|
+
if (this.prefixRows !== undefined)
|
|
583
|
+
return this.prefixRows;
|
|
584
|
+
const prefixIds = new Map();
|
|
585
|
+
for (const rowId of this.rowIds()) {
|
|
586
|
+
for (const prefix of this.prefixesForPath(this.pathForRowForPrefixIndex(rowId))) {
|
|
587
|
+
if (!prefixIds.has(prefix))
|
|
588
|
+
prefixIds.set(prefix, prefixIds.size);
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
const counts = new Uint32Array(prefixIds.size);
|
|
592
|
+
for (const rowId of this.rowIds()) {
|
|
593
|
+
const path = this.pathForRowForPrefixIndex(rowId);
|
|
594
|
+
const ownPrefixId = prefixIds.get(path);
|
|
595
|
+
if (ownPrefixId !== undefined)
|
|
596
|
+
counts[ownPrefixId] += 1;
|
|
597
|
+
for (const prefix of this.prefixesForPath(path))
|
|
598
|
+
counts[prefixIds.get(prefix)] += 1;
|
|
599
|
+
}
|
|
600
|
+
const offsets = new Uint32Array(prefixIds.size + 1);
|
|
601
|
+
for (let prefixId = 0; prefixId < counts.length; prefixId += 1) {
|
|
602
|
+
offsets[prefixId + 1] = offsets[prefixId] + counts[prefixId];
|
|
603
|
+
}
|
|
604
|
+
const nextOffsets = new Uint32Array(offsets);
|
|
605
|
+
const rowIds = new Uint32Array(offsets[offsets.length - 1]);
|
|
606
|
+
for (const rowId of this.rowIds()) {
|
|
607
|
+
const path = this.pathForRowForPrefixIndex(rowId);
|
|
608
|
+
const ownPrefixId = prefixIds.get(path);
|
|
609
|
+
if (ownPrefixId !== undefined)
|
|
610
|
+
rowIds[nextOffsets[ownPrefixId]++] = rowId;
|
|
611
|
+
for (const prefix of this.prefixesForPath(path)) {
|
|
612
|
+
const prefixId = prefixIds.get(prefix);
|
|
613
|
+
rowIds[nextOffsets[prefixId]++] = rowId;
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
this.prefixRows = {
|
|
617
|
+
prefixIds,
|
|
618
|
+
offsets,
|
|
619
|
+
rowIds,
|
|
620
|
+
changedRows: new Set(),
|
|
621
|
+
appendedRows: new Map(),
|
|
622
|
+
nextPrefixId: prefixIds.size,
|
|
623
|
+
};
|
|
624
|
+
return this.prefixRows;
|
|
625
|
+
}
|
|
493
626
|
/**
|
|
494
627
|
* Returns and clears changes since the prior checkpoint.
|
|
495
628
|
*
|
|
@@ -704,6 +837,9 @@ export class JournalRowStore {
|
|
|
704
837
|
store.liveRows = snapshot.rowCount;
|
|
705
838
|
store.firstIterationRowId = iteration.first;
|
|
706
839
|
store.lastIterationRowId = iteration.last;
|
|
840
|
+
// Prefix candidates are deliberately lazy after recovery. A reverse
|
|
841
|
+
// shadow only appends a delta and never scans prefixes, while the retained
|
|
842
|
+
// area aggregate calls preparePrefixIndex() during its pre-realtime warmup.
|
|
707
843
|
return store;
|
|
708
844
|
}
|
|
709
845
|
reset(rowCapacity) {
|
|
@@ -726,6 +862,7 @@ export class JournalRowStore {
|
|
|
726
862
|
this.directories.length = 1;
|
|
727
863
|
this.directoryIds.clear();
|
|
728
864
|
this.directoryIds.set("", 0);
|
|
865
|
+
this.prefixRows = undefined;
|
|
729
866
|
this.authors.length = 1;
|
|
730
867
|
this.authorIds.clear();
|
|
731
868
|
this.freeRows.length = 0;
|
|
@@ -754,8 +891,83 @@ export class JournalRowStore {
|
|
|
754
891
|
this.storeLeafFallback(rowId, leaf, leafBytes);
|
|
755
892
|
this.insertIndex(rowId);
|
|
756
893
|
this.appendIterationRow(rowId);
|
|
894
|
+
this.addRowToPrefixIndex(rowId, path);
|
|
757
895
|
this.liveRows++;
|
|
758
896
|
}
|
|
897
|
+
addRowToPrefixIndex(rowId, path) {
|
|
898
|
+
const index = this.prefixRows;
|
|
899
|
+
if (index === undefined)
|
|
900
|
+
return;
|
|
901
|
+
// A reused row id could appear in the immutable range under its old path.
|
|
902
|
+
// It must be served only by the post-index dynamic bucket from now on.
|
|
903
|
+
index.changedRows.add(rowId);
|
|
904
|
+
const ownPrefixId = index.prefixIds.get(path);
|
|
905
|
+
if (ownPrefixId !== undefined)
|
|
906
|
+
this.addDynamicPrefixRow(index, ownPrefixId, rowId);
|
|
907
|
+
for (const prefix of this.prefixesForPath(path)) {
|
|
908
|
+
const prefixId = this.ensurePrefixId(index, prefix);
|
|
909
|
+
this.addDynamicPrefixRow(index, prefixId, rowId);
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
removeRowFromPrefixIndex(rowId, path) {
|
|
913
|
+
const index = this.prefixRows;
|
|
914
|
+
if (index === undefined)
|
|
915
|
+
return;
|
|
916
|
+
index.changedRows.add(rowId);
|
|
917
|
+
this.removeDynamicPrefixRow(index, path, rowId);
|
|
918
|
+
for (const prefix of this.prefixesForPath(path))
|
|
919
|
+
this.removeDynamicPrefixRow(index, prefix, rowId);
|
|
920
|
+
}
|
|
921
|
+
ensurePrefixId(index, prefix) {
|
|
922
|
+
const known = index.prefixIds.get(prefix);
|
|
923
|
+
if (known !== undefined)
|
|
924
|
+
return known;
|
|
925
|
+
// Released dynamic ids cannot be reused: other live dynamic prefixes may
|
|
926
|
+
// have larger ids, and an id collision would merge their candidate sets.
|
|
927
|
+
const prefixId = index.nextPrefixId++;
|
|
928
|
+
index.prefixIds.set(prefix, prefixId);
|
|
929
|
+
// A file may have been written before it gained descendants. It belongs
|
|
930
|
+
// first in this newly-created directory bucket, just as it did in the
|
|
931
|
+
// global insertion order before the index was warmed.
|
|
932
|
+
const exactRowId = this.findRowId(prefix);
|
|
933
|
+
if (exactRowId !== undefined)
|
|
934
|
+
this.addDynamicPrefixRow(index, prefixId, exactRowId);
|
|
935
|
+
return prefixId;
|
|
936
|
+
}
|
|
937
|
+
addDynamicPrefixRow(index, prefixId, rowId) {
|
|
938
|
+
let rows = index.appendedRows.get(prefixId);
|
|
939
|
+
if (rows === undefined) {
|
|
940
|
+
rows = new Set();
|
|
941
|
+
index.appendedRows.set(prefixId, rows);
|
|
942
|
+
}
|
|
943
|
+
rows.add(rowId);
|
|
944
|
+
}
|
|
945
|
+
removeDynamicPrefixRow(index, prefix, rowId) {
|
|
946
|
+
const prefixId = index.prefixIds.get(prefix);
|
|
947
|
+
if (prefixId === undefined)
|
|
948
|
+
return;
|
|
949
|
+
const rows = index.appendedRows.get(prefixId);
|
|
950
|
+
if (rows === undefined)
|
|
951
|
+
return;
|
|
952
|
+
rows.delete(rowId);
|
|
953
|
+
if (rows.size !== 0)
|
|
954
|
+
return;
|
|
955
|
+
index.appendedRows.delete(prefixId);
|
|
956
|
+
// Static packed ranges own their prefix strings for the index lifetime.
|
|
957
|
+
// A dynamically-created directory with no surviving row must release its
|
|
958
|
+
// string immediately: watcher churn can otherwise retain every transient
|
|
959
|
+
// directory name indefinitely.
|
|
960
|
+
if (prefixId + 1 >= index.offsets.length)
|
|
961
|
+
index.prefixIds.delete(prefix);
|
|
962
|
+
}
|
|
963
|
+
*prefixesForPath(path) {
|
|
964
|
+
const { directory } = splitPath(path);
|
|
965
|
+
for (let prefix = directory; prefix !== "";) {
|
|
966
|
+
yield prefix;
|
|
967
|
+
const slash = prefix.lastIndexOf("/");
|
|
968
|
+
prefix = slash === -1 ? "" : prefix.slice(0, slash);
|
|
969
|
+
}
|
|
970
|
+
}
|
|
759
971
|
recordDirty(rowId, path, hadPrevious, previousFingerprint) {
|
|
760
972
|
if (this.dirtyPaths.has(path))
|
|
761
973
|
return;
|
|
@@ -1017,6 +1229,13 @@ export class JournalRowStore {
|
|
|
1017
1229
|
: textDecoder.decode(this.leafBytes(rowId));
|
|
1018
1230
|
return directory === "" ? leaf : directory + "/" + leaf;
|
|
1019
1231
|
}
|
|
1232
|
+
pathForRowForPrefixIndex(rowId) {
|
|
1233
|
+
const directory = this.directories[this.dirIds[rowId]];
|
|
1234
|
+
const leaf = this.leafFallbacks.has(rowId)
|
|
1235
|
+
? this.leafFallbacks.get(rowId)
|
|
1236
|
+
: textDecoder.decode(this.leafBytes(rowId));
|
|
1237
|
+
return directory === "" ? leaf : directory + "/" + leaf;
|
|
1238
|
+
}
|
|
1020
1239
|
findRowId(path) {
|
|
1021
1240
|
const { directory, leaf } = splitPath(path);
|
|
1022
1241
|
const directoryId = this.directoryIds.get(directory);
|