@optimystic/db-p2p-storage-fs 0.24.1 → 0.25.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.
- package/README.md +120 -118
- package/dist/src/atomic-write.d.ts +1 -1
- package/dist/src/atomic-write.js +12 -4
- package/dist/src/atomic-write.js.map +1 -1
- package/dist/src/file-storage.d.ts +13 -7
- package/dist/src/file-storage.d.ts.map +1 -1
- package/dist/src/file-storage.js +55 -7
- package/dist/src/file-storage.js.map +1 -1
- package/package.json +3 -3
- package/src/atomic-write.ts +89 -82
- package/src/file-storage.ts +64 -8
package/README.md
CHANGED
|
@@ -1,118 +1,120 @@
|
|
|
1
|
-
# @optimystic/db-p2p-storage-fs
|
|
2
|
-
|
|
3
|
-
Node.js filesystem storage backend for Optimystic peers. Provides:
|
|
4
|
-
|
|
5
|
-
- **`FileRawStorage`** — implements `IRawStorage` so a Node peer persists block
|
|
6
|
-
metadata, revisions, pending transactions, committed transactions,
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
- `@optimystic/db-p2p-storage-
|
|
16
|
-
- `@optimystic/db-p2p-storage-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
import {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
1
|
+
# @optimystic/db-p2p-storage-fs
|
|
2
|
+
|
|
3
|
+
Node.js filesystem storage backend for Optimystic peers. Provides:
|
|
4
|
+
|
|
5
|
+
- **`FileRawStorage`** — implements `IRawStorage` so a Node peer persists block
|
|
6
|
+
metadata, revisions, pending transactions, committed transactions, commit
|
|
7
|
+
proofs, and
|
|
8
|
+
materialized blocks durably across restarts.
|
|
9
|
+
- **`FileKVStore`** — implements `IKVStore` for the persistent transaction state
|
|
10
|
+
used to recover crashed two-phase commits.
|
|
11
|
+
|
|
12
|
+
This package targets plain Node.js. Use the sibling adapter for other
|
|
13
|
+
environments:
|
|
14
|
+
|
|
15
|
+
- `@optimystic/db-p2p-storage-ns` — NativeScript (iOS/Android, SQLite)
|
|
16
|
+
- `@optimystic/db-p2p-storage-rn` — React Native (MMKV)
|
|
17
|
+
- `@optimystic/db-p2p-storage-web` — Browser (IndexedDB)
|
|
18
|
+
|
|
19
|
+
## Install
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
yarn add @optimystic/db-p2p-storage-fs @optimystic/db-p2p @optimystic/db-core
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
import { FileRawStorage, FileKVStore } from '@optimystic/db-p2p-storage-fs';
|
|
29
|
+
import { createLibp2pNode } from '@optimystic/db-p2p';
|
|
30
|
+
|
|
31
|
+
const rawStorage = new FileRawStorage('/var/lib/my-peer/data');
|
|
32
|
+
const kvStore = new FileKVStore('/var/lib/my-peer/data');
|
|
33
|
+
|
|
34
|
+
const libp2p = await createLibp2pNode({
|
|
35
|
+
bootstrapNodes: [/* … */],
|
|
36
|
+
networkName: 'my-network',
|
|
37
|
+
rawStorage,
|
|
38
|
+
kvStore,
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Both constructors take a single `basePath` — the directory under which all
|
|
43
|
+
data is stored. They can share the same `basePath` in practice because their
|
|
44
|
+
top-level names do not collide: block data lives under `<blockId>/`
|
|
45
|
+
subdirectories (block ids are content-address hashes), while KV data lives
|
|
46
|
+
under directories named by the first segment of each key (a `/`-separated key
|
|
47
|
+
becomes nested subdirectories — e.g. `coordinator/key1` → `coordinator/key1.json`).
|
|
48
|
+
Sharing is safe only as long as no block id equals a KV key's first segment;
|
|
49
|
+
give them separate `basePath`s if you cannot guarantee that.
|
|
50
|
+
|
|
51
|
+
## On-disk layout
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
<basePath>/
|
|
55
|
+
<blockId>/
|
|
56
|
+
meta.json — BlockMetadata (JSON)
|
|
57
|
+
revs/<rev>.json — ActionId for that revision number
|
|
58
|
+
pend/<id>.json — pending Transform (two-phase commit, before promotion)
|
|
59
|
+
actions/<id>.json — committed Transform
|
|
60
|
+
proofs/<rev>.json — BlockCommitProof retained for that revision
|
|
61
|
+
blocks/<id>.json — materialized IBlock snapshot
|
|
62
|
+
<key-segment>/
|
|
63
|
+
<key-segment>.json — FileKVStore value; key "/" separators become subdirectories
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Action ids that contain a colon (e.g. `tx:abcd1234`) are percent-encoded in
|
|
67
|
+
filenames (`tx%3Aabcd1234.json`) for Windows compatibility; the storage layer
|
|
68
|
+
encodes and decodes transparently so callers always work with the canonical
|
|
69
|
+
id form.
|
|
70
|
+
|
|
71
|
+
## Atomic writes
|
|
72
|
+
|
|
73
|
+
Every write goes through `atomic-write.ts`: the new content is written to a
|
|
74
|
+
`.tmp` sibling, then renamed over the canonical path. A crash mid-write
|
|
75
|
+
therefore leaves either the complete old file or the complete new file — never
|
|
76
|
+
a partial/torn one.
|
|
77
|
+
|
|
78
|
+
## Identity
|
|
79
|
+
|
|
80
|
+
Unlike the `ns`/`rn`/`web` adapters, this package ships **no** identity module
|
|
81
|
+
and no `loadOrCreateFSPeerKey` helper. The reference peer that uses this adapter
|
|
82
|
+
does not persist its libp2p private key, so an fs-backed node gets a fresh
|
|
83
|
+
ephemeral peer id on every restart. Adding durable identity is a separate
|
|
84
|
+
feature — see Known limitations below.
|
|
85
|
+
|
|
86
|
+
## Tests
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
yarn test # mocha, minimal reporter
|
|
90
|
+
yarn test:verbose # mocha, spec reporter
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Two layers run here, both over a per-test `fs.mkdtemp` fixture with `afterEach`
|
|
94
|
+
cleanup:
|
|
95
|
+
|
|
96
|
+
- **Shared conformance suite** — `runRawStorageConformance('FileSystem', …)` from
|
|
97
|
+
`@optimystic/db-p2p/testing/conformance`, the one cross-backend parity target. It proves the
|
|
98
|
+
fs backend (now `KvRawStorage` over a `FileStoreDriver`) behaves identically to
|
|
99
|
+
every other backend: round-trips, `listRevisions` ordering, promote atomicity +
|
|
100
|
+
the exact missing-pend error, clone-on-store/read (structural via the byte
|
|
101
|
+
boundary), drain-before-yield iteration, and a `BlockStorage` parity slice.
|
|
102
|
+
- **fs-only tests** (`node:assert`) — the behaviors the shared suite can't cover:
|
|
103
|
+
atomic writes + torn-file corruption tolerance, `readdir` error discrimination,
|
|
104
|
+
colon-encoded filenames + the POSIX legacy raw-colon fallback, the directory-based
|
|
105
|
+
`listBlockIds` meta-gate, and `FileKVStore.list`/`delete`.
|
|
106
|
+
|
|
107
|
+
## Known limitations
|
|
108
|
+
|
|
109
|
+
**No cross-process lock.** Two separate Node processes pointing at the same
|
|
110
|
+
`basePath` can interleave writes with no coordination. The constructor carries
|
|
111
|
+
a TODO (`file-storage.ts:52`) to integrate
|
|
112
|
+
[`proper-lockfile`](https://www.npmjs.com/package/proper-lockfile) along with
|
|
113
|
+
an explicit `dispose()` pattern. Until that lands, `FileRawStorage` is
|
|
114
|
+
single-process only.
|
|
115
|
+
|
|
116
|
+
**Ephemeral peer identity.** There is no `loadOrCreateFSPeerKey` equivalent.
|
|
117
|
+
A Node peer backed by `FileRawStorage` gets a new libp2p peer id each restart.
|
|
118
|
+
If your use case requires a stable, restart-surviving identity, a future
|
|
119
|
+
`feat-fs-peer-identity` feature should add the key-persistence helper — it is
|
|
120
|
+
deliberately out of scope here.
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* concurrent reader only ever sees the complete old file or the complete new
|
|
7
7
|
* file — never a torn/half-written one. After the rename we best-effort fsync
|
|
8
8
|
* the containing directory so the rename itself survives power loss on POSIX;
|
|
9
|
-
* that directory fsync is unsupported on win32 and
|
|
9
|
+
* that directory fsync is unsupported on win32 and is skipped there.
|
|
10
10
|
*
|
|
11
11
|
* On any failure the temp file is removed (best-effort) so a crashed write does
|
|
12
12
|
* not leave the canonical path damaged. A crash *between* the temp write and the
|
package/dist/src/atomic-write.js
CHANGED
|
@@ -14,7 +14,7 @@ let tempCounter = 0;
|
|
|
14
14
|
* concurrent reader only ever sees the complete old file or the complete new
|
|
15
15
|
* file — never a torn/half-written one. After the rename we best-effort fsync
|
|
16
16
|
* the containing directory so the rename itself survives power loss on POSIX;
|
|
17
|
-
* that directory fsync is unsupported on win32 and
|
|
17
|
+
* that directory fsync is unsupported on win32 and is skipped there.
|
|
18
18
|
*
|
|
19
19
|
* On any failure the temp file is removed (best-effort) so a crashed write does
|
|
20
20
|
* not leave the canonical path damaged. A crash *between* the temp write and the
|
|
@@ -62,17 +62,25 @@ export async function atomicWriteFile(filePath, content) {
|
|
|
62
62
|
}
|
|
63
63
|
/**
|
|
64
64
|
* Best-effort fsync of a directory so a completed rename is durable. POSIX needs
|
|
65
|
-
* this;
|
|
66
|
-
*
|
|
65
|
+
* this; platforms that reject opening a directory for fsync throw, and we ignore
|
|
66
|
+
* that rather than failing the write.
|
|
67
|
+
*
|
|
68
|
+
* Skipped outright on win32: there `fs.open(dir, 'r')` SUCCEEDS and only the
|
|
69
|
+
* following `handle.sync()` fails with EPERM (swallowed), so the open/close pair
|
|
70
|
+
* was guaranteed wasted work — exactly half of all `fs.open` calls a write
|
|
71
|
+
* workload makes. Durability is unchanged on win32 (the sync never succeeded
|
|
72
|
+
* there); the on-disk layout is untouched.
|
|
67
73
|
*/
|
|
68
74
|
async function fsyncDir(dir) {
|
|
75
|
+
if (process.platform === 'win32')
|
|
76
|
+
return;
|
|
69
77
|
let handle;
|
|
70
78
|
try {
|
|
71
79
|
handle = await fs.open(dir, 'r');
|
|
72
80
|
await handle.sync();
|
|
73
81
|
}
|
|
74
82
|
catch {
|
|
75
|
-
// Directory fsync unsupported here
|
|
83
|
+
// Directory fsync unsupported here — nothing to do.
|
|
76
84
|
}
|
|
77
85
|
finally {
|
|
78
86
|
if (handle)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"atomic-write.js","sourceRoot":"","sources":["../../src/atomic-write.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,gFAAgF;AAChF,4EAA4E;AAC5E,+EAA+E;AAC/E,+EAA+E;AAC/E,uDAAuD;AACvD,IAAI,WAAW,GAAG,CAAC,CAAC;AAEpB;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,QAAgB,EAAE,OAA4B;IACnF,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEzC,qFAAqF;IACrF,iEAAiE;IACjE,oFAAoF;IACpF,qFAAqF;IACrF,mEAAmE;IACnE,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,GAAG,IAAI,WAAW,EAAE,MAAM,CAAC,CAAC;IAEjG,IAAI,MAAiC,CAAC;IACtC,IAAI,CAAC;QACJ,MAAM,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QACrC,MAAM,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAChC,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACrB,MAAM,GAAG,SAAS,CAAC;QACnB,yEAAyE;QACzE,0EAA0E;QAC1E,2EAA2E;QAC3E,6EAA6E;QAC7E,6EAA6E;QAC7E,6EAA6E;QAC7E,4EAA4E;QAC5E,+EAA+E;QAC/E,MAAM,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,IAAI,MAAM;YAAE,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAqB,CAAC,CAAC,CAAC;QACpE,MAAM,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAyC,CAAC,CAAC,CAAC;QAChF,MAAM,GAAG,CAAC;IACX,CAAC;IAED,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC;AACrB,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"atomic-write.js","sourceRoot":"","sources":["../../src/atomic-write.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,gFAAgF;AAChF,4EAA4E;AAC5E,+EAA+E;AAC/E,+EAA+E;AAC/E,uDAAuD;AACvD,IAAI,WAAW,GAAG,CAAC,CAAC;AAEpB;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,QAAgB,EAAE,OAA4B;IACnF,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,MAAM,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEzC,qFAAqF;IACrF,iEAAiE;IACjE,oFAAoF;IACpF,qFAAqF;IACrF,mEAAmE;IACnE,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,GAAG,IAAI,WAAW,EAAE,MAAM,CAAC,CAAC;IAEjG,IAAI,MAAiC,CAAC;IACtC,IAAI,CAAC;QACJ,MAAM,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QACrC,MAAM,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAChC,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACrB,MAAM,GAAG,SAAS,CAAC;QACnB,yEAAyE;QACzE,0EAA0E;QAC1E,2EAA2E;QAC3E,6EAA6E;QAC7E,6EAA6E;QAC7E,6EAA6E;QAC7E,4EAA4E;QAC5E,+EAA+E;QAC/E,MAAM,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACpC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACd,IAAI,MAAM;YAAE,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAqB,CAAC,CAAC,CAAC;QACpE,MAAM,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,GAAyC,CAAC,CAAC,CAAC;QAChF,MAAM,GAAG,CAAC;IACX,CAAC;IAED,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC;AACrB,CAAC;AAED;;;;;;;;;;GAUG;AACH,KAAK,UAAU,QAAQ,CAAC,GAAW;IAClC,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO;IACzC,IAAI,MAAiC,CAAC;IACtC,IAAI,CAAC;QACJ,MAAM,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACjC,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;IACrB,CAAC;IAAC,MAAM,CAAC;QACR,oDAAoD;IACrD,CAAC;YAAS,CAAC;QACV,IAAI,MAAM;YAAE,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAqB,CAAC,CAAC,CAAC;IACrE,CAAC;AACF,CAAC"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { BlockId, ActionId } from "@optimystic/db-core";
|
|
2
|
-
import { KvRawStorage, type RawStoreDriver } from "@optimystic/db-p2p";
|
|
2
|
+
import { KvRawStorage, type RawStoreDriver, type StoreIdentity } from "@optimystic/db-p2p";
|
|
3
3
|
/**
|
|
4
|
-
* Filesystem {@link RawStoreDriver}: the
|
|
5
|
-
* to
|
|
6
|
-
* (`{meta.json,revs/,pend/,actions/,blocks/}`). The directory tree is a
|
|
4
|
+
* Filesystem {@link RawStoreDriver}: the six logical block-storage stores mapped
|
|
5
|
+
* to six paths under `basePath/<blockId>/`
|
|
6
|
+
* (`{meta.json,revs/,pend/,actions/,proofs/,blocks/}`). The directory tree is a
|
|
7
7
|
* deliberate, human-inspectable/debuggable layout — it is NOT flattened into
|
|
8
8
|
* encoded-filename KV keys.
|
|
9
9
|
*
|
|
@@ -15,7 +15,9 @@ import { KvRawStorage, type RawStoreDriver } from "@optimystic/db-p2p";
|
|
|
15
15
|
*/
|
|
16
16
|
export declare class FileStoreDriver implements RawStoreDriver {
|
|
17
17
|
private readonly basePath;
|
|
18
|
+
private readonly identity;
|
|
18
19
|
constructor(basePath: string);
|
|
20
|
+
storeIdentity(): StoreIdentity;
|
|
19
21
|
getMetadata(blockId: BlockId): Promise<Uint8Array | undefined>;
|
|
20
22
|
putMetadata(blockId: BlockId, value: Uint8Array): Promise<void>;
|
|
21
23
|
getRevision(blockId: BlockId, rev: number): Promise<Uint8Array | undefined>;
|
|
@@ -27,6 +29,8 @@ export declare class FileStoreDriver implements RawStoreDriver {
|
|
|
27
29
|
listPendingActionIds(blockId: BlockId): AsyncIterable<ActionId>;
|
|
28
30
|
getTransaction(blockId: BlockId, actionId: ActionId): Promise<Uint8Array | undefined>;
|
|
29
31
|
putTransaction(blockId: BlockId, actionId: ActionId, value: Uint8Array): Promise<void>;
|
|
32
|
+
getProof(blockId: BlockId, rev: number): Promise<Uint8Array | undefined>;
|
|
33
|
+
putProof(blockId: BlockId, rev: number, value: Uint8Array): Promise<void>;
|
|
30
34
|
getMaterialized(blockId: BlockId, actionId: ActionId): Promise<Uint8Array | undefined>;
|
|
31
35
|
putMaterialized(blockId: BlockId, actionId: ActionId, value: Uint8Array): Promise<void>;
|
|
32
36
|
deleteMaterialized(blockId: BlockId, actionId: ActionId): Promise<void>;
|
|
@@ -37,6 +41,7 @@ export declare class FileStoreDriver implements RawStoreDriver {
|
|
|
37
41
|
private getBlockPath;
|
|
38
42
|
private getMetadataPath;
|
|
39
43
|
private getRevisionPath;
|
|
44
|
+
private getProofPath;
|
|
40
45
|
private getPendingActionPath;
|
|
41
46
|
private getActionPath;
|
|
42
47
|
private getMaterializedPath;
|
|
@@ -51,13 +56,14 @@ export declare class FileStoreDriver implements RawStoreDriver {
|
|
|
51
56
|
* imports keep resolving; the kernel supplies the `IRawStorage` surface and the
|
|
52
57
|
* driver supplies fs behavior.
|
|
53
58
|
*
|
|
54
|
-
* `listBlockIds`/`getApproximateBytesUsed` are re-declared here as
|
|
55
|
-
* (the fs driver always implements them, so the kernel constructor always
|
|
56
|
-
* them) — the base declares them optional, but every fs consumer relies on them.
|
|
59
|
+
* `listBlockIds`/`getApproximateBytesUsed`/`getStoreIdentity` are re-declared here as
|
|
60
|
+
* always-present (the fs driver always implements them, so the kernel constructor always
|
|
61
|
+
* wires them) — the base declares them optional, but every fs consumer relies on them.
|
|
57
62
|
*/
|
|
58
63
|
export declare class FileRawStorage extends KvRawStorage {
|
|
59
64
|
listBlockIds: () => AsyncIterable<BlockId>;
|
|
60
65
|
getApproximateBytesUsed: () => Promise<number>;
|
|
66
|
+
getStoreIdentity: () => StoreIdentity;
|
|
61
67
|
constructor(basePath: string);
|
|
62
68
|
}
|
|
63
69
|
//# sourceMappingURL=file-storage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-storage.d.ts","sourceRoot":"","sources":["../../src/file-storage.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,KAAK,cAAc,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"file-storage.d.ts","sourceRoot":"","sources":["../../src/file-storage.ts"],"names":[],"mappings":"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"}
|
package/dist/src/file-storage.js
CHANGED
|
@@ -35,9 +35,9 @@ function isParseableJson(bytes) {
|
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
/**
|
|
38
|
-
* Filesystem {@link RawStoreDriver}: the
|
|
39
|
-
* to
|
|
40
|
-
* (`{meta.json,revs/,pend/,actions/,blocks/}`). The directory tree is a
|
|
38
|
+
* Filesystem {@link RawStoreDriver}: the six logical block-storage stores mapped
|
|
39
|
+
* to six paths under `basePath/<blockId>/`
|
|
40
|
+
* (`{meta.json,revs/,pend/,actions/,proofs/,blocks/}`). The directory tree is a
|
|
41
41
|
* deliberate, human-inspectable/debuggable layout — it is NOT flattened into
|
|
42
42
|
* encoded-filename KV keys.
|
|
43
43
|
*
|
|
@@ -49,9 +49,43 @@ function isParseableJson(bytes) {
|
|
|
49
49
|
*/
|
|
50
50
|
export class FileStoreDriver {
|
|
51
51
|
basePath;
|
|
52
|
+
identity;
|
|
52
53
|
constructor(basePath) {
|
|
53
54
|
this.basePath = basePath;
|
|
54
55
|
// TODO: use https://www.npmjs.com/package/proper-lockfile to take a lock on the basePath, also introduce explicit dispose pattern
|
|
56
|
+
// The directory this driver is backed by, resolved once here: `path.resolve` is
|
|
57
|
+
// cwd-dependent, and capturing it at construction is the correct reading — two drivers
|
|
58
|
+
// built from the same RELATIVE path under different cwds genuinely address different
|
|
59
|
+
// directories and must not compare equal. An empty basePath resolves to the cwd;
|
|
60
|
+
// nothing special-cases it. (A whitespace-only basePath is NOT the cwd — `path.resolve`
|
|
61
|
+
// is pure string work, so `' '` names a child directory called `' '`.)
|
|
62
|
+
// Lowercased on win32 because Windows paths are case-insensitive: `C:\Foo` and `C:\foo`
|
|
63
|
+
// are one directory and must produce one identity.
|
|
64
|
+
// NOTE: aliases of one directory that this does NOT collapse, and so read as two
|
|
65
|
+
// identities: symlinks, junctions, UNC-versus-mapped-drive spellings, and case-differing
|
|
66
|
+
// spellings on a case-INSENSITIVE non-Windows volume (the default on macOS) — platform is
|
|
67
|
+
// the only signal available synchronously, and case-folding every darwin path would be
|
|
68
|
+
// wrong on a case-sensitive volume. `fs.realpath` resolves all of these, but it is async
|
|
69
|
+
// (this constructor is not) and requires the directory to already exist. Revisit if an
|
|
70
|
+
// alias ever bites. All of these fail in the SAFE direction: a missed alias reports two
|
|
71
|
+
// identities for one directory, so an identity-keyed consumer declines to merge and gets
|
|
72
|
+
// today's behavior.
|
|
73
|
+
// NOTE: the win32 fold is the one branch that can err in the UNSAFE direction — Windows
|
|
74
|
+
// 10+ supports per-directory case sensitivity (`fsutil file setCaseSensitiveInfo`), and
|
|
75
|
+
// on such a directory `X:\p\Foo` and `X:\p\foo` are two directories folded onto ONE
|
|
76
|
+
// identity. That merging consumer now exists — `withReadCache` (db-p2p) shares ONE read
|
|
77
|
+
// cache per identity — so on such a directory the two stores would read through one cache
|
|
78
|
+
// and see each other's blocks, and if the second cache is built directly rather than
|
|
79
|
+
// through that helper, `SharedCachePool.registerStore` refuses it outright (one cache per
|
|
80
|
+
// backing store) and construction throws. Not addressable synchronously either (the flag is a
|
|
81
|
+
// per-directory filesystem query). Revisit if Optimystic ever targets a
|
|
82
|
+
// case-sensitive-enabled Windows directory; until then the fold is right for every
|
|
83
|
+
// ordinary Windows volume.
|
|
84
|
+
const resolved = path.resolve(basePath);
|
|
85
|
+
this.identity = `file:${process.platform === 'win32' ? resolved.toLowerCase() : resolved}`;
|
|
86
|
+
}
|
|
87
|
+
storeIdentity() {
|
|
88
|
+
return this.identity;
|
|
55
89
|
}
|
|
56
90
|
// --- metadata ---
|
|
57
91
|
async getMetadata(blockId) {
|
|
@@ -163,6 +197,17 @@ export class FileStoreDriver {
|
|
|
163
197
|
async putTransaction(blockId, actionId, value) {
|
|
164
198
|
await atomicWriteFile(this.getActionPath(blockId, actionId), value);
|
|
165
199
|
}
|
|
200
|
+
// --- proofs ---
|
|
201
|
+
// Keyed by (blockId, rev) like the revisions store, but JSON-valued like the action
|
|
202
|
+
// stores — so it takes the corrupt-content-as-missing guard the revisions store does
|
|
203
|
+
// not, and the filename carries no colon to encode. Deliberately no delete: a proof
|
|
204
|
+
// lives and dies with its revision record (see RawStoreDriver.getProof).
|
|
205
|
+
async getProof(blockId, rev) {
|
|
206
|
+
return this.readBytesIfExists(this.getProofPath(blockId, rev), true);
|
|
207
|
+
}
|
|
208
|
+
async putProof(blockId, rev, value) {
|
|
209
|
+
await atomicWriteFile(this.getProofPath(blockId, rev), value);
|
|
210
|
+
}
|
|
166
211
|
// --- materialized ---
|
|
167
212
|
async getMaterialized(blockId, actionId) {
|
|
168
213
|
return this.readActionScopedBytes(this.getMaterializedPath(blockId, actionId), this.getMaterializedPath(blockId, actionId, false));
|
|
@@ -200,7 +245,7 @@ export class FileStoreDriver {
|
|
|
200
245
|
}
|
|
201
246
|
// --- optional passthroughs ---
|
|
202
247
|
async *listBlockIds() {
|
|
203
|
-
// The block layout is `basePath/<blockId>/{meta.json,revs/,pend/,actions/,blocks/}`
|
|
248
|
+
// The block layout is `basePath/<blockId>/{meta.json,revs/,pend/,actions/,proofs/,blocks/}`
|
|
204
249
|
// (see getBlockPath), so the direct children of basePath are the per-block directories
|
|
205
250
|
// and each directory NAME is the blockId (used raw, no encoding). Filter to directories
|
|
206
251
|
// so a stray file can't be mistaken for a block; `*.tmp` atomic-write orphans live inside
|
|
@@ -291,6 +336,9 @@ export class FileStoreDriver {
|
|
|
291
336
|
getRevisionPath(blockId, rev) {
|
|
292
337
|
return path.join(this.getBlockPath(blockId), 'revs', `${rev}.json`);
|
|
293
338
|
}
|
|
339
|
+
getProofPath(blockId, rev) {
|
|
340
|
+
return path.join(this.getBlockPath(blockId), 'proofs', `${rev}.json`);
|
|
341
|
+
}
|
|
294
342
|
// `encoded` controls colon handling: writes and canonical reads use the
|
|
295
343
|
// percent-encoded filename (encoded = true); the legacy raw-colon fallback
|
|
296
344
|
// (see readActionScopedBytes) passes encoded = false to reach pre-encode
|
|
@@ -373,9 +421,9 @@ export class FileStoreDriver {
|
|
|
373
421
|
* imports keep resolving; the kernel supplies the `IRawStorage` surface and the
|
|
374
422
|
* driver supplies fs behavior.
|
|
375
423
|
*
|
|
376
|
-
* `listBlockIds`/`getApproximateBytesUsed` are re-declared here as
|
|
377
|
-
* (the fs driver always implements them, so the kernel constructor always
|
|
378
|
-
* them) — the base declares them optional, but every fs consumer relies on them.
|
|
424
|
+
* `listBlockIds`/`getApproximateBytesUsed`/`getStoreIdentity` are re-declared here as
|
|
425
|
+
* always-present (the fs driver always implements them, so the kernel constructor always
|
|
426
|
+
* wires them) — the base declares them optional, but every fs consumer relies on them.
|
|
379
427
|
*/
|
|
380
428
|
export class FileRawStorage extends KvRawStorage {
|
|
381
429
|
constructor(basePath) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"file-storage.js","sourceRoot":"","sources":["../../src/file-storage.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"file-storage.js","sourceRoot":"","sources":["../../src/file-storage.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@optimystic/db-p2p-storage-fs",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Node.js filesystem storage backend for @optimystic/db-p2p",
|
|
6
6
|
"main": "dist/src/index.js",
|
|
@@ -48,8 +48,8 @@
|
|
|
48
48
|
"typescript": "^5.9.3"
|
|
49
49
|
},
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"@optimystic/db-core": "^0.
|
|
52
|
-
"@optimystic/db-p2p": "^0.
|
|
51
|
+
"@optimystic/db-core": "^0.25.0",
|
|
52
|
+
"@optimystic/db-p2p": "^0.25.0",
|
|
53
53
|
"debug": "^4.4.3"
|
|
54
54
|
}
|
|
55
55
|
}
|
package/src/atomic-write.ts
CHANGED
|
@@ -1,82 +1,89 @@
|
|
|
1
|
-
import { promises as fs } from 'fs';
|
|
2
|
-
import * as path from 'path';
|
|
3
|
-
|
|
4
|
-
// Per-process monotonic counter for unique temp names. Combined with the pid it
|
|
5
|
-
// makes each temp path unique across concurrent writers to the same logical
|
|
6
|
-
// target — even two FileRawStorage/FileKVStore instances in one process, which
|
|
7
|
-
// do not lock (see the proper-lockfile TODO in file-storage.ts). Deterministic
|
|
8
|
-
// and collision-safe, unlike Math.random()/Date.now().
|
|
9
|
-
let tempCounter = 0;
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Atomically write `content` to `filePath`.
|
|
13
|
-
*
|
|
14
|
-
* Writes to a unique `*.tmp` sibling, fsyncs the data, then renames it into
|
|
15
|
-
* place. `rename` over an existing file is atomic on POSIX and NTFS, so a
|
|
16
|
-
* concurrent reader only ever sees the complete old file or the complete new
|
|
17
|
-
* file — never a torn/half-written one. After the rename we best-effort fsync
|
|
18
|
-
* the containing directory so the rename itself survives power loss on POSIX;
|
|
19
|
-
* that directory fsync is unsupported on win32 and
|
|
20
|
-
*
|
|
21
|
-
* On any failure the temp file is removed (best-effort) so a crashed write does
|
|
22
|
-
* not leave the canonical path damaged. A crash *between* the temp write and the
|
|
23
|
-
* rename leaves only an inert `*.tmp` sibling — never read (reads target
|
|
24
|
-
* canonical paths) and skipped by `.json` directory scans.
|
|
25
|
-
*
|
|
26
|
-
* `content` is `string | Uint8Array`: `FileKVStore` writes strings, while the
|
|
27
|
-
* `KvRawStorage`-backed `FileStoreDriver` writes the kernel's raw value bytes.
|
|
28
|
-
* `FileHandle.writeFile` writes either losslessly — a `Uint8Array` is written
|
|
29
|
-
* byte-for-byte, so non-ASCII JSON round-trips exactly.
|
|
30
|
-
*/
|
|
31
|
-
export async function atomicWriteFile(filePath: string, content: string | Uint8Array): Promise<void> {
|
|
32
|
-
const dir = path.dirname(filePath);
|
|
33
|
-
await fs.mkdir(dir, { recursive: true });
|
|
34
|
-
|
|
35
|
-
// Suffix ends in `.tmp` (not `.json`) so listPendingTransactions / FileKVStore.list,
|
|
36
|
-
// which filter on `.json`, never surface an in-flight temp file.
|
|
37
|
-
// NOTE: a crash between open and rename leaves an inert `*.tmp` orphan (never read,
|
|
38
|
-
// skipped by `.json` scans). No cleanup sweep exists; if a crash-looping writer ever
|
|
39
|
-
// accumulates many, add a startup sweep of stale `*.tmp` siblings.
|
|
40
|
-
const tmpPath = path.join(dir, `${path.basename(filePath)}.${process.pid}.${tempCounter++}.tmp`);
|
|
41
|
-
|
|
42
|
-
let handle: fs.FileHandle | undefined;
|
|
43
|
-
try {
|
|
44
|
-
handle = await fs.open(tmpPath, 'w');
|
|
45
|
-
await handle.writeFile(content);
|
|
46
|
-
await handle.sync();
|
|
47
|
-
await handle.close();
|
|
48
|
-
handle = undefined;
|
|
49
|
-
// NOTE: on win32, rename-over-existing can throw EPERM/EACCES/EBUSY if a
|
|
50
|
-
// concurrent reader holds the target open without FILE_SHARE_DELETE (Node
|
|
51
|
-
// readIfExists/get open→read→close in a tiny window, so it's rare). Modern
|
|
52
|
-
// libuv retries some cases; if this ever surfaces as spurious write failures
|
|
53
|
-
// under concurrent read+write on Windows, add a bounded retry loop here (the
|
|
54
|
-
// write-file-atomic package does exactly this). Conditional — the adapter is
|
|
55
|
-
// already last-writer-wins with no cross-process lock (proper-lockfile TODO
|
|
56
|
-
// in file-storage.ts), so it is not reachable under current single-writer use.
|
|
57
|
-
await fs.rename(tmpPath, filePath);
|
|
58
|
-
} catch (err) {
|
|
59
|
-
if (handle) await handle.close().catch(() => { /* best-effort */ });
|
|
60
|
-
await fs.unlink(tmpPath).catch(() => { /* best-effort: temp may not exist */ });
|
|
61
|
-
throw err;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
await fsyncDir(dir);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Best-effort fsync of a directory so a completed rename is durable. POSIX needs
|
|
69
|
-
* this;
|
|
70
|
-
*
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
1
|
+
import { promises as fs } from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
|
|
4
|
+
// Per-process monotonic counter for unique temp names. Combined with the pid it
|
|
5
|
+
// makes each temp path unique across concurrent writers to the same logical
|
|
6
|
+
// target — even two FileRawStorage/FileKVStore instances in one process, which
|
|
7
|
+
// do not lock (see the proper-lockfile TODO in file-storage.ts). Deterministic
|
|
8
|
+
// and collision-safe, unlike Math.random()/Date.now().
|
|
9
|
+
let tempCounter = 0;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Atomically write `content` to `filePath`.
|
|
13
|
+
*
|
|
14
|
+
* Writes to a unique `*.tmp` sibling, fsyncs the data, then renames it into
|
|
15
|
+
* place. `rename` over an existing file is atomic on POSIX and NTFS, so a
|
|
16
|
+
* concurrent reader only ever sees the complete old file or the complete new
|
|
17
|
+
* file — never a torn/half-written one. After the rename we best-effort fsync
|
|
18
|
+
* the containing directory so the rename itself survives power loss on POSIX;
|
|
19
|
+
* that directory fsync is unsupported on win32 and is skipped there.
|
|
20
|
+
*
|
|
21
|
+
* On any failure the temp file is removed (best-effort) so a crashed write does
|
|
22
|
+
* not leave the canonical path damaged. A crash *between* the temp write and the
|
|
23
|
+
* rename leaves only an inert `*.tmp` sibling — never read (reads target
|
|
24
|
+
* canonical paths) and skipped by `.json` directory scans.
|
|
25
|
+
*
|
|
26
|
+
* `content` is `string | Uint8Array`: `FileKVStore` writes strings, while the
|
|
27
|
+
* `KvRawStorage`-backed `FileStoreDriver` writes the kernel's raw value bytes.
|
|
28
|
+
* `FileHandle.writeFile` writes either losslessly — a `Uint8Array` is written
|
|
29
|
+
* byte-for-byte, so non-ASCII JSON round-trips exactly.
|
|
30
|
+
*/
|
|
31
|
+
export async function atomicWriteFile(filePath: string, content: string | Uint8Array): Promise<void> {
|
|
32
|
+
const dir = path.dirname(filePath);
|
|
33
|
+
await fs.mkdir(dir, { recursive: true });
|
|
34
|
+
|
|
35
|
+
// Suffix ends in `.tmp` (not `.json`) so listPendingTransactions / FileKVStore.list,
|
|
36
|
+
// which filter on `.json`, never surface an in-flight temp file.
|
|
37
|
+
// NOTE: a crash between open and rename leaves an inert `*.tmp` orphan (never read,
|
|
38
|
+
// skipped by `.json` scans). No cleanup sweep exists; if a crash-looping writer ever
|
|
39
|
+
// accumulates many, add a startup sweep of stale `*.tmp` siblings.
|
|
40
|
+
const tmpPath = path.join(dir, `${path.basename(filePath)}.${process.pid}.${tempCounter++}.tmp`);
|
|
41
|
+
|
|
42
|
+
let handle: fs.FileHandle | undefined;
|
|
43
|
+
try {
|
|
44
|
+
handle = await fs.open(tmpPath, 'w');
|
|
45
|
+
await handle.writeFile(content);
|
|
46
|
+
await handle.sync();
|
|
47
|
+
await handle.close();
|
|
48
|
+
handle = undefined;
|
|
49
|
+
// NOTE: on win32, rename-over-existing can throw EPERM/EACCES/EBUSY if a
|
|
50
|
+
// concurrent reader holds the target open without FILE_SHARE_DELETE (Node
|
|
51
|
+
// readIfExists/get open→read→close in a tiny window, so it's rare). Modern
|
|
52
|
+
// libuv retries some cases; if this ever surfaces as spurious write failures
|
|
53
|
+
// under concurrent read+write on Windows, add a bounded retry loop here (the
|
|
54
|
+
// write-file-atomic package does exactly this). Conditional — the adapter is
|
|
55
|
+
// already last-writer-wins with no cross-process lock (proper-lockfile TODO
|
|
56
|
+
// in file-storage.ts), so it is not reachable under current single-writer use.
|
|
57
|
+
await fs.rename(tmpPath, filePath);
|
|
58
|
+
} catch (err) {
|
|
59
|
+
if (handle) await handle.close().catch(() => { /* best-effort */ });
|
|
60
|
+
await fs.unlink(tmpPath).catch(() => { /* best-effort: temp may not exist */ });
|
|
61
|
+
throw err;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
await fsyncDir(dir);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Best-effort fsync of a directory so a completed rename is durable. POSIX needs
|
|
69
|
+
* this; platforms that reject opening a directory for fsync throw, and we ignore
|
|
70
|
+
* that rather than failing the write.
|
|
71
|
+
*
|
|
72
|
+
* Skipped outright on win32: there `fs.open(dir, 'r')` SUCCEEDS and only the
|
|
73
|
+
* following `handle.sync()` fails with EPERM (swallowed), so the open/close pair
|
|
74
|
+
* was guaranteed wasted work — exactly half of all `fs.open` calls a write
|
|
75
|
+
* workload makes. Durability is unchanged on win32 (the sync never succeeded
|
|
76
|
+
* there); the on-disk layout is untouched.
|
|
77
|
+
*/
|
|
78
|
+
async function fsyncDir(dir: string): Promise<void> {
|
|
79
|
+
if (process.platform === 'win32') return;
|
|
80
|
+
let handle: fs.FileHandle | undefined;
|
|
81
|
+
try {
|
|
82
|
+
handle = await fs.open(dir, 'r');
|
|
83
|
+
await handle.sync();
|
|
84
|
+
} catch {
|
|
85
|
+
// Directory fsync unsupported here — nothing to do.
|
|
86
|
+
} finally {
|
|
87
|
+
if (handle) await handle.close().catch(() => { /* best-effort */ });
|
|
88
|
+
}
|
|
89
|
+
}
|
package/src/file-storage.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { promises as fs } from 'fs';
|
|
2
2
|
import * as path from 'path';
|
|
3
3
|
import type { BlockId, ActionId } from "@optimystic/db-core";
|
|
4
|
-
import { KvRawStorage, type RawStoreDriver } from "@optimystic/db-p2p";
|
|
4
|
+
import { KvRawStorage, type RawStoreDriver, type StoreIdentity } from "@optimystic/db-p2p";
|
|
5
5
|
import { createLogger } from './logger.js';
|
|
6
6
|
import { atomicWriteFile } from './atomic-write.js';
|
|
7
7
|
|
|
@@ -40,9 +40,9 @@ function isParseableJson(bytes: Uint8Array): boolean {
|
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
/**
|
|
43
|
-
* Filesystem {@link RawStoreDriver}: the
|
|
44
|
-
* to
|
|
45
|
-
* (`{meta.json,revs/,pend/,actions/,blocks/}`). The directory tree is a
|
|
43
|
+
* Filesystem {@link RawStoreDriver}: the six logical block-storage stores mapped
|
|
44
|
+
* to six paths under `basePath/<blockId>/`
|
|
45
|
+
* (`{meta.json,revs/,pend/,actions/,proofs/,blocks/}`). The directory tree is a
|
|
46
46
|
* deliberate, human-inspectable/debuggable layout — it is NOT flattened into
|
|
47
47
|
* encoded-filename KV keys.
|
|
48
48
|
*
|
|
@@ -53,8 +53,44 @@ function isParseableJson(bytes: Uint8Array): boolean {
|
|
|
53
53
|
* the legacy raw-colon read fallback + win32 guards, and rename-based promote.
|
|
54
54
|
*/
|
|
55
55
|
export class FileStoreDriver implements RawStoreDriver {
|
|
56
|
+
private readonly identity: StoreIdentity;
|
|
57
|
+
|
|
56
58
|
constructor(private readonly basePath: string) {
|
|
57
59
|
// TODO: use https://www.npmjs.com/package/proper-lockfile to take a lock on the basePath, also introduce explicit dispose pattern
|
|
60
|
+
// The directory this driver is backed by, resolved once here: `path.resolve` is
|
|
61
|
+
// cwd-dependent, and capturing it at construction is the correct reading — two drivers
|
|
62
|
+
// built from the same RELATIVE path under different cwds genuinely address different
|
|
63
|
+
// directories and must not compare equal. An empty basePath resolves to the cwd;
|
|
64
|
+
// nothing special-cases it. (A whitespace-only basePath is NOT the cwd — `path.resolve`
|
|
65
|
+
// is pure string work, so `' '` names a child directory called `' '`.)
|
|
66
|
+
// Lowercased on win32 because Windows paths are case-insensitive: `C:\Foo` and `C:\foo`
|
|
67
|
+
// are one directory and must produce one identity.
|
|
68
|
+
// NOTE: aliases of one directory that this does NOT collapse, and so read as two
|
|
69
|
+
// identities: symlinks, junctions, UNC-versus-mapped-drive spellings, and case-differing
|
|
70
|
+
// spellings on a case-INSENSITIVE non-Windows volume (the default on macOS) — platform is
|
|
71
|
+
// the only signal available synchronously, and case-folding every darwin path would be
|
|
72
|
+
// wrong on a case-sensitive volume. `fs.realpath` resolves all of these, but it is async
|
|
73
|
+
// (this constructor is not) and requires the directory to already exist. Revisit if an
|
|
74
|
+
// alias ever bites. All of these fail in the SAFE direction: a missed alias reports two
|
|
75
|
+
// identities for one directory, so an identity-keyed consumer declines to merge and gets
|
|
76
|
+
// today's behavior.
|
|
77
|
+
// NOTE: the win32 fold is the one branch that can err in the UNSAFE direction — Windows
|
|
78
|
+
// 10+ supports per-directory case sensitivity (`fsutil file setCaseSensitiveInfo`), and
|
|
79
|
+
// on such a directory `X:\p\Foo` and `X:\p\foo` are two directories folded onto ONE
|
|
80
|
+
// identity. That merging consumer now exists — `withReadCache` (db-p2p) shares ONE read
|
|
81
|
+
// cache per identity — so on such a directory the two stores would read through one cache
|
|
82
|
+
// and see each other's blocks, and if the second cache is built directly rather than
|
|
83
|
+
// through that helper, `SharedCachePool.registerStore` refuses it outright (one cache per
|
|
84
|
+
// backing store) and construction throws. Not addressable synchronously either (the flag is a
|
|
85
|
+
// per-directory filesystem query). Revisit if Optimystic ever targets a
|
|
86
|
+
// case-sensitive-enabled Windows directory; until then the fold is right for every
|
|
87
|
+
// ordinary Windows volume.
|
|
88
|
+
const resolved = path.resolve(basePath);
|
|
89
|
+
this.identity = `file:${process.platform === 'win32' ? resolved.toLowerCase() : resolved}`;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
storeIdentity(): StoreIdentity {
|
|
93
|
+
return this.identity;
|
|
58
94
|
}
|
|
59
95
|
|
|
60
96
|
// --- metadata ---
|
|
@@ -186,6 +222,21 @@ export class FileStoreDriver implements RawStoreDriver {
|
|
|
186
222
|
await atomicWriteFile(this.getActionPath(blockId, actionId), value);
|
|
187
223
|
}
|
|
188
224
|
|
|
225
|
+
// --- proofs ---
|
|
226
|
+
|
|
227
|
+
// Keyed by (blockId, rev) like the revisions store, but JSON-valued like the action
|
|
228
|
+
// stores — so it takes the corrupt-content-as-missing guard the revisions store does
|
|
229
|
+
// not, and the filename carries no colon to encode. Deliberately no delete: a proof
|
|
230
|
+
// lives and dies with its revision record (see RawStoreDriver.getProof).
|
|
231
|
+
|
|
232
|
+
async getProof(blockId: BlockId, rev: number): Promise<Uint8Array | undefined> {
|
|
233
|
+
return this.readBytesIfExists(this.getProofPath(blockId, rev), true);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
async putProof(blockId: BlockId, rev: number, value: Uint8Array): Promise<void> {
|
|
237
|
+
await atomicWriteFile(this.getProofPath(blockId, rev), value);
|
|
238
|
+
}
|
|
239
|
+
|
|
189
240
|
// --- materialized ---
|
|
190
241
|
|
|
191
242
|
async getMaterialized(blockId: BlockId, actionId: ActionId): Promise<Uint8Array | undefined> {
|
|
@@ -234,7 +285,7 @@ export class FileStoreDriver implements RawStoreDriver {
|
|
|
234
285
|
// --- optional passthroughs ---
|
|
235
286
|
|
|
236
287
|
async *listBlockIds(): AsyncIterable<BlockId> {
|
|
237
|
-
// The block layout is `basePath/<blockId>/{meta.json,revs/,pend/,actions/,blocks/}`
|
|
288
|
+
// The block layout is `basePath/<blockId>/{meta.json,revs/,pend/,actions/,proofs/,blocks/}`
|
|
238
289
|
// (see getBlockPath), so the direct children of basePath are the per-block directories
|
|
239
290
|
// and each directory NAME is the blockId (used raw, no encoding). Filter to directories
|
|
240
291
|
// so a stray file can't be mistaken for a block; `*.tmp` atomic-write orphans live inside
|
|
@@ -326,6 +377,10 @@ export class FileStoreDriver implements RawStoreDriver {
|
|
|
326
377
|
return path.join(this.getBlockPath(blockId), 'revs', `${rev}.json`);
|
|
327
378
|
}
|
|
328
379
|
|
|
380
|
+
private getProofPath(blockId: BlockId, rev: number): string {
|
|
381
|
+
return path.join(this.getBlockPath(blockId), 'proofs', `${rev}.json`);
|
|
382
|
+
}
|
|
383
|
+
|
|
329
384
|
// `encoded` controls colon handling: writes and canonical reads use the
|
|
330
385
|
// percent-encoded filename (encoded = true); the legacy raw-colon fallback
|
|
331
386
|
// (see readActionScopedBytes) passes encoded = false to reach pre-encode
|
|
@@ -408,13 +463,14 @@ export class FileStoreDriver implements RawStoreDriver {
|
|
|
408
463
|
* imports keep resolving; the kernel supplies the `IRawStorage` surface and the
|
|
409
464
|
* driver supplies fs behavior.
|
|
410
465
|
*
|
|
411
|
-
* `listBlockIds`/`getApproximateBytesUsed` are re-declared here as
|
|
412
|
-
* (the fs driver always implements them, so the kernel constructor always
|
|
413
|
-
* them) — the base declares them optional, but every fs consumer relies on them.
|
|
466
|
+
* `listBlockIds`/`getApproximateBytesUsed`/`getStoreIdentity` are re-declared here as
|
|
467
|
+
* always-present (the fs driver always implements them, so the kernel constructor always
|
|
468
|
+
* wires them) — the base declares them optional, but every fs consumer relies on them.
|
|
414
469
|
*/
|
|
415
470
|
export class FileRawStorage extends KvRawStorage {
|
|
416
471
|
declare listBlockIds: () => AsyncIterable<BlockId>;
|
|
417
472
|
declare getApproximateBytesUsed: () => Promise<number>;
|
|
473
|
+
declare getStoreIdentity: () => StoreIdentity;
|
|
418
474
|
|
|
419
475
|
constructor(basePath: string) {
|
|
420
476
|
super(new FileStoreDriver(basePath));
|