@optimystic/db-p2p-storage-fs 1.14.0 → 1.16.0

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 (37) hide show
  1. package/README.md +142 -33
  2. package/dist/src/file-batch-backend.d.ts +69 -0
  3. package/dist/src/file-batch-backend.d.ts.map +1 -0
  4. package/dist/src/file-batch-backend.js +400 -0
  5. package/dist/src/file-batch-backend.js.map +1 -0
  6. package/dist/src/file-kv-store.d.ts +37 -3
  7. package/dist/src/file-kv-store.d.ts.map +1 -1
  8. package/dist/src/file-kv-store.js +100 -34
  9. package/dist/src/file-kv-store.js.map +1 -1
  10. package/dist/src/file-storage.d.ts +20 -58
  11. package/dist/src/file-storage.d.ts.map +1 -1
  12. package/dist/src/file-storage.js +16 -430
  13. package/dist/src/file-storage.js.map +1 -1
  14. package/dist/src/file-write-log.d.ts +361 -0
  15. package/dist/src/file-write-log.d.ts.map +1 -0
  16. package/dist/src/file-write-log.js +848 -0
  17. package/dist/src/file-write-log.js.map +1 -0
  18. package/dist/src/index.d.ts +3 -0
  19. package/dist/src/index.d.ts.map +1 -1
  20. package/dist/src/index.js +3 -0
  21. package/dist/src/index.js.map +1 -1
  22. package/dist/src/store-lock.d.ts +42 -0
  23. package/dist/src/store-lock.d.ts.map +1 -0
  24. package/dist/src/store-lock.js +116 -0
  25. package/dist/src/store-lock.js.map +1 -0
  26. package/package.json +3 -3
  27. package/src/file-batch-backend.ts +430 -0
  28. package/src/file-kv-store.ts +112 -32
  29. package/src/file-storage.ts +22 -468
  30. package/src/file-write-log.ts +906 -0
  31. package/src/index.ts +3 -0
  32. package/src/store-lock.ts +123 -0
  33. package/dist/src/atomic-write.d.ts +0 -22
  34. package/dist/src/atomic-write.d.ts.map +0 -1
  35. package/dist/src/atomic-write.js +0 -90
  36. package/dist/src/atomic-write.js.map +0 -1
  37. package/src/atomic-write.ts +0 -89
