@optimystic/db-p2p 0.14.1 → 0.16.3

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 (275) hide show
  1. package/README.md +616 -609
  2. package/dist/src/cluster/block-transfer-service.d.ts.map +1 -1
  3. package/dist/src/cluster/block-transfer-service.js +4 -3
  4. package/dist/src/cluster/block-transfer-service.js.map +1 -1
  5. package/dist/src/cluster/block-transfer.d.ts +52 -3
  6. package/dist/src/cluster/block-transfer.d.ts.map +1 -1
  7. package/dist/src/cluster/block-transfer.js +129 -6
  8. package/dist/src/cluster/block-transfer.js.map +1 -1
  9. package/dist/src/cluster/client.d.ts.map +1 -1
  10. package/dist/src/cluster/client.js +3 -1
  11. package/dist/src/cluster/client.js.map +1 -1
  12. package/dist/src/cluster/cluster-repo.d.ts +182 -11
  13. package/dist/src/cluster/cluster-repo.d.ts.map +1 -1
  14. package/dist/src/cluster/cluster-repo.js +429 -69
  15. package/dist/src/cluster/cluster-repo.js.map +1 -1
  16. package/dist/src/cluster/peer-key-binding.d.ts +25 -0
  17. package/dist/src/cluster/peer-key-binding.d.ts.map +1 -0
  18. package/dist/src/cluster/peer-key-binding.js +39 -0
  19. package/dist/src/cluster/peer-key-binding.js.map +1 -0
  20. package/dist/src/cluster/quorum-restore.d.ts +72 -0
  21. package/dist/src/cluster/quorum-restore.d.ts.map +1 -0
  22. package/dist/src/cluster/quorum-restore.js +0 -0
  23. package/dist/src/cluster/quorum-restore.js.map +1 -0
  24. package/dist/src/cluster/rebalance-monitor.d.ts +23 -1
  25. package/dist/src/cluster/rebalance-monitor.d.ts.map +1 -1
  26. package/dist/src/cluster/rebalance-monitor.js +17 -2
  27. package/dist/src/cluster/rebalance-monitor.js.map +1 -1
  28. package/dist/src/cluster/service.d.ts.map +1 -1
  29. package/dist/src/cluster/service.js +7 -1
  30. package/dist/src/cluster/service.js.map +1 -1
  31. package/dist/src/cluster/spread-on-churn.d.ts +7 -0
  32. package/dist/src/cluster/spread-on-churn.d.ts.map +1 -1
  33. package/dist/src/cluster/spread-on-churn.js +4 -1
  34. package/dist/src/cluster/spread-on-churn.js.map +1 -1
  35. package/dist/src/cluster/supermajority-coupling.d.ts +22 -0
  36. package/dist/src/cluster/supermajority-coupling.d.ts.map +1 -0
  37. package/dist/src/cluster/supermajority-coupling.js +27 -0
  38. package/dist/src/cluster/supermajority-coupling.js.map +1 -0
  39. package/dist/src/cohort-topic/cohort-gossip-driver.d.ts +46 -4
  40. package/dist/src/cohort-topic/cohort-gossip-driver.d.ts.map +1 -1
  41. package/dist/src/cohort-topic/cohort-gossip-driver.js +62 -7
  42. package/dist/src/cohort-topic/cohort-gossip-driver.js.map +1 -1
  43. package/dist/src/cohort-topic/cohort-gossip-transport.d.ts +7 -0
  44. package/dist/src/cohort-topic/cohort-gossip-transport.d.ts.map +1 -1
  45. package/dist/src/cohort-topic/cohort-gossip-transport.js +9 -0
  46. package/dist/src/cohort-topic/cohort-gossip-transport.js.map +1 -1
  47. package/dist/src/cohort-topic/host.d.ts +197 -27
  48. package/dist/src/cohort-topic/host.d.ts.map +1 -1
  49. package/dist/src/cohort-topic/host.js +643 -87
  50. package/dist/src/cohort-topic/host.js.map +1 -1
  51. package/dist/src/dispute/arbitrator-selection.d.ts +68 -7
  52. package/dist/src/dispute/arbitrator-selection.d.ts.map +1 -1
  53. package/dist/src/dispute/arbitrator-selection.js +105 -16
  54. package/dist/src/dispute/arbitrator-selection.js.map +1 -1
  55. package/dist/src/dispute/cascade.d.ts +7 -0
  56. package/dist/src/dispute/cascade.d.ts.map +1 -1
  57. package/dist/src/dispute/cascade.js +1 -1
  58. package/dist/src/dispute/cascade.js.map +1 -1
  59. package/dist/src/dispute/client.d.ts.map +1 -1
  60. package/dist/src/dispute/client.js +3 -2
  61. package/dist/src/dispute/client.js.map +1 -1
  62. package/dist/src/dispute/dispute-service.d.ts +32 -3
  63. package/dist/src/dispute/dispute-service.d.ts.map +1 -1
  64. package/dist/src/dispute/dispute-service.js +82 -9
  65. package/dist/src/dispute/dispute-service.js.map +1 -1
  66. package/dist/src/dispute/index.d.ts +1 -1
  67. package/dist/src/dispute/index.d.ts.map +1 -1
  68. package/dist/src/dispute/index.js +1 -1
  69. package/dist/src/dispute/index.js.map +1 -1
  70. package/dist/src/dispute/invalidation.d.ts +25 -0
  71. package/dist/src/dispute/invalidation.d.ts.map +1 -1
  72. package/dist/src/dispute/invalidation.js +14 -2
  73. package/dist/src/dispute/invalidation.js.map +1 -1
  74. package/dist/src/dispute/service.d.ts.map +1 -1
  75. package/dist/src/dispute/service.js +7 -1
  76. package/dist/src/dispute/service.js.map +1 -1
  77. package/dist/src/index.d.ts +4 -1
  78. package/dist/src/index.d.ts.map +1 -1
  79. package/dist/src/index.js +4 -1
  80. package/dist/src/index.js.map +1 -1
  81. package/dist/src/it-utility.d.ts +1 -1
  82. package/dist/src/it-utility.d.ts.map +1 -1
  83. package/dist/src/it-utility.js +4 -13
  84. package/dist/src/it-utility.js.map +1 -1
  85. package/dist/src/libp2p-key-network.d.ts +98 -1
  86. package/dist/src/libp2p-key-network.d.ts.map +1 -1
  87. package/dist/src/libp2p-key-network.js +272 -17
  88. package/dist/src/libp2p-key-network.js.map +1 -1
  89. package/dist/src/libp2p-node-base.d.ts +12 -0
  90. package/dist/src/libp2p-node-base.d.ts.map +1 -1
  91. package/dist/src/libp2p-node-base.js +441 -89
  92. package/dist/src/libp2p-node-base.js.map +1 -1
  93. package/dist/src/matchmaking/query-transport.d.ts +2 -0
  94. package/dist/src/matchmaking/query-transport.d.ts.map +1 -1
  95. package/dist/src/matchmaking/query-transport.js +6 -0
  96. package/dist/src/matchmaking/query-transport.js.map +1 -1
  97. package/dist/src/matchmaking/traffic-validation.js +1 -0
  98. package/dist/src/matchmaking/traffic-validation.js.map +1 -1
  99. package/dist/src/network/network-manager-service.d.ts +2 -2
  100. package/dist/src/network/network-manager-service.d.ts.map +1 -1
  101. package/dist/src/network/network-manager-service.js +8 -4
  102. package/dist/src/network/network-manager-service.js.map +1 -1
  103. package/dist/src/owned-block-seed.d.ts +27 -0
  104. package/dist/src/owned-block-seed.d.ts.map +1 -0
  105. package/dist/src/owned-block-seed.js +37 -0
  106. package/dist/src/owned-block-seed.js.map +1 -0
  107. package/dist/src/protocol-client.d.ts +1 -0
  108. package/dist/src/protocol-client.d.ts.map +1 -1
  109. package/dist/src/protocol-client.js +9 -2
  110. package/dist/src/protocol-client.js.map +1 -1
  111. package/dist/src/protocol-limits.d.ts +32 -0
  112. package/dist/src/protocol-limits.d.ts.map +1 -0
  113. package/dist/src/protocol-limits.js +32 -0
  114. package/dist/src/protocol-limits.js.map +1 -0
  115. package/dist/src/repo/client.d.ts.map +1 -1
  116. package/dist/src/repo/client.js +3 -0
  117. package/dist/src/repo/client.js.map +1 -1
  118. package/dist/src/repo/cluster-coordinator.d.ts +41 -4
  119. package/dist/src/repo/cluster-coordinator.d.ts.map +1 -1
  120. package/dist/src/repo/cluster-coordinator.js +128 -80
  121. package/dist/src/repo/cluster-coordinator.js.map +1 -1
  122. package/dist/src/repo/coordinator-repo.d.ts +38 -1
  123. package/dist/src/repo/coordinator-repo.d.ts.map +1 -1
  124. package/dist/src/repo/coordinator-repo.js +92 -13
  125. package/dist/src/repo/coordinator-repo.js.map +1 -1
  126. package/dist/src/repo/service.d.ts.map +1 -1
  127. package/dist/src/repo/service.js +7 -1
  128. package/dist/src/repo/service.js.map +1 -1
  129. package/dist/src/reputation/peer-reputation.js +1 -1
  130. package/dist/src/reputation/peer-reputation.js.map +1 -1
  131. package/dist/src/reputation/types.d.ts +3 -1
  132. package/dist/src/reputation/types.d.ts.map +1 -1
  133. package/dist/src/reputation/types.js +3 -0
  134. package/dist/src/reputation/types.js.map +1 -1
  135. package/dist/src/rn.d.ts +5 -1
  136. package/dist/src/rn.d.ts.map +1 -1
  137. package/dist/src/rn.js +7 -1
  138. package/dist/src/rn.js.map +1 -1
  139. package/dist/src/storage/arachnode-fret-adapter.d.ts +30 -1
  140. package/dist/src/storage/arachnode-fret-adapter.d.ts.map +1 -1
  141. package/dist/src/storage/arachnode-fret-adapter.js +15 -2
  142. package/dist/src/storage/arachnode-fret-adapter.js.map +1 -1
  143. package/dist/src/storage/arachnode-partition.d.ts +49 -0
  144. package/dist/src/storage/arachnode-partition.d.ts.map +1 -0
  145. package/dist/src/storage/arachnode-partition.js +61 -0
  146. package/dist/src/storage/arachnode-partition.js.map +1 -0
  147. package/dist/src/storage/block-storage.d.ts +40 -1
  148. package/dist/src/storage/block-storage.d.ts.map +1 -1
  149. package/dist/src/storage/block-storage.js +150 -57
  150. package/dist/src/storage/block-storage.js.map +1 -1
  151. package/dist/src/storage/i-block-storage.d.ts +8 -0
  152. package/dist/src/storage/i-block-storage.d.ts.map +1 -1
  153. package/dist/src/storage/i-raw-storage.d.ts +13 -0
  154. package/dist/src/storage/i-raw-storage.d.ts.map +1 -1
  155. package/dist/src/storage/kv-raw-storage.d.ts +45 -0
  156. package/dist/src/storage/kv-raw-storage.d.ts.map +1 -0
  157. package/dist/src/storage/kv-raw-storage.js +113 -0
  158. package/dist/src/storage/kv-raw-storage.js.map +1 -0
  159. package/dist/src/storage/memory-storage.d.ts +20 -58
  160. package/dist/src/storage/memory-storage.d.ts.map +1 -1
  161. package/dist/src/storage/memory-storage.js +22 -148
  162. package/dist/src/storage/memory-storage.js.map +1 -1
  163. package/dist/src/storage/memory-store-driver.d.ts +39 -0
  164. package/dist/src/storage/memory-store-driver.d.ts.map +1 -0
  165. package/dist/src/storage/memory-store-driver.js +129 -0
  166. package/dist/src/storage/memory-store-driver.js.map +1 -0
  167. package/dist/src/storage/raw-store-codec.d.ts +10 -0
  168. package/dist/src/storage/raw-store-codec.d.ts.map +1 -0
  169. package/dist/src/storage/raw-store-codec.js +36 -0
  170. package/dist/src/storage/raw-store-codec.js.map +1 -0
  171. package/dist/src/storage/raw-store-driver.d.ts +69 -0
  172. package/dist/src/storage/raw-store-driver.d.ts.map +1 -0
  173. package/dist/src/storage/raw-store-driver.js +2 -0
  174. package/dist/src/storage/raw-store-driver.js.map +1 -0
  175. package/dist/src/storage/restoration-coordinator-v2.d.ts.map +1 -1
  176. package/dist/src/storage/restoration-coordinator-v2.js +1 -1
  177. package/dist/src/storage/restoration-coordinator-v2.js.map +1 -1
  178. package/dist/src/storage/restoration-coordinator.d.ts +73 -0
  179. package/dist/src/storage/restoration-coordinator.d.ts.map +1 -0
  180. package/dist/src/storage/restoration-coordinator.js +181 -0
  181. package/dist/src/storage/restoration-coordinator.js.map +1 -0
  182. package/dist/src/storage/ring-selector.d.ts +92 -5
  183. package/dist/src/storage/ring-selector.d.ts.map +1 -1
  184. package/dist/src/storage/ring-selector.js +153 -51
  185. package/dist/src/storage/ring-selector.js.map +1 -1
  186. package/dist/src/storage/ring-shift-coordinator.d.ts +128 -0
  187. package/dist/src/storage/ring-shift-coordinator.d.ts.map +1 -0
  188. package/dist/src/storage/ring-shift-coordinator.js +196 -0
  189. package/dist/src/storage/ring-shift-coordinator.js.map +1 -0
  190. package/dist/src/storage/storage-monitor.d.ts +28 -0
  191. package/dist/src/storage/storage-monitor.d.ts.map +1 -1
  192. package/dist/src/storage/storage-monitor.js +42 -2
  193. package/dist/src/storage/storage-monitor.js.map +1 -1
  194. package/dist/src/storage/storage-repo.d.ts +19 -0
  195. package/dist/src/storage/storage-repo.d.ts.map +1 -1
  196. package/dist/src/storage/storage-repo.js +172 -22
  197. package/dist/src/storage/storage-repo.js.map +1 -1
  198. package/dist/src/sync/client.d.ts.map +1 -1
  199. package/dist/src/sync/client.js +5 -1
  200. package/dist/src/sync/client.js.map +1 -1
  201. package/dist/src/sync/service.d.ts.map +1 -1
  202. package/dist/src/sync/service.js +2 -1
  203. package/dist/src/sync/service.js.map +1 -1
  204. package/dist/src/testing/cohort-topic-mesh-harness.d.ts +28 -4
  205. package/dist/src/testing/cohort-topic-mesh-harness.d.ts.map +1 -1
  206. package/dist/src/testing/cohort-topic-mesh-harness.js +51 -10
  207. package/dist/src/testing/cohort-topic-mesh-harness.js.map +1 -1
  208. package/dist/src/testing/index.d.ts +1 -0
  209. package/dist/src/testing/index.d.ts.map +1 -1
  210. package/dist/src/testing/index.js +1 -0
  211. package/dist/src/testing/index.js.map +1 -1
  212. package/dist/src/testing/mesh-harness.d.ts.map +1 -1
  213. package/dist/src/testing/mesh-harness.js +15 -7
  214. package/dist/src/testing/mesh-harness.js.map +1 -1
  215. package/dist/src/testing/raw-storage-conformance.d.ts +24 -0
  216. package/dist/src/testing/raw-storage-conformance.d.ts.map +1 -0
  217. package/dist/src/testing/raw-storage-conformance.js +313 -0
  218. package/dist/src/testing/raw-storage-conformance.js.map +1 -0
  219. package/package.json +4 -4
  220. package/src/cluster/block-transfer-service.ts +4 -3
  221. package/src/cluster/block-transfer.ts +424 -265
  222. package/src/cluster/client.ts +3 -1
  223. package/src/cluster/cluster-repo.ts +481 -71
  224. package/src/cluster/peer-key-binding.ts +37 -0
  225. package/src/cluster/quorum-restore.ts +0 -0
  226. package/src/cluster/rebalance-monitor.ts +34 -3
  227. package/src/cluster/service.ts +7 -1
  228. package/src/cluster/spread-on-churn.ts +11 -1
  229. package/src/cluster/supermajority-coupling.ts +37 -0
  230. package/src/cohort-topic/cohort-gossip-driver.ts +96 -9
  231. package/src/cohort-topic/cohort-gossip-transport.ts +10 -0
  232. package/src/cohort-topic/host.ts +831 -105
  233. package/src/dispute/arbitrator-selection.ts +138 -28
  234. package/src/dispute/cascade.ts +8 -1
  235. package/src/dispute/client.ts +3 -2
  236. package/src/dispute/dispute-service.ts +94 -9
  237. package/src/dispute/index.ts +7 -1
  238. package/src/dispute/invalidation.ts +40 -2
  239. package/src/dispute/service.ts +7 -1
  240. package/src/index.ts +46 -43
  241. package/src/it-utility.ts +5 -13
  242. package/src/libp2p-key-network.ts +281 -18
  243. package/src/libp2p-node-base.ts +511 -81
  244. package/src/matchmaking/query-transport.ts +9 -0
  245. package/src/network/network-manager-service.ts +8 -2
  246. package/src/owned-block-seed.ts +40 -0
  247. package/src/protocol-client.ts +10 -3
  248. package/src/protocol-limits.ts +33 -0
  249. package/src/repo/client.ts +3 -0
  250. package/src/repo/cluster-coordinator.ts +145 -82
  251. package/src/repo/coordinator-repo.ts +96 -16
  252. package/src/repo/service.ts +7 -1
  253. package/src/reputation/types.ts +3 -0
  254. package/src/rn.ts +7 -1
  255. package/src/storage/arachnode-fret-adapter.ts +33 -2
  256. package/src/storage/arachnode-partition.ts +74 -0
  257. package/src/storage/block-storage.ts +169 -61
  258. package/src/storage/i-block-storage.ts +9 -0
  259. package/src/storage/i-raw-storage.ts +14 -0
  260. package/src/storage/kv-raw-storage.ts +135 -0
  261. package/src/storage/memory-storage.ts +25 -173
  262. package/src/storage/memory-store-driver.ts +157 -0
  263. package/src/storage/raw-store-codec.ts +42 -0
  264. package/src/storage/raw-store-driver.ts +80 -0
  265. package/src/storage/{restoration-coordinator-v2.ts → restoration-coordinator.ts} +43 -37
  266. package/src/storage/ring-selector.ts +317 -176
  267. package/src/storage/ring-shift-coordinator.ts +271 -0
  268. package/src/storage/storage-monitor.ts +70 -3
  269. package/src/storage/storage-repo.ts +710 -558
  270. package/src/sync/client.ts +5 -1
  271. package/src/sync/service.ts +2 -1
  272. package/src/testing/cohort-topic-mesh-harness.ts +61 -11
  273. package/src/testing/index.ts +1 -0
  274. package/src/testing/mesh-harness.ts +14 -6
  275. package/src/testing/raw-storage-conformance.ts +397 -0