@@ -0,0 +1,361 @@
1
+ import { type CommittedBatch, type SetTimer, type SinkCommitOptions, type StoreIdentity } from '@optimystic/db-p2p';
2
+ export declare const WRITE_LOG_FILENAME = "write-ahead.log";
3
+ /**
4
+ * The log a checkpoint has sealed and is syncing the tree under. Present on disk only between a
5
+ * checkpoint's seal and its truncate; an open replays it ahead of {@link WRITE_LOG_FILENAME}.
6
+ */
7
+ export declare const SEALED_WRITE_LOG_FILENAME = "write-ahead.log.sealed";
8
+ /** {@link FileWriteLogOptions.checkpointBytes}'s default: 16 MiB. */
9
+ export declare const DEFAULT_CHECKPOINT_BYTES: number;
10
+ /** {@link FileWriteLogOptions.checkpointIdleMs}'s default. */
11
+ export declare const DEFAULT_CHECKPOINT_IDLE_MS = 5000;
12
+ /**
13
+ * The log's fixed header: the magic bytes `OPTIMYSTIC-WAL`, then one format-version byte. A file
14
+ * that does not start with exactly this is not a log this build wrote, and replay applies nothing
15
+ * from it.
16
+ */
17
+ export declare const WRITE_LOG_FORMAT_VERSION = 1;
18
+ export declare const WRITE_LOG_HEADER: Uint8Array;
19
+ /**
20
+ * One write of a batch. `path` is relative to the store's directory, with forward slashes
21
+ * whatever the platform, so a log written on one platform replays on another.
22
+ */
23
+ export type WriteLogEntry = {
24
+ readonly kind: 'put';
25
+ readonly path: string;
26
+ readonly value: Uint8Array;
27
+ } | {
28
+ readonly kind: 'delete';
29
+ readonly path: string;
30
+ };
31
+ /**
32
+ * One record: `[u32 payload length][u32 CRC-32 of the payload][payload]`, little-endian, where the
33
+ * payload is the batch's entries in order, each `[u8 kind][u16 path length][path, UTF-8][u32 value
34
+ * length][value]`. A delete carries a zero-length value.
35
+ */
36
+ export declare function encodeWriteLogRecord(entries: readonly WriteLogEntry[]): Uint8Array;
37
+ /** Why a strict read of the log stopped before the end of the file. */
38
+ export type WriteLogStop = 'bad-header' | 'torn-record' | 'crc-mismatch' | 'bad-entry';
39
+ export interface DecodedWriteLog {
40
+ /** Every batch read, in log order. */
41
+ readonly batches: readonly (readonly WriteLogEntry[])[];
42
+ /** The byte offset reading stopped at: the file's length when every byte parsed. */
43
+ readonly stoppedAt: number;
44
+ /** Set when reading stopped short; the batches before the offending record are in `batches`. */
45
+ readonly stoppedBy?: WriteLogStop;
46
+ }
47
+ /**
48
+ * Read a log strictly: a header that is not ours, a record whose length runs past the end of the
49
+ * file, a CRC that does not match, or an entry that does not parse stops the read before that
50
+ * record. What precedes it is returned in order.
51
+ */
52
+ export declare function decodeWriteLog(bytes: Uint8Array): DecodedWriteLog;
53
+ /** The file's bytes, or `undefined` when there is no such file. Any other error propagates. */
54
+ export declare function readFileIfExists(filePath: string): Promise<Uint8Array | undefined>;
55
+ /**
56
+ * Best-effort fsync of a directory, so an entry added to, removed from or renamed within it
57
+ * survives power loss. POSIX needs this; platforms that reject opening a directory for fsync
58
+ * throw, and the throw is ignored rather than failing the write.
59
+ *
60
+ * Skipped outright on win32: there `fs.open(dir, 'r')` SUCCEEDS and only the following
61
+ * `handle.sync()` fails with EPERM, so the open/close pair was guaranteed wasted work. Durability
62
+ * is unchanged on win32 (the sync never succeeded there).
63
+ *
64
+ * NOTE: every error is swallowed, an I/O error included, and a checkpoint discards its sealed log
65
+ * on the strength of these syncs. A directory sync that fails with EIO therefore lets the log go
66
+ * while a directory entry it covered may not be durable. If that is ever seen, swallow only the
67
+ * codes a filesystem uses to refuse a directory sync (EINVAL, ENOTSUP, EISDIR, EPERM, EBADF) and
68
+ * ENOENT, and let the rest fail the checkpoint.
69
+ */
70
+ export declare function fsyncDir(dir: string): Promise<void>;
71
+ /** fsync a file in place; a file that no longer exists is skipped. Opened `r+`: Windows refuses to flush a read-only handle. */
72
+ export declare function fsyncFile(filePath: string): Promise<void>;
73
+ /**
74
+ * The identity every store over `basePath` reports (`RawStoreDriver.storeIdentity`): `file:` and
75
+ * the directory resolved once, here. `path.resolve` is cwd-dependent, and resolving at construction
76
+ * is the correct reading — two stores built from the same RELATIVE path under different cwds
77
+ * genuinely address different directories and must not compare equal. An empty basePath resolves
78
+ * to the cwd; nothing special-cases it. (A whitespace-only basePath is NOT the cwd — `path.resolve`
79
+ * is pure string work, so `' '` names a child directory called `' '`.)
80
+ *
81
+ * Lowercased on win32 because Windows paths are case-insensitive: `C:\Foo` and `C:\foo` are one
82
+ * directory and must produce one identity.
83
+ *
84
+ * NOTE: aliases of one directory that this does NOT collapse, and so read as two identities:
85
+ * symlinks, junctions, UNC-versus-mapped-drive spellings, and case-differing spellings on a
86
+ * case-INSENSITIVE non-Windows volume (the default on macOS) — platform is the only signal
87
+ * available synchronously, and case-folding every darwin path would be wrong on a case-sensitive
88
+ * volume. `fs.realpath` resolves all of these, but it is async (a store's constructor is not) and
89
+ * requires the directory to already exist. Revisit if an alias ever bites. All of these fail in
90
+ * the SAFE direction for the read cache: a missed alias reports two identities for one directory,
91
+ * so an identity-keyed consumer declines to merge and gets today's behavior. For the write-ahead
92
+ * log they fail less safely: two stores over two spellings of one directory open two logs, and
93
+ * the second is refused by the lock.
94
+ * NOTE: the win32 fold is the one branch that can err in the UNSAFE direction — Windows 10+
95
+ * supports per-directory case sensitivity (`fsutil file setCaseSensitiveInfo`), and on such a
96
+ * directory `X:\p\Foo` and `X:\p\foo` are two directories folded onto ONE identity. The merging
97
+ * consumers — `withReadCache` (one read cache per identity) and the log registry below (one log
98
+ * per identity) — would then read and write two directories through one cache and one log. Not
99
+ * addressable synchronously either (the flag is a per-directory filesystem query). Revisit if
100
+ * Optimystic ever targets a case-sensitive-enabled Windows directory; until then the fold is
101
+ * right for every ordinary Windows volume.
102
+ */
103
+ export declare function fileStoreIdentity(basePath: string): StoreIdentity;
104
+ /** Paths the tree has been written to since the log was last checkpointed; the checkpoint's work list. */
105
+ export interface DirtyPaths {
106
+ /** Absolute paths of files written, less those deleted since. */
107
+ readonly files: Set<string>;
108
+ /** Absolute paths of directories whose entries changed: a file written or deleted in them, or a directory created in them. */
109
+ readonly directories: Set<string>;
110
+ }
111
+ /** When the log is checkpointed. Shared by every store over the directory; see {@link FileWriteLog.acquire}. */
112
+ export interface FileWriteLogOptions {
113
+ /**
114
+ * Checkpoint once the log holds at least this many bytes of records, checked after each append.
115
+ * Default {@link DEFAULT_CHECKPOINT_BYTES}.
116
+ */
117
+ checkpointBytes?: number;
118
+ /**
119
+ * Checkpoint this long after the last append, so a store that stops writing does not keep its
120
+ * log until it closes. Re-armed by every append. Default {@link DEFAULT_CHECKPOINT_IDLE_MS}.
121
+ */
122
+ checkpointIdleMs?: number;
123
+ /** Arms the idle checkpoint; defaults to an unref'd `setTimeout`, so it never holds a process open. Injected by tests. */
124
+ setTimer?: SetTimer;
125
+ }
126
+ /** Throws a `RangeError` for a checkpoint setting out of range; a store's constructor calls it, so a bad setting fails there rather than at the first write. */
127
+ export declare function assertFileWriteLogOptions(options: FileWriteLogOptions): void;
128
+ /**
129
+ * The write-ahead log of one store directory: `<basePath>/write-ahead.log`, every batch of writes
130
+ * appended as one record, synced by the earliest deadline any batch was given, and applied to the
131
+ * readable file tree once it is durable.
132
+ *
133
+ * The write-ahead rule: a tree file only ever holds content whose log record is durable. So what
134
+ * survives a crash is the log's durable prefix plus whatever the tree already held, and {@link open}
135
+ * reconstructs it by replaying the log in order (puts and deletes are idempotent) before anything
136
+ * is served. A replay of a put over a newer tree file cannot happen: every tree write has a log
137
+ * record, and the log is replayed in order, so the last record for a path is the newest content
138
+ * the tree was ever given. A store written by a build before the log has no log file and opens
139
+ * with nothing to replay.
140
+ *
141
+ * A record reaches the operating system in its commit, so it survives a crash of this process from
142
+ * then on: the next open's replay applies it. What the sync adds is surviving a power cut, and a
143
+ * {@link commit} allowed to wait for that (`syncWithinMs` above 0) resolves without it, so that one
144
+ * sync, made by the earliest deadline, covers every record appended since the last. The rules are
145
+ * at {@link commit} and {@link syncUnsynced}.
146
+ *
147
+ * A {@link checkpoint} makes the tree as durable as the log and then discards the log, so the log
148
+ * never grows without bound: it runs when the log passes `checkpointBytes`, `checkpointIdleMs` after
149
+ * the last append, and on the last {@link release}. Its three steps are under {@link checkpointOnce}.
150
+ *
151
+ * One instance per directory per process, shared by reference count through {@link acquire}, so
152
+ * every store over one directory in one process — `FileRawStorage` and `FileKVStore` alike — shares
153
+ * one log, one lock and one checkpoint, rather than deadlocking on the lock or interleaving two
154
+ * writers into one file. Each keeps its own overlay above this, which is why a second store opened
155
+ * beside a first cannot see the first's unflushed writes.
156
+ */
157
+ export declare class FileWriteLog {
158
+ readonly basePath: string;
159
+ readonly identity: StoreIdentity;
160
+ private readonly settings;
161
+ /** A previous log over this directory still releasing its handle and lock; opening waits for it. */
162
+ private readonly predecessorClosed;
163
+ private static readonly registry;
164
+ /** Logs whose last reference was released and whose handle and lock are still being let go of. */
165
+ private static readonly closing;
166
+ /**
167
+ * The shared log for the directory, counted once more. Synchronous, so two acquirers in one
168
+ * tick get one instance. Balance every call with one {@link release}.
169
+ *
170
+ * The checkpoint settings are the first acquirer's: a store opened over a directory whose log is
171
+ * already open shares that log's settings, and a setting it names that differs is logged and
172
+ * not applied.
173
+ */
174
+ static acquire(basePath: string, options?: FileWriteLogOptions): FileWriteLog;
175
+ readonly logPath: string;
176
+ readonly sealedPath: string;
177
+ /** What the tree has been given since the log was last sealed; see {@link DirtyPaths}. Swapped for an empty set by each seal. */
178
+ private dirty;
179
+ /** Bytes of records in the current log, the size threshold's measure. Zero means there is nothing to checkpoint. */
180
+ private appendedBytes;
181
+ private refs;
182
+ private opening;
183
+ private handle;
184
+ private lock;
185
+ /** Commits and seals run one at a time, in order, on this chain; it never rejects. */
186
+ private queue;
187
+ private fault;
188
+ private closed;
189
+ /** The checkpoint running now, if any, which also runs every one asked for while it ran. */
190
+ private checkpointRun;
191
+ /** A checkpoint was asked for while {@link checkpointRun} was running: run one more after it. */
192
+ private checkpointAgain;
193
+ private cancelIdleCheckpoint;
194
+ /**
195
+ * Records appended and not yet synced, in log order, each held with the entries the sync step
196
+ * writes to the tree and the `durable` it settles; with them the earliest deadline, the timer
197
+ * armed for it, and the `window-overrun` episode. Emptied by every sync step and by the latch.
198
+ * Bounded by the window: it holds what was committed since the last sync, and the earliest
199
+ * deadline among them forces one.
200
+ */
201
+ private readonly unsynced;
202
+ private constructor();
203
+ /** True once an open, an append, an apply or a checkpoint failed; every later commit then throws {@link StoreFailedError}. */
204
+ get failed(): boolean;
205
+ /**
206
+ * Take the lock, replay the log into the tree, truncate it and hold it open. Memoized: the first
207
+ * operation opens, every later one waits for that. A directory another live process holds throws
208
+ * {@link StoreLockedError} from every operation; an I/O failure latches the log failed and throws
209
+ * {@link StoreFailedError} from every operation. Either outcome is kept for the life of the
210
+ * instance, and the instance is shared by every store over the directory until each has released
211
+ * it: to retry after the holder has exited, close those stores and open a new one.
212
+ */
213
+ open(): Promise<void>;
214
+ /**
215
+ * Append the batch as one record and resolve with its `durable`, which settles once the record is
216
+ * synced and the batch written to the tree. Batches commit one at a time in the order they were
217
+ * submitted, and their `durable` settle in that order. `WriteGroupSink.commit`'s contract:
218
+ *
219
+ * - `syncWithinMs` 0 (**strict**): the sync step runs before this resolves, so the returned
220
+ * `durable` is already settled and every earlier batch is durable too.
221
+ * - Otherwise (**relaxed**): the record is in the operating system and the batch waits in
222
+ * {@link unsynced} with the deadline `syncWithinMs` after this was CALLED, not after the queue got
223
+ * to it, so a commit that waited in line past its own deadline is treated as overdue. A timer
224
+ * armed for the earliest deadline runs the sync step; a strict commit or a checkpoint meanwhile
225
+ * runs it sooner, for every batch waiting.
226
+ * - **Backpressure:** a commit that finds the earliest unsynced deadline already passed runs the
227
+ * sync step before it resolves, whatever its own window. When the disk falls behind, writers
228
+ * wait for it instead of the window quietly growing.
229
+ *
230
+ * The deadlines, the timer and the backpressure test are the rules of `SyncDeadlines`, from
231
+ * `@optimystic/db-p2p`, which every store that defers its sync shares.
232
+ *
233
+ * The tree is written at the sync, not here, so a reader of the tree never sees a batch whose
234
+ * record a power cut could still take; the overlay above each store serves the batch until its
235
+ * `durable` resolves.
236
+ */
237
+ commit(entries: readonly WriteLogEntry[], { syncWithinMs }: SinkCommitOptions): Promise<CommittedBatch>;
238
+ /**
239
+ * Hasten: make every record appended before this call durable, and write its batch to the tree.
240
+ * Queued, so it covers exactly those records; with nothing unsynced it touches no disk.
241
+ * `WriteGroupSink.sync`'s contract.
242
+ */
243
+ sync(): Promise<void>;
244
+ /**
245
+ * Make the tree as durable as the log, then discard the log. One at a time: asked for while one
246
+ * runs, it runs once more after that one, and resolves when that has. Skipped when the log has
247
+ * failed, was never opened, or holds no record. A failure latches the log failed, like a rejected
248
+ * commit: a half-synced tree under a discarded log cannot be recovered.
249
+ */
250
+ checkpoint(): Promise<void>;
251
+ /**
252
+ * Give back one reference. The last release waits for the commit in flight and for a checkpoint
253
+ * in flight, runs a final checkpoint, closes the log handle and removes the lock; a log acquired
254
+ * for the directory meanwhile opens after that. Rejects only when that final checkpoint fails,
255
+ * and lets go of the handle and the lock either way.
256
+ */
257
+ release(): Promise<void>;
258
+ private throwIfFailed;
259
+ private enqueue;
260
+ private noteDifferingSettings;
261
+ private openOnce;
262
+ /**
263
+ * Apply the sealed segment's records, then the current log's, in order; make what they touched
264
+ * durable; then remove the sealed segment. The two files are one log: a sealed segment that
265
+ * stops short ends the replay there, and the current log is discarded with the rest of it.
266
+ *
267
+ * Re-applying a sealed segment whose checkpoint already synced the tree is harmless, because the
268
+ * current log holds every later write of the same paths, in order, and is applied after it. What
269
+ * must never happen is the sealed segment outliving the current log's truncation, since replaying
270
+ * it alone would put older content over newer: so the sealed segment is removed, and the
271
+ * directory synced, before {@link openOnce} truncates the current log. (On win32, where
272
+ * {@link fsyncDir} is skipped, NTFS commits the unlink and the later truncation through its
273
+ * metadata journal in order.)
274
+ */
275
+ private replay;
276
+ /** Apply one log file's intact records, in order, into `touched`. */
277
+ private replaySegment;
278
+ /** Create (or truncate) the current log to its header, and make it and its directory entry durable before any record goes in. */
279
+ private createEmptyLog;
280
+ /**
281
+ * Append the batch as one record. The record has reached the operating system when this
282
+ * resolves, so it survives a crash of this process: the next open's replay applies it. A failed
283
+ * append latches the log, and rejects every batch still waiting for its sync, since no sync will
284
+ * ever be made for them.
285
+ */
286
+ private append;
287
+ /**
288
+ * The sync step: one sync of the log makes every record appended so far durable; then each waiting
289
+ * batch is written to the tree, in order, and its `durable` resolved, in order. Called only from a
290
+ * queued task — a commit, {@link sync}, the timer's task or a checkpoint's seal — so it covers
291
+ * exactly the records appended before that task began, and a sealed segment only ever holds
292
+ * synced records whose tree writes are done. Nothing waiting: nothing is touched.
293
+ *
294
+ * A failure anywhere latches the log and rejects every covered `durable`, the ones whose tree
295
+ * write succeeded included: the records are durable and the next open's replay rebuilds the tree
296
+ * from them, but a `durable` is a promise that this process finished the work, and it did not.
297
+ *
298
+ * `owedSince` is the moment the timer fired, when the timer's task runs this: `SyncDeadlines.take`
299
+ * counts the sync's lateness from it rather than from a deadline the timer's own slop missed, and
300
+ * the cover says `window-overrun` once per episode of syncs that started late.
301
+ */
302
+ private syncUnsynced;
303
+ /** The timer fired: run the sync step in the queue. Its failure has latched the log, so it is only logged here, like a background checkpoint's. */
304
+ private syncInBackground;
305
+ /**
306
+ * Latch the log failed on its first fault and reject every batch waiting for a sync that will now
307
+ * never be made, so no caller waits on a `durable` for ever. Returns the error to throw.
308
+ */
309
+ private latch;
310
+ /**
311
+ * Write each entry to its canonical path, creating missing directories; record what the tree was given.
312
+ *
313
+ * NOTE: the write goes straight to the canonical path, so a reader of that path can see it
314
+ * half-written. The committing store's own readers are served from its overlay until the batch's
315
+ * `durable` resolves, and the two store kinds over one directory never share a path, so only a
316
+ * second store of the same kind over the same directory can read a torn file — a shape Invariant
317
+ * 5 already excludes. If that shape is ever supported, write through a temp file and rename.
318
+ */
319
+ private applyBatch;
320
+ /**
321
+ * `mkdir` created at least `dir`'s topmost missing ancestor, whose parent's entry is new too, so
322
+ * every directory from `dir` up to the store's root is marked — a superset of what was created,
323
+ * at most the layout's depth of extra directory syncs per checkpoint. (The created path `mkdir`
324
+ * returns is not compared against: on win32 it comes back in `\\?\` long-path form.)
325
+ */
326
+ private noteCreated;
327
+ /**
328
+ * After an append: re-arm the idle checkpoint, and start one now when the log has passed its size
329
+ * threshold. Nothing once the last release has begun, since it runs the final checkpoint itself.
330
+ */
331
+ private scheduleCheckpoint;
332
+ /** Never awaited by a commit: a commit holds the queue the checkpoint's seal waits in. Its failure has latched the log. */
333
+ private checkpointInBackground;
334
+ private disarmIdleCheckpoint;
335
+ private runCheckpoints;
336
+ /**
337
+ * 1. **Seal**, in the commit queue so no apply is in flight: run the sync step for whatever is
338
+ * still waiting, rename the log to {@link SEALED_WRITE_LOG_FILENAME} and start an empty one, and
339
+ * take the dirty set, leaving an empty one. Commits resume on the new log at once; only this
340
+ * step waits in the queue.
341
+ * 2. **Sync**, off the commit path: every file in the taken set, then every directory. A file
342
+ * deleted since is skipped; one rewritten since is synced with its newer content, which the
343
+ * new log covers too.
344
+ * 3. **Truncate**: unlink the sealed segment and sync the directory.
345
+ *
346
+ * A crash anywhere in this leaves the sealed segment, the current log or both, and the next open
347
+ * replays them in that order (see {@link replay}).
348
+ */
349
+ private checkpointOnce;
350
+ /**
351
+ * Step 1 of {@link checkpointOnce}: the dirty set the sealed segment covers, or `undefined` when
352
+ * there is nothing to seal. The sync step runs first, so the sealed segment holds only synced
353
+ * records whose tree writes are in the set the checkpoint goes on to sync. An unsynced record
354
+ * always has bytes, so `appendedBytes` is never 0 while one waits: the early return cannot skip
355
+ * one, and the final checkpoint on the last release syncs whatever is still waiting.
356
+ */
357
+ private seal;
358
+ private shutDown;
359
+ private releaseResources;
360
+ }
361
+ //# sourceMappingURL=file-write-log.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-write-log.d.ts","sourceRoot":"","sources":["../../src/file-write-log.ts"],"names":[],"mappings":"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"}