@@ -1,60 +1,22 @@
1
- import type { BlockId, IBlock, Transform, ActionId, ActionRev } from "@optimystic/db-core";
2
- import type { BlockMetadata } from "./struct.js";
3
- import type { IRawStorage } from "./i-raw-storage.js";
4
- export declare class MemoryRawStorage implements IRawStorage {
5
- private metadata;
6
- private revisions;
7
- private pendingActions;
8
- private actions;
9
- private materializedBlocks;
10
- private getRevisionKey;
11
- private getActionKey;
12
- /**
13
- * Retrieves metadata for a block.
14
- *
15
- * @pitfall **MUST return a clone** - `BlockStorage.setLatest` mutates the returned
16
- * metadata in place (`meta.latest = latest`) before calling `saveMetadata`. Returning
17
- * the stored reference leaks that mutation into RAM even when a subsequent
18
- * `saveMetadata` call fails, masking mid-commit crashes that a persistent store
19
- * (file/sqlite/leveldb) would surface correctly.
20
- * @see docs/internals.md "Storage Returns References" pitfall
21
- */
22
- getMetadata(blockId: BlockId): Promise<BlockMetadata | undefined>;
23
- /**
24
- * Stores metadata for a block.
25
- *
26
- * @pitfall **MUST store a clone** - callers may continue mutating the metadata object
27
- * after saving; storing the reference lets those mutations corrupt persisted state.
28
- * @see docs/internals.md "Storage Returns References" pitfall
29
- */
30
- saveMetadata(blockId: BlockId, metadata: BlockMetadata): Promise<void>;
31
- getRevision(blockId: BlockId, rev: number): Promise<ActionId | undefined>;
32
- saveRevision(blockId: BlockId, rev: number, actionId: ActionId): Promise<void>;
33
- listRevisions(blockId: BlockId, startRev: number, endRev: number): AsyncIterable<ActionRev>;
34
- getPendingTransaction(blockId: BlockId, actionId: ActionId): Promise<Transform | undefined>;
35
- savePendingTransaction(blockId: BlockId, actionId: ActionId, transform: Transform): Promise<void>;
36
- deletePendingTransaction(blockId: BlockId, actionId: ActionId): Promise<void>;
37
- listPendingTransactions(blockId: BlockId): AsyncIterable<ActionId>;
38
- getTransaction(blockId: BlockId, actionId: ActionId): Promise<Transform | undefined>;
39
- saveTransaction(blockId: BlockId, actionId: ActionId, transform: Transform): Promise<void>;
40
- /**
41
- * Retrieves a materialized block at a specific revision.
42
- *
43
- * @pitfall **MUST return a clone** - `applyTransform()` mutates blocks in place.
44
- * If we return the stored reference, mutations corrupt ALL revisions that share
45
- * the same underlying object.
46
- * @see docs/internals.md "Storage Returns References" pitfall
47
- */
48
- getMaterializedBlock(blockId: BlockId, actionId: ActionId): Promise<IBlock | undefined>;
49
- /**
50
- * Stores a materialized block at a specific revision.
51
- *
52
- * @pitfall **MUST store a clone** - callers may continue mutating the block after saving.
53
- * If we store the reference, those mutations corrupt the stored data.
54
- * @see docs/internals.md "Storage Returns References" pitfall
55
- */
56
- saveMaterializedBlock(blockId: BlockId, actionId: ActionId, block?: IBlock): Promise<void>;
57
- promotePendingTransaction(blockId: BlockId, actionId: ActionId): Promise<void>;
58
- getApproximateBytesUsed(): Promise<number>;
1
+ import { KvRawStorage } from "./kv-raw-storage.js";
2
+ /**
3
+ * In-memory {@link IRawStorage}, now a thin shell over the shared
4
+ * {@link KvRawStorage} kernel backed by a {@link MemoryStoreDriver}.
5
+ *
6
+ * @pitfall The old hand-rolled version had to `structuredClone` on every get and
7
+ * put — otherwise callers mutating a returned/stored object corrupted the store
8
+ * (see docs/internals.md "Storage Returns References"). That discipline is GONE
9
+ * and must not be reintroduced: values cross the driver boundary as
10
+ * `Uint8Array` produced by `JSON`-encode and consumed by `JSON`-decode, so every
11
+ * read decodes a fresh object and every write stored an independent byte
12
+ * snapshot BY CONSTRUCTION. The clone-on-store / clone-on-read invariant is now
13
+ * structural, not a rule. The conformance suite asserts it so a future driver
14
+ * that shortcuts the byte boundary is caught.
15
+ *
16
+ * The name is kept stable so existing imports (`from '@optimystic/db-p2p'`)
17
+ * continue to resolve.
18
+ */
19
+ export declare class MemoryRawStorage extends KvRawStorage {
20
+ constructor();
59
21
  }
60
22
  //# sourceMappingURL=memory-storage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"memory-storage.d.ts","sourceRoot":"","sources":["../../../src/storage/memory-storage.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAC3F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,qBAAa,gBAAiB,YAAW,WAAW;IACnD,OAAO,CAAC,QAAQ,CAAqC;IACrD,OAAO,CAAC,SAAS,CAA+B;IAChD,OAAO,CAAC,cAAc,CAAgC;IACtD,OAAO,CAAC,OAAO,CAAgC;IAC/C,OAAO,CAAC,kBAAkB,CAA6B;IAEvD,OAAO,CAAC,cAAc;IAItB,OAAO,CAAC,YAAY;IAIpB;;;;;;;;;OASG;IACG,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC;IAKvE;;;;;;OAMG;IACG,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAItE,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,SAAS,CAAC;IAIzE,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAI7E,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,aAAa,CAAC,SAAS,CAAC;IAsB5F,qBAAqB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;IAI3F,sBAAsB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAKjG,wBAAwB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAI5E,uBAAuB,CAAC,OAAO,EAAE,OAAO,GAAG,aAAa,CAAC,QAAQ,CAAC;IASnE,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;IAIpF,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhG;;;;;;;OAOG;IACG,oBAAoB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAM7F;;;;;;OAMG;IACG,qBAAqB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU1F,yBAAyB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAS9E,uBAAuB,IAAI,OAAO,CAAC,MAAM,CAAC;CAmBhD"}
1
+ {"version":3,"file":"memory-storage.d.ts","sourceRoot":"","sources":["../../../src/storage/memory-storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGnD;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,gBAAiB,SAAQ,YAAY;;CAIjD"}
@@ -1,151 +1,25 @@
1
- export class MemoryRawStorage {
2
- metadata = new Map();
3
- revisions = new Map(); // blockId:rev -> actionId
4
- pendingActions = new Map(); // blockId:actionId -> transform
5
- actions = new Map(); // blockId:actionId -> transform
6
- materializedBlocks = new Map(); // blockId:actionId -> block
7
- getRevisionKey(blockId, rev) {
8
- return `${blockId}:${rev}`;
9
- }
10
- getActionKey(blockId, actionId) {
11
- return `${blockId}:${actionId}`;
12
- }
13
- /**
14
- * Retrieves metadata for a block.
15
- *
16
- * @pitfall **MUST return a clone** - `BlockStorage.setLatest` mutates the returned
17
- * metadata in place (`meta.latest = latest`) before calling `saveMetadata`. Returning
18
- * the stored reference leaks that mutation into RAM even when a subsequent
19
- * `saveMetadata` call fails, masking mid-commit crashes that a persistent store
20
- * (file/sqlite/leveldb) would surface correctly.
21
- * @see docs/internals.md "Storage Returns References" pitfall
22
- */
23
- async getMetadata(blockId) {
24
- const meta = this.metadata.get(blockId);
25
- return meta ? structuredClone(meta) : undefined;
26
- }
27
- /**
28
- * Stores metadata for a block.
29
- *
30
- * @pitfall **MUST store a clone** - callers may continue mutating the metadata object
31
- * after saving; storing the reference lets those mutations corrupt persisted state.
32
- * @see docs/internals.md "Storage Returns References" pitfall
33
- */
34
- async saveMetadata(blockId, metadata) {
35
- this.metadata.set(blockId, structuredClone(metadata));
36
- }
37
- async getRevision(blockId, rev) {
38
- return this.revisions.get(this.getRevisionKey(blockId, rev));
39
- }
40
- async saveRevision(blockId, rev, actionId) {
41
- this.revisions.set(this.getRevisionKey(blockId, rev), actionId);
42
- }
43
- async *listRevisions(blockId, startRev, endRev) {
44
- const ascending = startRev <= endRev;
45
- const actualStart = ascending ? startRev : endRev;
46
- const actualEnd = ascending ? endRev : startRev;
47
- const results = [];
48
- for (let rev = actualStart; rev <= actualEnd; rev++) {
49
- const actionId = this.revisions.get(this.getRevisionKey(blockId, rev));
50
- if (actionId) {
51
- results.push({ rev, actionId });
52
- }
53
- }
54
- if (!ascending) {
55
- results.reverse();
56
- }
57
- for (const result of results) {
58
- yield result;
59
- }
60
- }
61
- async getPendingTransaction(blockId, actionId) {
62
- return this.pendingActions.get(this.getActionKey(blockId, actionId));
63
- }
64
- async savePendingTransaction(blockId, actionId, transform) {
65
- // Clone transform to prevent external modifications from affecting stored data
66
- this.pendingActions.set(this.getActionKey(blockId, actionId), structuredClone(transform));
67
- }
68
- async deletePendingTransaction(blockId, actionId) {
69
- this.pendingActions.delete(this.getActionKey(blockId, actionId));
70
- }
71
- async *listPendingTransactions(blockId) {
72
- const prefix = `${blockId}:`;
73
- for (const [key] of Array.from(this.pendingActions.entries())) {
74
- if (key.startsWith(prefix)) {
75
- yield key.substring(prefix.length);
76
- }
77
- }
78
- }
79
- async getTransaction(blockId, actionId) {
80
- return this.actions.get(this.getActionKey(blockId, actionId));
81
- }
82
- async saveTransaction(blockId, actionId, transform) {
83
- this.actions.set(this.getActionKey(blockId, actionId), transform);
84
- }
85
- /**
86
- * Retrieves a materialized block at a specific revision.
87
- *
88
- * @pitfall **MUST return a clone** - `applyTransform()` mutates blocks in place.
89
- * If we return the stored reference, mutations corrupt ALL revisions that share
90
- * the same underlying object.
91
- * @see docs/internals.md "Storage Returns References" pitfall
92
- */
93
- async getMaterializedBlock(blockId, actionId) {
94
- const block = this.materializedBlocks.get(this.getActionKey(blockId, actionId));
95
- // Clone to prevent external mutations from affecting stored data
96
- return block ? structuredClone(block) : undefined;
97
- }
98
- /**
99
- * Stores a materialized block at a specific revision.
100
- *
101
- * @pitfall **MUST store a clone** - callers may continue mutating the block after saving.
102
- * If we store the reference, those mutations corrupt the stored data.
103
- * @see docs/internals.md "Storage Returns References" pitfall
104
- */
105
- async saveMaterializedBlock(blockId, actionId, block) {
106
- const key = this.getActionKey(blockId, actionId);
107
- if (block) {
108
- // Clone to prevent external mutations from affecting stored data
109
- this.materializedBlocks.set(key, structuredClone(block));
110
- }
111
- else {
112
- this.materializedBlocks.delete(key);
113
- }
114
- }
115
- async promotePendingTransaction(blockId, actionId) {
116
- const key = this.getActionKey(blockId, actionId);
117
- const transform = this.pendingActions.get(key);
118
- if (transform) {
119
- this.actions.set(key, transform);
120
- this.pendingActions.delete(key);
121
- }
122
- }
123
- async getApproximateBytesUsed() {
124
- let total = 0;
125
- for (const [blockId, meta] of this.metadata) {
126
- total += blockId.length + jsonByteSize(meta);
127
- }
128
- for (const [key, actionId] of this.revisions) {
129
- total += key.length + actionId.length;
130
- }
131
- for (const [key, transform] of this.pendingActions) {
132
- total += key.length + jsonByteSize(transform);
133
- }
134
- for (const [key, transform] of this.actions) {
135
- total += key.length + jsonByteSize(transform);
136
- }
137
- for (const [key, block] of this.materializedBlocks) {
138
- total += key.length + jsonByteSize(block);
139
- }
140
- return total;
141
- }
142
- }
143
- function jsonByteSize(value) {
144
- try {
145
- return JSON.stringify(value)?.length ?? 0;
146
- }
147
- catch {
148
- return 0;
1
+ import { KvRawStorage } from "./kv-raw-storage.js";
2
+ import { MemoryStoreDriver } from "./memory-store-driver.js";
3
+ /**
4
+ * In-memory {@link IRawStorage}, now a thin shell over the shared
5
+ * {@link KvRawStorage} kernel backed by a {@link MemoryStoreDriver}.
6
+ *
7
+ * @pitfall The old hand-rolled version had to `structuredClone` on every get and
8
+ * put — otherwise callers mutating a returned/stored object corrupted the store
9
+ * (see docs/internals.md "Storage Returns References"). That discipline is GONE
10
+ * and must not be reintroduced: values cross the driver boundary as
11
+ * `Uint8Array` produced by `JSON`-encode and consumed by `JSON`-decode, so every
12
+ * read decodes a fresh object and every write stored an independent byte
13
+ * snapshot BY CONSTRUCTION. The clone-on-store / clone-on-read invariant is now
14
+ * structural, not a rule. The conformance suite asserts it so a future driver
15
+ * that shortcuts the byte boundary is caught.
16
+ *
17
+ * The name is kept stable so existing imports (`from '@optimystic/db-p2p'`)
18
+ * continue to resolve.
19
+ */
20
+ export class MemoryRawStorage extends KvRawStorage {
21
+ constructor() {
22
+ super(new MemoryStoreDriver());
149
23
  }
150
24
  }
151
25
  //# sourceMappingURL=memory-storage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"memory-storage.js","sourceRoot":"","sources":["../../../src/storage/memory-storage.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"memory-storage.js","sourceRoot":"","sources":["../../../src/storage/memory-storage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,OAAO,gBAAiB,SAAQ,YAAY;IACjD;QACC,KAAK,CAAC,IAAI,iBAAiB,EAAE,CAAC,CAAC;IAChC,CAAC;CACD"}
@@ -0,0 +1,39 @@
1
+ import type { BlockId, ActionId } from "@optimystic/db-core";
2
+ import type { RawStoreDriver } from "./raw-store-driver.js";
3
+ /**
4
+ * In-memory {@link RawStoreDriver}: the five logical block-storage stores as
5
+ * `Map`s of `Uint8Array` values. `KvRawStorage` hands this driver bytes produced
6
+ * by `JSON`-encode and reads them back via `JSON`-decode, so every get yields a
7
+ * fresh object and every save stored an independent byte snapshot BY
8
+ * CONSTRUCTION — the old `structuredClone`-on-every-get/put discipline is now
9
+ * structural, not a rule a maintainer has to remember. The driver therefore
10
+ * stores the byte reference directly: those bytes are never mutated by the
11
+ * kernel or exposed to callers as a mutable handle.
12
+ */
13
+ export declare class MemoryStoreDriver implements RawStoreDriver {
14
+ private readonly metadata;
15
+ private readonly revisions;
16
+ private readonly pending;
17
+ private readonly transactions;
18
+ private readonly materialized;
19
+ private revisionKey;
20
+ private actionKey;
21
+ getMetadata(blockId: BlockId): Promise<Uint8Array | undefined>;
22
+ putMetadata(blockId: BlockId, value: Uint8Array): Promise<void>;
23
+ getRevision(blockId: BlockId, rev: number): Promise<Uint8Array | undefined>;
24
+ putRevision(blockId: BlockId, rev: number, value: Uint8Array): Promise<void>;
25
+ rangeRevisions(blockId: BlockId, lo: number, hi: number, reverse: boolean): AsyncIterable<[number, Uint8Array]>;
26
+ getPending(blockId: BlockId, actionId: ActionId): Promise<Uint8Array | undefined>;
27
+ putPending(blockId: BlockId, actionId: ActionId, value: Uint8Array): Promise<void>;
28
+ deletePending(blockId: BlockId, actionId: ActionId): Promise<void>;
29
+ listPendingActionIds(blockId: BlockId): AsyncIterable<ActionId>;
30
+ getTransaction(blockId: BlockId, actionId: ActionId): Promise<Uint8Array | undefined>;
31
+ putTransaction(blockId: BlockId, actionId: ActionId, value: Uint8Array): Promise<void>;
32
+ getMaterialized(blockId: BlockId, actionId: ActionId): Promise<Uint8Array | undefined>;
33
+ putMaterialized(blockId: BlockId, actionId: ActionId, value: Uint8Array): Promise<void>;
34
+ deleteMaterialized(blockId: BlockId, actionId: ActionId): Promise<void>;
35
+ promote(blockId: BlockId, actionId: ActionId): Promise<void>;
36
+ listBlockIds(): AsyncIterable<BlockId>;
37
+ approximateBytesUsed(): Promise<number>;
38
+ }
39
+ //# sourceMappingURL=memory-store-driver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-store-driver.d.ts","sourceRoot":"","sources":["../../../src/storage/memory-store-driver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D;;;;;;;;;GASG;AACH,qBAAa,iBAAkB,YAAW,cAAc;IACvD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAkC;IAC3D,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiC;IAC3D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiC;IACzD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAiC;IAC9D,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAiC;IAE9D,OAAO,CAAC,WAAW;IAInB,OAAO,CAAC,SAAS;IAMX,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAI9D,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAM/D,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAI3E,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3E,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,aAAa,CAAC,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IAqBhH,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAIjF,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAIlF,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjE,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,aAAa,CAAC,QAAQ,CAAC;IAiBhE,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAIrF,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAMtF,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAItF,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvF,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAMvE,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAY3D,YAAY,IAAI,aAAa,CAAC,OAAO,CAAC;IAUvC,oBAAoB,IAAI,OAAO,CAAC,MAAM,CAAC;CAY7C"}
@@ -0,0 +1,129 @@
1
+ /**
2
+ * In-memory {@link RawStoreDriver}: the five logical block-storage stores as
3
+ * `Map`s of `Uint8Array` values. `KvRawStorage` hands this driver bytes produced
4
+ * by `JSON`-encode and reads them back via `JSON`-decode, so every get yields a
5
+ * fresh object and every save stored an independent byte snapshot BY
6
+ * CONSTRUCTION — the old `structuredClone`-on-every-get/put discipline is now
7
+ * structural, not a rule a maintainer has to remember. The driver therefore
8
+ * stores the byte reference directly: those bytes are never mutated by the
9
+ * kernel or exposed to callers as a mutable handle.
10
+ */
11
+ export class MemoryStoreDriver {
12
+ metadata = new Map();
13
+ revisions = new Map(); // `${blockId}:${rev}` -> actionId bytes
14
+ pending = new Map(); // `${blockId}:${actionId}` -> transform bytes
15
+ transactions = new Map();
16
+ materialized = new Map();
17
+ revisionKey(blockId, rev) {
18
+ return `${blockId}:${rev}`;
19
+ }
20
+ actionKey(blockId, actionId) {
21
+ return `${blockId}:${actionId}`;
22
+ }
23
+ // --- metadata ---
24
+ async getMetadata(blockId) {
25
+ return this.metadata.get(blockId);
26
+ }
27
+ async putMetadata(blockId, value) {
28
+ this.metadata.set(blockId, value);
29
+ }
30
+ // --- revisions ---
31
+ async getRevision(blockId, rev) {
32
+ return this.revisions.get(this.revisionKey(blockId, rev));
33
+ }
34
+ async putRevision(blockId, rev, value) {
35
+ this.revisions.set(this.revisionKey(blockId, rev), value);
36
+ }
37
+ async *rangeRevisions(blockId, lo, hi, reverse) {
38
+ // Drain into an array before yielding (drain-before-yield contract): the
39
+ // consumer awaits between yields, and a Map has no live cursor to pin, but
40
+ // this keeps the memory driver's semantics identical to the native backends.
41
+ const results = [];
42
+ for (let rev = lo; rev <= hi; rev++) {
43
+ const value = this.revisions.get(this.revisionKey(blockId, rev));
44
+ if (value !== undefined) {
45
+ results.push([rev, value]);
46
+ }
47
+ }
48
+ if (reverse) {
49
+ results.reverse();
50
+ }
51
+ for (const result of results) {
52
+ yield result;
53
+ }
54
+ }
55
+ // --- pending ---
56
+ async getPending(blockId, actionId) {
57
+ return this.pending.get(this.actionKey(blockId, actionId));
58
+ }
59
+ async putPending(blockId, actionId, value) {
60
+ this.pending.set(this.actionKey(blockId, actionId), value);
61
+ }
62
+ async deletePending(blockId, actionId) {
63
+ this.pending.delete(this.actionKey(blockId, actionId));
64
+ }
65
+ async *listPendingActionIds(blockId) {
66
+ const prefix = `${blockId}:`;
67
+ // Snapshot before yielding (drain-before-yield): a concurrent putPending during
68
+ // the scan must not invalidate a live map iterator.
69
+ const ids = [];
70
+ for (const key of Array.from(this.pending.keys())) {
71
+ if (key.startsWith(prefix)) {
72
+ ids.push(key.substring(prefix.length));
73
+ }
74
+ }
75
+ for (const id of ids) {
76
+ yield id;
77
+ }
78
+ }
79
+ // --- transactions ---
80
+ async getTransaction(blockId, actionId) {
81
+ return this.transactions.get(this.actionKey(blockId, actionId));
82
+ }
83
+ async putTransaction(blockId, actionId, value) {
84
+ this.transactions.set(this.actionKey(blockId, actionId), value);
85
+ }
86
+ // --- materialized ---
87
+ async getMaterialized(blockId, actionId) {
88
+ return this.materialized.get(this.actionKey(blockId, actionId));
89
+ }
90
+ async putMaterialized(blockId, actionId, value) {
91
+ this.materialized.set(this.actionKey(blockId, actionId), value);
92
+ }
93
+ async deleteMaterialized(blockId, actionId) {
94
+ this.materialized.delete(this.actionKey(blockId, actionId));
95
+ }
96
+ // --- promote (atomic move; synchronous Map ops make it indivisible here) ---
97
+ async promote(blockId, actionId) {
98
+ const key = this.actionKey(blockId, actionId);
99
+ const value = this.pending.get(key);
100
+ if (value === undefined) {
101
+ throw new Error(`Pending action ${actionId} not found for block ${blockId}`);
102
+ }
103
+ this.transactions.set(key, value);
104
+ this.pending.delete(key);
105
+ }
106
+ // --- optional passthroughs ---
107
+ async *listBlockIds() {
108
+ // Snapshot the keys before yielding so a concurrent putMetadata during the scan
109
+ // doesn't invalidate a live map iterator. Fresh in-memory storage is empty, so at
110
+ // real process startup this yields nothing — it exists so the seed path can be
111
+ // unit-tested against a pre-populated store.
112
+ for (const blockId of Array.from(this.metadata.keys())) {
113
+ yield blockId;
114
+ }
115
+ }
116
+ async approximateBytesUsed() {
117
+ let total = 0;
118
+ for (const [blockId, value] of this.metadata) {
119
+ total += blockId.length + value.byteLength;
120
+ }
121
+ for (const store of [this.revisions, this.pending, this.transactions, this.materialized]) {
122
+ for (const [key, value] of store) {
123
+ total += key.length + value.byteLength;
124
+ }
125
+ }
126
+ return total;
127
+ }
128
+ }
129
+ //# sourceMappingURL=memory-store-driver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memory-store-driver.js","sourceRoot":"","sources":["../../../src/storage/memory-store-driver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { ActionId } from "@optimystic/db-core";
2
+ /** JSON-encode a value (`BlockMetadata` / `Transform` / `IBlock`) to UTF-8 bytes. */
3
+ export declare function encodeJson<T>(value: T): Uint8Array;
4
+ /** Decode UTF-8 JSON bytes back into a value. Callers guard the miss (`undefined`) first. */
5
+ export declare function decodeJson<T>(bytes: Uint8Array): T;
6
+ /** Encode an `ActionId` string to UTF-8 bytes (stored as the revisions-store value). */
7
+ export declare function encodeActionId(actionId: ActionId): Uint8Array;
8
+ /** Decode UTF-8 bytes back into an `ActionId` string. */
9
+ export declare function decodeActionId(bytes: Uint8Array): ActionId;
10
+ //# sourceMappingURL=raw-store-codec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"raw-store-codec.d.ts","sourceRoot":"","sources":["../../../src/storage/raw-store-codec.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAuBpD,qFAAqF;AACrF,wBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,UAAU,CAElD;AAED,6FAA6F;AAC7F,wBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,UAAU,GAAG,CAAC,CAElD;AAED,wFAAwF;AACxF,wBAAgB,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,UAAU,CAE7D;AAED,yDAAyD;AACzD,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,GAAG,QAAQ,CAE1D"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Value codec shared by every `KvRawStorage`-backed store. Values cross the
3
+ * `RawStoreDriver` boundary as `Uint8Array`, so this module is the single place
4
+ * that turns `BlockMetadata`/`Transform`/`IBlock` (via JSON) and the `ActionId`
5
+ * string (via UTF-8) into bytes and back.
6
+ *
7
+ * Because a get always decodes fresh bytes into a NEW object and a save always
8
+ * encodes an independent byte copy, the clone-on-store / clone-on-read invariant
9
+ * that in-memory storage used to enforce by hand (`structuredClone`) is now
10
+ * structural for kernel-backed stores — see docs/internals.md "Storage Returns
11
+ * References".
12
+ *
13
+ * Round-trip fidelity matters for `BlockMetadata`: an open-ended `RevisionRange`
14
+ * is encoded `[E]` (one element, upper bound `undefined`). `JSON.stringify([5])`
15
+ * → `"[5]"` → `JSON.parse` → `[5]`, so the open-ended encoding survives byte-exact.
16
+ * Do NOT normalize ranges here.
17
+ */
18
+ const encoder = new TextEncoder();
19
+ const decoder = new TextDecoder();
20
+ /** JSON-encode a value (`BlockMetadata` / `Transform` / `IBlock`) to UTF-8 bytes. */
21
+ export function encodeJson(value) {
22
+ return encoder.encode(JSON.stringify(value));
23
+ }
24
+ /** Decode UTF-8 JSON bytes back into a value. Callers guard the miss (`undefined`) first. */
25
+ export function decodeJson(bytes) {
26
+ return JSON.parse(decoder.decode(bytes));
27
+ }
28
+ /** Encode an `ActionId` string to UTF-8 bytes (stored as the revisions-store value). */
29
+ export function encodeActionId(actionId) {
30
+ return encoder.encode(actionId);
31
+ }
32
+ /** Decode UTF-8 bytes back into an `ActionId` string. */
33
+ export function decodeActionId(bytes) {
34
+ return decoder.decode(bytes);
35
+ }
36
+ //# sourceMappingURL=raw-store-codec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"raw-store-codec.js","sourceRoot":"","sources":["../../../src/storage/raw-store-codec.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;GAgBG;AAEH,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;AAClC,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC;AAElC,qFAAqF;AACrF,MAAM,UAAU,UAAU,CAAI,KAAQ;IACrC,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;AAC9C,CAAC;AAED,6FAA6F;AAC7F,MAAM,UAAU,UAAU,CAAI,KAAiB;IAC9C,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAM,CAAC;AAC/C,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,cAAc,CAAC,QAAkB;IAChD,OAAO,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AACjC,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,cAAc,CAAC,KAAiB;IAC/C,OAAO,OAAO,CAAC,MAAM,CAAC,KAAK,CAAa,CAAC;AAC1C,CAAC"}
@@ -0,0 +1,69 @@
1
+ import type { BlockId, ActionId } from "@optimystic/db-core";
2
+ /**
3
+ * Bytes-valued, per-logical-store driver surface. Each backend implements the
4
+ * five block-storage stores (metadata, revisions, pending, transactions,
5
+ * materialized) over its native mechanism (LevelDB tag-ranges, five SQLite
6
+ * tables, five IndexedDB object stores, five filesystem subdirectories, five
7
+ * in-memory maps). `KvRawStorage` layers all JSON serialization and call
8
+ * orchestration on top — drivers never (de)serialize values and never see the
9
+ * `BlockMetadata`/`Transform`/`IBlock` types. Drivers speak only
10
+ * `Uint8Array`/`BlockId`/`ActionId`/`number`.
11
+ *
12
+ * ### Iteration semantics (drain-before-yield)
13
+ *
14
+ * `rangeRevisions` and `listPendingActionIds` return an `AsyncIterable`, but a
15
+ * driver MUST drain its native cursor/iterator into memory BEFORE yielding to
16
+ * the consumer. A live LevelDB iterator, IndexedDB transaction, or SQLite
17
+ * cursor must not straddle the consumer's `await`s: IndexedDB auto-commits an
18
+ * idle transaction, SQLite would hold its mutex slot, and LevelDB pins native
19
+ * resources. The kernel encodes this as a contract (not a shared implementation)
20
+ * because the drain is backend-specific. The conformance suite exercises it by
21
+ * interleaving other awaits between yielded items.
22
+ *
23
+ * ### Promote atomicity
24
+ *
25
+ * `promote` is the ONLY cross-key atomic operation the kernel requires. Every
26
+ * other write is a single put/delete. Each backend satisfies `promote` with its
27
+ * native atomic mechanism (LevelDB batch, SQLite transaction, IndexedDB
28
+ * readwrite transaction, filesystem rename); the kernel never assumes an
29
+ * atomicity a backend cannot deliver.
30
+ */
31
+ export interface RawStoreDriver {
32
+ getMetadata(blockId: BlockId): Promise<Uint8Array | undefined>;
33
+ putMetadata(blockId: BlockId, value: Uint8Array): Promise<void>;
34
+ getRevision(blockId: BlockId, rev: number): Promise<Uint8Array | undefined>;
35
+ putRevision(blockId: BlockId, rev: number, value: Uint8Array): Promise<void>;
36
+ /**
37
+ * Yield `[rev, value]` for every present rev in `[lo, hi]` (both inclusive),
38
+ * ascending when `reverse` is false, descending when `reverse` is true. The
39
+ * driver MUST drain any native cursor into memory before yielding — see the
40
+ * "drain-before-yield" contract above.
41
+ */
42
+ rangeRevisions(blockId: BlockId, lo: number, hi: number, reverse: boolean): AsyncIterable<[number, Uint8Array]>;
43
+ getPending(blockId: BlockId, actionId: ActionId): Promise<Uint8Array | undefined>;
44
+ putPending(blockId: BlockId, actionId: ActionId, value: Uint8Array): Promise<void>;
45
+ deletePending(blockId: BlockId, actionId: ActionId): Promise<void>;
46
+ /** Yield each present pending actionId for the block. MUST drain before yielding (see above). */
47
+ listPendingActionIds(blockId: BlockId): AsyncIterable<ActionId>;
48
+ getTransaction(blockId: BlockId, actionId: ActionId): Promise<Uint8Array | undefined>;
49
+ putTransaction(blockId: BlockId, actionId: ActionId, value: Uint8Array): Promise<void>;
50
+ getMaterialized(blockId: BlockId, actionId: ActionId): Promise<Uint8Array | undefined>;
51
+ putMaterialized(blockId: BlockId, actionId: ActionId, value: Uint8Array): Promise<void>;
52
+ deleteMaterialized(blockId: BlockId, actionId: ActionId): Promise<void>;
53
+ /**
54
+ * Atomically move `pending(blockId, actionId)` → `transactions(blockId, actionId)`:
55
+ * write the transactions entry and remove the pending entry as one indivisible
56
+ * step (batch / DB transaction / rename). A crash must leave exactly one of the
57
+ * two states, never both/neither. Throw
58
+ * `Pending action <actionId> not found for block <blockId>` when no pending
59
+ * entry exists. This is the ONLY cross-key atomic operation the kernel requires.
60
+ */
61
+ promote(blockId: BlockId, actionId: ActionId): Promise<void>;
62
+ /** Optional — enumerate block ids with durable metadata (startup seed). Passed through by the kernel. */
63
+ listBlockIds?(): AsyncIterable<BlockId>;
64
+ /** Optional — best cheap byte estimate. Passed through by the kernel. */
65
+ approximateBytesUsed?(): Promise<number>;
66
+ /** Optional — release the underlying handle. */
67
+ close?(): Promise<void>;
68
+ }
69
+ //# sourceMappingURL=raw-store-driver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"raw-store-driver.d.ts","sourceRoot":"","sources":["../../../src/storage/raw-store-driver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAE7D;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,WAAW,cAAc;IAE9B,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC;IAC/D,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAGhE,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC;IAC5E,WAAW,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7E;;;;;OAKG;IACH,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,aAAa,CAAC,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IAGhH,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC;IAClF,UAAU,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnF,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnE,iGAAiG;IACjG,oBAAoB,CAAC,OAAO,EAAE,OAAO,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;IAGhE,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC;IACtF,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAGvF,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAAC;IACvF,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxF,kBAAkB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAExE;;;;;;;OAOG;IACH,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE7D,yGAAyG;IACzG,YAAY,CAAC,IAAI,aAAa,CAAC,OAAO,CAAC,CAAC;IACxC,yEAAyE;IACzE,oBAAoB,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,gDAAgD;IAChD,KAAK,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=raw-store-driver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"raw-store-driver.js","sourceRoot":"","sources":["../../../src/storage/raw-store-driver.ts"],"names":[],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"restoration-coordinator-v2.d.ts","sourceRoot":"","sources":["../../../src/storage/restoration-coordinator-v2.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAGnD,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAGxE;;;;;;;;GAQG;AACH,qBAAa,sBAAsB;IASjC,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,iFAAiF;IACjF,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC;IAZ7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAKtB;gBAGgB,WAAW,EAAE,oBAAoB,EACjC,WAAW,EAAE,YAAY,EACzB,cAAc,EAAE,MAAM;IACvC,iFAAiF;IAChE,UAAU,CAAC,EAAE,MAAM,YAAA;IAGrC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAsC;IAE1D;;OAEG;IACG,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC;IAkDhF;;OAEG;IACH,qBAAqB,IAAI,eAAe;IAMxC;;OAEG;YACW,cAAc;IAM5B;;OAEG;IACH,OAAO,CAAC,cAAc;IAKtB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAczB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAmB1B;;OAEG;YACW,SAAS;IAiBvB;;OAEG;IACH,OAAO,CAAC,aAAa;IAerB;;OAEG;IACH,UAAU,IAAI;QACb,aAAa,EAAE,MAAM,CAAC;QACtB,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACnC,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACnC,iBAAiB,EAAE,MAAM,CAAC;KAC1B;CAGD"}
1
+ {"version":3,"file":"restoration-coordinator-v2.d.ts","sourceRoot":"","sources":["../../../src/storage/restoration-coordinator-v2.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAGnD,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEjE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAGxE;;;;;;;;GAQG;AACH,qBAAa,sBAAsB;IASjC,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,iFAAiF;IACjF,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC;IAZ7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAKtB;gBAGgB,WAAW,EAAE,oBAAoB,EACjC,WAAW,EAAE,YAAY,EACzB,cAAc,EAAE,MAAM;IACvC,iFAAiF;IAChE,UAAU,CAAC,EAAE,MAAM,YAAA;IAGrC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAsC;IAE1D;;OAEG;IACG,OAAO,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC;IAkDhF;;OAEG;IACH,qBAAqB,IAAI,eAAe;IAMxC;;OAEG;YACW,cAAc;IAM5B;;OAEG;IACH,OAAO,CAAC,cAAc;IAKtB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAczB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAmB1B;;OAEG;YACW,SAAS;IAiBvB;;OAEG;IACH,OAAO,CAAC,aAAa;IAarB;;OAEG;IACH,UAAU,IAAI;QACb,aAAa,EAAE,MAAM,CAAC;QACtB,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACnC,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACnC,iBAAiB,EAAE,MAAM,CAAC;KAC1B;CAGD"}
@@ -160,7 +160,7 @@ export class RestorationCoordinator {
160
160
  .reduce((sum, c) => sum + c, 0);
161
161
  const prevTotal = this.metrics.averageDurationMs * (totalSuccesses - 1);
162
162
  this.metrics.averageDurationMs = (prevTotal + durationMs) / totalSuccesses;
163
- console.log(`[Ring ${ringDepth}] Successfully restored block ${blockId} in ${durationMs}ms`);
163
+ this.log('[Ring %d] Successfully restored block %s in %dms', ringDepth, blockId, durationMs);
164
164
  }
165
165
  /**
166
166
  * Get restoration metrics for monitoring.