@lix-js/sdk 0.6.0-preview.3 → 0.6.0-preview.5

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 (235) hide show
  1. package/README.md +1 -1
  2. package/SKILL.md +105 -65
  3. package/dist/engine-wasm/index.js +4 -4
  4. package/dist/engine-wasm/wasm/lix_engine.d.ts +30 -6
  5. package/dist/engine-wasm/wasm/lix_engine.js +187 -117
  6. package/dist/engine-wasm/wasm/lix_engine.wasm +0 -0
  7. package/dist/engine-wasm/wasm/lix_engine.wasm.d.ts +14 -8
  8. package/dist/generated/builtin-schemas.d.ts +69 -69
  9. package/dist/generated/builtin-schemas.js +94 -94
  10. package/dist/open-lix.d.ts +42 -28
  11. package/dist/open-lix.js +49 -10
  12. package/dist/sqlite/index.js +86 -30
  13. package/dist-engine-src/README.md +3 -3
  14. package/dist-engine-src/src/backend/capabilities.rs +67 -0
  15. package/dist-engine-src/src/backend/conformance/baseline.rs +1127 -0
  16. package/dist-engine-src/src/backend/conformance/factory.rs +93 -0
  17. package/dist-engine-src/src/backend/conformance/failure_tests.rs +608 -0
  18. package/dist-engine-src/src/backend/conformance/fixtures.rs +26 -0
  19. package/dist-engine-src/src/backend/conformance/mod.rs +75 -0
  20. package/dist-engine-src/src/backend/conformance/model.rs +28 -0
  21. package/dist-engine-src/src/backend/conformance/model_based.rs +257 -0
  22. package/dist-engine-src/src/backend/conformance/persistence.rs +204 -0
  23. package/dist-engine-src/src/backend/conformance/projection.rs +21 -0
  24. package/dist-engine-src/src/backend/conformance/pushdown.rs +24 -0
  25. package/dist-engine-src/src/backend/conformance/runner.rs +90 -0
  26. package/dist-engine-src/src/backend/conformance/scan.rs +24 -0
  27. package/dist-engine-src/src/backend/conformance/write.rs +16 -0
  28. package/dist-engine-src/src/backend/error.rs +94 -0
  29. package/dist-engine-src/src/backend/in_memory.rs +670 -0
  30. package/dist-engine-src/src/backend/mod.rs +36 -9
  31. package/dist-engine-src/src/backend/predicate.rs +80 -0
  32. package/dist-engine-src/src/backend/traits.rs +260 -0
  33. package/dist-engine-src/src/backend/types.rs +224 -81
  34. package/dist-engine-src/src/binary_cas/context.rs +8 -8
  35. package/dist-engine-src/src/binary_cas/kv.rs +234 -259
  36. package/dist-engine-src/src/{version → branch}/context.rs +12 -12
  37. package/dist-engine-src/src/branch/lifecycle.rs +221 -0
  38. package/dist-engine-src/src/branch/mod.rs +13 -0
  39. package/dist-engine-src/src/branch/refs.rs +321 -0
  40. package/dist-engine-src/src/branch/stage_rows.rs +67 -0
  41. package/dist-engine-src/src/branch/types.rs +21 -0
  42. package/dist-engine-src/src/catalog/context.rs +18 -18
  43. package/dist-engine-src/src/catalog/snapshot.rs +8 -8
  44. package/dist-engine-src/src/changelog/bench_support.rs +785 -0
  45. package/dist-engine-src/src/changelog/change.rs +1 -0
  46. package/dist-engine-src/src/changelog/codec.rs +497 -0
  47. package/dist-engine-src/src/changelog/commit.rs +1 -0
  48. package/dist-engine-src/src/changelog/context.rs +1614 -0
  49. package/dist-engine-src/src/changelog/mod.rs +29 -0
  50. package/dist-engine-src/src/changelog/store.rs +163 -0
  51. package/dist-engine-src/src/changelog/test_support.rs +54 -0
  52. package/dist-engine-src/src/changelog/types.rs +213 -0
  53. package/dist-engine-src/src/commit_graph/context.rs +317 -274
  54. package/dist-engine-src/src/commit_graph/mod.rs +2 -4
  55. package/dist-engine-src/src/commit_graph/types.rs +22 -42
  56. package/dist-engine-src/src/commit_graph/walker.rs +133 -103
  57. package/dist-engine-src/src/common/error.rs +52 -18
  58. package/dist-engine-src/src/common/identity.rs +2 -2
  59. package/dist-engine-src/src/common/mod.rs +1 -1
  60. package/dist-engine-src/src/domain.rs +42 -46
  61. package/dist-engine-src/src/engine.rs +74 -96
  62. package/dist-engine-src/src/{entity_identity.rs → entity_pk.rs} +89 -92
  63. package/dist-engine-src/src/functions/context.rs +56 -52
  64. package/dist-engine-src/src/functions/state.rs +51 -52
  65. package/dist-engine-src/src/init.rs +288 -154
  66. package/dist-engine-src/src/json_store/context.rs +15 -266
  67. package/dist-engine-src/src/json_store/mod.rs +26 -0
  68. package/dist-engine-src/src/json_store/store.rs +103 -718
  69. package/dist-engine-src/src/json_store/types.rs +4 -9
  70. package/dist-engine-src/src/lib.rs +49 -19
  71. package/dist-engine-src/src/live_state/context.rs +654 -790
  72. package/dist-engine-src/src/live_state/mod.rs +9 -3
  73. package/dist-engine-src/src/live_state/overlay.rs +4 -4
  74. package/dist-engine-src/src/live_state/types.rs +30 -21
  75. package/dist-engine-src/src/live_state/visibility.rs +514 -71
  76. package/dist-engine-src/src/plugin/install.rs +48 -48
  77. package/dist-engine-src/src/plugin/manifest.rs +7 -7
  78. package/dist-engine-src/src/plugin/materializer.rs +0 -275
  79. package/dist-engine-src/src/plugin/plugin_manifest.json +4 -3
  80. package/dist-engine-src/src/schema/builtin/lix_binary_blob_ref.json +2 -2
  81. package/dist-engine-src/src/schema/builtin/lix_branch_descriptor.json +34 -0
  82. package/dist-engine-src/src/schema/builtin/lix_branch_ref.json +48 -0
  83. package/dist-engine-src/src/schema/builtin/lix_change.json +3 -3
  84. package/dist-engine-src/src/schema/builtin/lix_commit.json +1 -1
  85. package/dist-engine-src/src/schema/builtin/lix_label_assignment.json +6 -6
  86. package/dist-engine-src/src/schema/builtin/mod.rs +18 -20
  87. package/dist-engine-src/src/schema/compatibility.rs +11 -11
  88. package/dist-engine-src/src/schema/definition.json +2 -2
  89. package/dist-engine-src/src/schema/definition.rs +5 -5
  90. package/dist-engine-src/src/schema/key.rs +3 -3
  91. package/dist-engine-src/src/schema/mod.rs +1 -1
  92. package/dist-engine-src/src/schema/tests.rs +18 -18
  93. package/dist-engine-src/src/session/context.rs +819 -124
  94. package/dist-engine-src/src/session/create_branch.rs +94 -0
  95. package/dist-engine-src/src/session/execute.rs +260 -57
  96. package/dist-engine-src/src/session/merge/analysis.rs +9 -3
  97. package/dist-engine-src/src/session/merge/{version.rs → branch.rs} +119 -129
  98. package/dist-engine-src/src/session/merge/conflicts.rs +2 -2
  99. package/dist-engine-src/src/session/merge/mod.rs +5 -6
  100. package/dist-engine-src/src/session/merge/stats.rs +7 -11
  101. package/dist-engine-src/src/session/mod.rs +19 -16
  102. package/dist-engine-src/src/session/switch_branch.rs +113 -0
  103. package/dist-engine-src/src/session/transaction.rs +557 -0
  104. package/dist-engine-src/src/sql2/bind/classify.rs +102 -0
  105. package/dist-engine-src/src/sql2/bind/error.rs +5 -0
  106. package/dist-engine-src/src/sql2/bind/expr.rs +29 -0
  107. package/dist-engine-src/src/sql2/bind/mod.rs +12 -0
  108. package/dist-engine-src/src/sql2/{udfs/public_call.rs → bind/public_udf.rs} +98 -3
  109. package/dist-engine-src/src/sql2/bind/read.rs +65 -0
  110. package/dist-engine-src/src/sql2/bind/statement.rs +2236 -0
  111. package/dist-engine-src/src/sql2/bind/table.rs +273 -0
  112. package/dist-engine-src/src/sql2/bind/write.rs +86 -0
  113. package/dist-engine-src/src/sql2/branch_scope.rs +436 -0
  114. package/dist-engine-src/src/sql2/catalog/capability.rs +20 -0
  115. package/dist-engine-src/src/sql2/catalog/entity_surface.rs +296 -0
  116. package/dist-engine-src/src/sql2/catalog/mod.rs +15 -0
  117. package/dist-engine-src/src/sql2/catalog/registry.rs +556 -0
  118. package/dist-engine-src/src/sql2/catalog/schema.rs +88 -0
  119. package/dist-engine-src/src/sql2/catalog/surface.rs +41 -0
  120. package/dist-engine-src/src/sql2/change_materialization.rs +122 -0
  121. package/dist-engine-src/src/sql2/context.rs +36 -30
  122. package/dist-engine-src/src/sql2/error.rs +4 -5
  123. package/dist-engine-src/src/sql2/exec/bound_public_write.rs +1593 -0
  124. package/dist-engine-src/src/sql2/exec/datafusion.rs +5266 -0
  125. package/dist-engine-src/src/sql2/exec/fast_write.rs +82 -0
  126. package/dist-engine-src/src/sql2/exec/mod.rs +24 -0
  127. package/dist-engine-src/src/sql2/exec/write.rs +661 -0
  128. package/dist-engine-src/src/sql2/filesystem_planner.rs +72 -77
  129. package/dist-engine-src/src/sql2/filesystem_visibility.rs +21 -21
  130. package/dist-engine-src/src/sql2/history_projection.rs +8 -8
  131. package/dist-engine-src/src/sql2/history_route.rs +35 -31
  132. package/dist-engine-src/src/sql2/mod.rs +30 -24
  133. package/dist-engine-src/src/sql2/optimize/datafusion.rs +1 -0
  134. package/dist-engine-src/src/sql2/optimize/mod.rs +2 -0
  135. package/dist-engine-src/src/sql2/optimize/simple_write.rs +116 -0
  136. package/dist-engine-src/src/sql2/parse/mod.rs +69 -0
  137. package/dist-engine-src/src/sql2/parse/normalize.rs +1 -0
  138. package/dist-engine-src/src/sql2/plan/branch_scope.rs +24 -0
  139. package/dist-engine-src/src/sql2/plan/mod.rs +5 -0
  140. package/dist-engine-src/src/sql2/plan/predicate.rs +22 -0
  141. package/dist-engine-src/src/sql2/plan/write.rs +147 -0
  142. package/dist-engine-src/src/sql2/predicate_typecheck.rs +258 -0
  143. package/dist-engine-src/src/sql2/{version_provider.rs → providers/branch.rs} +218 -214
  144. package/dist-engine-src/src/sql2/{change_provider.rs → providers/change.rs} +156 -42
  145. package/dist-engine-src/src/sql2/{directory_provider.rs → providers/directory.rs} +291 -322
  146. package/dist-engine-src/src/sql2/{directory_history_provider.rs → providers/directory_history.rs} +56 -42
  147. package/dist-engine-src/src/sql2/providers/entity.rs +1484 -0
  148. package/dist-engine-src/src/sql2/{entity_history_provider.rs → providers/entity_history.rs} +43 -31
  149. package/dist-engine-src/src/sql2/{file_provider.rs → providers/file.rs} +323 -316
  150. package/dist-engine-src/src/sql2/{file_history_provider.rs → providers/file_history.rs} +60 -46
  151. package/dist-engine-src/src/sql2/{history_provider.rs → providers/history.rs} +46 -32
  152. package/dist-engine-src/src/sql2/{lix_state_provider.rs → providers/lix_state.rs} +359 -329
  153. package/dist-engine-src/src/sql2/providers/mod.rs +508 -0
  154. package/dist-engine-src/src/sql2/read_only.rs +2 -2
  155. package/dist-engine-src/src/sql2/session.rs +47 -96
  156. package/dist-engine-src/src/sql2/storage/constraints.rs +1 -0
  157. package/dist-engine-src/src/sql2/storage/mod.rs +1 -0
  158. package/dist-engine-src/src/sql2/test_support/differential.rs +712 -0
  159. package/dist-engine-src/src/sql2/test_support/generators.rs +354 -0
  160. package/dist-engine-src/src/sql2/test_support/mod.rs +2 -0
  161. package/dist-engine-src/src/sql2/udfs/{lix_active_version_commit_id.rs → lix_active_branch_commit_id.rs} +7 -7
  162. package/dist-engine-src/src/sql2/udfs/mod.rs +3 -6
  163. package/dist-engine-src/src/sql2/write_normalization.rs +45 -22
  164. package/dist-engine-src/src/storage/conformance.rs +399 -0
  165. package/dist-engine-src/src/storage/context.rs +552 -288
  166. package/dist-engine-src/src/storage/mod.rs +48 -10
  167. package/dist-engine-src/src/storage/point.rs +440 -0
  168. package/dist-engine-src/src/storage/read_scope.rs +43 -64
  169. package/dist-engine-src/src/storage/reader.rs +867 -0
  170. package/dist-engine-src/src/storage/scan.rs +784 -0
  171. package/dist-engine-src/src/storage/spaces.rs +236 -0
  172. package/dist-engine-src/src/storage/stats.rs +80 -0
  173. package/dist-engine-src/src/storage/write_set.rs +962 -0
  174. package/dist-engine-src/src/storage_bench.rs +136 -4828
  175. package/dist-engine-src/src/test_support.rs +360 -138
  176. package/dist-engine-src/src/tracked_state/bench_support.rs +394 -0
  177. package/dist-engine-src/src/tracked_state/codec.rs +155 -1057
  178. package/dist-engine-src/src/tracked_state/commit_root_rebuild.rs +358 -0
  179. package/dist-engine-src/src/tracked_state/context.rs +1927 -993
  180. package/dist-engine-src/src/tracked_state/diff.rs +1715 -261
  181. package/dist-engine-src/src/tracked_state/merge.rs +74 -88
  182. package/dist-engine-src/src/tracked_state/mod.rs +19 -16
  183. package/dist-engine-src/src/tracked_state/{materialization.rs → row_materialization.rs} +50 -178
  184. package/dist-engine-src/src/tracked_state/storage.rs +243 -191
  185. package/dist-engine-src/src/tracked_state/tree.rs +247 -371
  186. package/dist-engine-src/src/tracked_state/types.rs +49 -42
  187. package/dist-engine-src/src/transaction/bench_support.rs +407 -0
  188. package/dist-engine-src/src/transaction/commit.rs +821 -713
  189. package/dist-engine-src/src/transaction/context.rs +705 -600
  190. package/dist-engine-src/src/transaction/mod.rs +13 -2
  191. package/dist-engine-src/src/transaction/normalization.rs +63 -76
  192. package/dist-engine-src/src/transaction/prep.rs +13 -13
  193. package/dist-engine-src/src/transaction/schema_resolver.rs +19 -5
  194. package/dist-engine-src/src/transaction/staging.rs +228 -434
  195. package/dist-engine-src/src/transaction/types.rs +41 -98
  196. package/dist-engine-src/src/transaction/validation.rs +382 -446
  197. package/dist-engine-src/src/untracked_state/codec.rs +337 -29
  198. package/dist-engine-src/src/untracked_state/context.rs +7 -7
  199. package/dist-engine-src/src/untracked_state/materialization.rs +2 -2
  200. package/dist-engine-src/src/untracked_state/mod.rs +1 -1
  201. package/dist-engine-src/src/untracked_state/storage.rs +659 -157
  202. package/dist-engine-src/src/untracked_state/types.rs +21 -21
  203. package/package.json +71 -68
  204. package/dist-engine-src/src/backend/kv.rs +0 -358
  205. package/dist-engine-src/src/backend/testing.rs +0 -658
  206. package/dist-engine-src/src/commit_store/codec.rs +0 -887
  207. package/dist-engine-src/src/commit_store/context.rs +0 -944
  208. package/dist-engine-src/src/commit_store/materialization.rs +0 -84
  209. package/dist-engine-src/src/commit_store/mod.rs +0 -16
  210. package/dist-engine-src/src/commit_store/storage.rs +0 -600
  211. package/dist-engine-src/src/commit_store/types.rs +0 -215
  212. package/dist-engine-src/src/schema/builtin/lix_version_descriptor.json +0 -34
  213. package/dist-engine-src/src/schema/builtin/lix_version_ref.json +0 -48
  214. package/dist-engine-src/src/session/create_version.rs +0 -88
  215. package/dist-engine-src/src/session/merge/apply.rs +0 -23
  216. package/dist-engine-src/src/session/optimization9_sql2_bench.rs +0 -100
  217. package/dist-engine-src/src/session/switch_version.rs +0 -109
  218. package/dist-engine-src/src/sql2/classify.rs +0 -182
  219. package/dist-engine-src/src/sql2/entity_provider.rs +0 -3211
  220. package/dist-engine-src/src/sql2/execute.rs +0 -3440
  221. package/dist-engine-src/src/sql2/public_bind/assignment.rs +0 -46
  222. package/dist-engine-src/src/sql2/public_bind/capability.rs +0 -41
  223. package/dist-engine-src/src/sql2/public_bind/dml.rs +0 -166
  224. package/dist-engine-src/src/sql2/public_bind/mod.rs +0 -25
  225. package/dist-engine-src/src/sql2/public_bind/table.rs +0 -168
  226. package/dist-engine-src/src/sql2/version_scope.rs +0 -394
  227. package/dist-engine-src/src/storage/types.rs +0 -501
  228. package/dist-engine-src/src/tracked_state/by_file_index.rs +0 -98
  229. package/dist-engine-src/src/tracked_state/materializer.rs +0 -488
  230. package/dist-engine-src/src/transaction/live_state_overlay.rs +0 -35
  231. package/dist-engine-src/src/version/lifecycle.rs +0 -221
  232. package/dist-engine-src/src/version/mod.rs +0 -13
  233. package/dist-engine-src/src/version/refs.rs +0 -330
  234. package/dist-engine-src/src/version/stage_rows.rs +0 -67
  235. package/dist-engine-src/src/version/types.rs +0 -21
@@ -4,11 +4,10 @@ use crate::json_store::types::{
4
4
  JsonProjectionLoadRequestRef, JsonRef, JsonValueBatch, JsonWritePlacementRef,
5
5
  NormalizedJsonRef,
6
6
  };
7
- use crate::storage::{KvGetGroup, StorageReader, StorageWriteSet};
7
+ use crate::storage::{StorageKey, StorageRead, StorageValue, StorageWriteSet};
8
8
  use crate::LixError;
9
- use std::collections::{HashMap, HashSet};
10
-
11
- const PACK_LOCAL_MAX_JSON_BYTES: usize = 64 * 1024;
9
+ use bytes::Bytes;
10
+ use std::collections::HashSet;
12
11
 
13
12
  #[derive(Debug, Clone, Copy)]
14
13
  pub(crate) struct JsonStoreContext;
@@ -20,7 +19,7 @@ impl JsonStoreContext {
20
19
 
21
20
  pub(crate) fn reader<S>(&self, store: S) -> JsonStoreReader<S>
22
21
  where
23
- S: StorageReader,
22
+ S: StorageRead,
24
23
  {
25
24
  JsonStoreReader { store }
26
25
  }
@@ -31,24 +30,13 @@ impl JsonStoreContext {
31
30
 
32
31
  pub(crate) async fn load_bytes_many(
33
32
  &self,
34
- store: &mut impl StorageReader,
33
+ store: &(impl StorageRead + ?Sized),
35
34
  request: JsonLoadRequestRef<'_>,
36
35
  ) -> Result<JsonLoadBatch, LixError> {
37
36
  store::load_json_bytes_many_in_scope(store, request.refs, request.scope)
38
37
  .await
39
38
  .map(JsonLoadBatch::new)
40
39
  }
41
-
42
- pub(crate) fn commit_pack_get_group(&self, commit_id: &str, pack_id: u32) -> KvGetGroup {
43
- KvGetGroup {
44
- namespace: store::JSON_PACK_NAMESPACE.to_string(),
45
- keys: vec![store::pack_key(commit_id, pack_id)],
46
- }
47
- }
48
-
49
- pub(crate) fn decode_pack_refs(&self, bytes: &[u8]) -> Result<Vec<JsonRef>, LixError> {
50
- store::decode_json_pack_refs(bytes)
51
- }
52
40
  }
53
41
 
54
42
  pub(crate) struct JsonStoreReader<S> {
@@ -68,13 +56,13 @@ where
68
56
 
69
57
  impl<S> JsonStoreReader<S>
70
58
  where
71
- S: StorageReader,
59
+ S: StorageRead,
72
60
  {
73
61
  pub(crate) async fn load_bytes_many(
74
62
  &mut self,
75
63
  request: JsonLoadRequestRef<'_>,
76
64
  ) -> Result<JsonLoadBatch, LixError> {
77
- store::load_json_bytes_many_in_scope(&mut self.store, request.refs, request.scope)
65
+ store::load_json_bytes_many_in_scope(&self.store, request.refs, request.scope)
78
66
  .await
79
67
  .map(JsonLoadBatch::new)
80
68
  }
@@ -136,12 +124,6 @@ where
136
124
 
137
125
  pub(crate) struct JsonStoreWriter;
138
126
 
139
- #[derive(Debug, Clone, Default)]
140
- pub(crate) struct JsonStageBatchReport {
141
- pub(crate) refs: Vec<JsonRef>,
142
- pub(crate) pack_indexes: HashMap<[u8; 32], usize>,
143
- }
144
-
145
127
  impl JsonStoreWriter {
146
128
  fn new() -> Self {
147
129
  Self
@@ -150,19 +132,10 @@ impl JsonStoreWriter {
150
132
  pub(crate) fn stage_batch<'a>(
151
133
  &mut self,
152
134
  writes: &mut StorageWriteSet,
153
- placement: JsonWritePlacementRef<'a>,
135
+ placement: JsonWritePlacementRef,
154
136
  payloads: impl IntoIterator<Item = NormalizedJsonRef<'a>>,
155
137
  ) -> Result<Vec<JsonRef>, LixError> {
156
- self.stage_batch_report(writes, placement, payloads)
157
- .map(|report| report.refs)
158
- }
159
-
160
- pub(crate) fn stage_batch_report<'a>(
161
- &mut self,
162
- writes: &mut StorageWriteSet,
163
- placement: JsonWritePlacementRef<'a>,
164
- payloads: impl IntoIterator<Item = NormalizedJsonRef<'a>>,
165
- ) -> Result<JsonStageBatchReport, LixError> {
138
+ let JsonWritePlacementRef::OutOfBand = placement;
166
139
  let mut unique_encoded = Vec::new();
167
140
  let mut order = Vec::new();
168
141
  let mut seen = HashSet::new();
@@ -184,240 +157,16 @@ impl JsonStoreWriter {
184
157
  }
185
158
  }
186
159
 
187
- let pack_local = matches!(placement, JsonWritePlacementRef::CommitPack { .. });
188
- let mut pack_indexes = HashMap::new();
189
- if let JsonWritePlacementRef::CommitPack { commit_id, pack_id } = placement {
190
- let pack_entries = unique_encoded
191
- .iter()
192
- .filter(|encoded| encoded.uncompressed_len <= PACK_LOCAL_MAX_JSON_BYTES)
193
- .collect::<Vec<_>>();
194
- for (index, encoded) in pack_entries.iter().enumerate() {
195
- pack_indexes.insert(*encoded.json_ref.as_hash_array(), index);
196
- }
197
- if !pack_entries.is_empty() {
198
- let encoded_pack = store::encode_json_pack(&pack_entries)?;
199
- writes.put(
200
- store::JSON_PACK_NAMESPACE,
201
- store::pack_key(commit_id, pack_id),
202
- encoded_pack,
203
- );
204
- }
205
- }
206
-
207
160
  for encoded in &unique_encoded {
208
- if pack_local && encoded.uncompressed_len <= PACK_LOCAL_MAX_JSON_BYTES {
209
- continue;
210
- }
211
161
  writes.put(
212
- store::JSON_NAMESPACE,
213
- encoded.json_ref.as_hash_bytes().to_vec(),
214
- store::encode_direct_json_payload(encoded),
162
+ store::JSON_SPACE,
163
+ StorageKey(Bytes::copy_from_slice(encoded.json_ref.as_hash_bytes())),
164
+ StorageValue {
165
+ bytes: Bytes::from(store::encode_direct_json_payload(encoded)),
166
+ },
215
167
  );
216
168
  }
217
169
 
218
- Ok(JsonStageBatchReport {
219
- refs: order,
220
- pack_indexes,
221
- })
222
- }
223
- }
224
-
225
- #[cfg(test)]
226
- mod tests {
227
- use std::sync::Arc;
228
-
229
- use super::*;
230
- use crate::backend::testing::UnitTestBackend;
231
- use crate::json_store::types::JsonReadScopeRef;
232
- use crate::storage::StorageContext;
233
-
234
- #[tokio::test]
235
- async fn commit_local_batch_writes_pack_without_direct_rows() {
236
- let storage = StorageContext::new(Arc::new(UnitTestBackend::new()));
237
- let context = JsonStoreContext::new();
238
- let first = "{\"value\":\"first\"}";
239
- let second = "{\"value\":\"second\"}";
240
-
241
- let mut transaction = storage
242
- .begin_write_transaction()
243
- .await
244
- .expect("transaction should open");
245
- let mut writes = StorageWriteSet::new();
246
- context
247
- .writer()
248
- .stage_batch(
249
- &mut writes,
250
- JsonWritePlacementRef::CommitPack {
251
- commit_id: "commit-a",
252
- pack_id: 0,
253
- },
254
- [
255
- NormalizedJsonRef::new(first),
256
- NormalizedJsonRef::new(second),
257
- ],
258
- )
259
- .expect("json pack should stage");
260
- writes
261
- .apply(&mut transaction.as_mut())
262
- .await
263
- .expect("json pack should apply");
264
- transaction
265
- .commit()
266
- .await
267
- .expect("transaction should commit");
268
-
269
- let refs = [
270
- JsonRef::for_content(first.as_bytes()),
271
- JsonRef::for_content(second.as_bytes()),
272
- ];
273
- let unknown = context
274
- .reader(storage.clone())
275
- .load_bytes_many(JsonLoadRequestRef {
276
- refs: &refs,
277
- scope: JsonReadScopeRef::OutOfBand,
278
- })
279
- .await
280
- .expect("unknown load should check direct rows");
281
- assert_eq!(unknown.into_values(), vec![None, None]);
282
-
283
- let pack_ids = [0];
284
- let packed = context
285
- .reader(storage.clone())
286
- .load_bytes_many(JsonLoadRequestRef {
287
- refs: &refs,
288
- scope: JsonReadScopeRef::CommitPacks {
289
- commit_id: "commit-a",
290
- pack_ids: &pack_ids,
291
- },
292
- })
293
- .await
294
- .expect("packed load should hydrate");
295
- assert_eq!(
296
- packed.into_values(),
297
- vec![
298
- Some(first.as_bytes().to_vec()),
299
- Some(second.as_bytes().to_vec())
300
- ]
301
- );
302
- }
303
-
304
- #[tokio::test]
305
- async fn commit_local_batch_dedupes_pack_payloads_but_returns_request_order() {
306
- let storage = StorageContext::new(Arc::new(UnitTestBackend::new()));
307
- let context = JsonStoreContext::new();
308
- let first = "{\"value\":\"first\"}";
309
- let second = "{\"value\":\"second\"}";
310
-
311
- let mut transaction = storage
312
- .begin_write_transaction()
313
- .await
314
- .expect("transaction should open");
315
- let mut writes = StorageWriteSet::new();
316
- let staged_refs = context
317
- .writer()
318
- .stage_batch(
319
- &mut writes,
320
- JsonWritePlacementRef::CommitPack {
321
- commit_id: "commit-a",
322
- pack_id: 0,
323
- },
324
- [
325
- NormalizedJsonRef::new(first),
326
- NormalizedJsonRef::new(first),
327
- NormalizedJsonRef::new(second),
328
- ],
329
- )
330
- .expect("json pack should stage");
331
- writes
332
- .apply(&mut transaction.as_mut())
333
- .await
334
- .expect("json pack should apply");
335
- transaction
336
- .commit()
337
- .await
338
- .expect("transaction should commit");
339
-
340
- let first_ref = JsonRef::for_content(first.as_bytes());
341
- let second_ref = JsonRef::for_content(second.as_bytes());
342
- assert_eq!(staged_refs, vec![first_ref, first_ref, second_ref]);
343
-
344
- let refs = [first_ref, second_ref];
345
- let unknown = context
346
- .reader(storage.clone())
347
- .load_bytes_many(JsonLoadRequestRef {
348
- refs: &refs,
349
- scope: JsonReadScopeRef::OutOfBand,
350
- })
351
- .await
352
- .expect("unknown load should check direct rows");
353
- assert_eq!(unknown.into_values(), vec![None, None]);
354
-
355
- let pack_ids = [0];
356
- let packed = context
357
- .reader(storage.clone())
358
- .load_bytes_many(JsonLoadRequestRef {
359
- refs: &refs,
360
- scope: JsonReadScopeRef::CommitPacks {
361
- commit_id: "commit-a",
362
- pack_ids: &pack_ids,
363
- },
364
- })
365
- .await
366
- .expect("packed load should hydrate");
367
- assert_eq!(
368
- packed.into_values(),
369
- vec![
370
- Some(first.as_bytes().to_vec()),
371
- Some(second.as_bytes().to_vec())
372
- ]
373
- );
374
- }
375
-
376
- #[tokio::test]
377
- async fn commit_local_batch_accepts_trusted_prehashed_payload() {
378
- let storage = StorageContext::new(Arc::new(UnitTestBackend::new()));
379
- let context = JsonStoreContext::new();
380
- let json = "{\"value\":\"prehashed\"}";
381
- let json_ref = JsonRef::for_content(json.as_bytes());
382
-
383
- let mut transaction = storage
384
- .begin_write_transaction()
385
- .await
386
- .expect("transaction should open");
387
- let mut writes = StorageWriteSet::new();
388
- let refs = context
389
- .writer()
390
- .stage_batch(
391
- &mut writes,
392
- JsonWritePlacementRef::CommitPack {
393
- commit_id: "commit-a",
394
- pack_id: 0,
395
- },
396
- [NormalizedJsonRef::trusted_prehashed(json, json_ref)],
397
- )
398
- .expect("prehashed json should stage");
399
- assert_eq!(refs, vec![json_ref]);
400
- writes
401
- .apply(&mut transaction.as_mut())
402
- .await
403
- .expect("json pack should apply");
404
- transaction
405
- .commit()
406
- .await
407
- .expect("transaction should commit");
408
-
409
- let pack_ids = [0];
410
- let packed = context
411
- .reader(storage.clone())
412
- .load_bytes_many(JsonLoadRequestRef {
413
- refs: &refs,
414
- scope: JsonReadScopeRef::CommitPacks {
415
- commit_id: "commit-a",
416
- pack_ids: &pack_ids,
417
- },
418
- })
419
- .await
420
- .expect("prehashed payload should hydrate");
421
- assert_eq!(packed.into_values(), vec![Some(json.as_bytes().to_vec())]);
170
+ Ok(order)
422
171
  }
423
172
  }
@@ -4,9 +4,35 @@ mod encoded;
4
4
  pub(crate) mod store;
5
5
  pub(crate) mod types;
6
6
 
7
+ use crate::storage::StorageWriteSet;
8
+ use crate::LixError;
9
+
7
10
  #[allow(unused_imports)]
8
11
  pub(crate) use context::{JsonStoreContext, JsonStoreReader, JsonStoreWriter};
9
12
  pub(crate) use types::{
10
13
  JsonLoadRequestRef, JsonReadScopeRef, JsonRef, JsonWritePlacementRef, NormalizedJson,
11
14
  NormalizedJsonRef,
12
15
  };
16
+
17
+ pub(crate) fn direct_json_payload_ref_from_key(key: &[u8]) -> Result<JsonRef, LixError> {
18
+ let hash: [u8; 32] = key.try_into().map_err(|_| {
19
+ LixError::unknown(format!(
20
+ "json_store direct payload key has {} bytes, expected 32",
21
+ key.len()
22
+ ))
23
+ })?;
24
+ Ok(JsonRef::from_hash_bytes(hash))
25
+ }
26
+
27
+ pub(crate) fn stage_direct_json_payload_delete(writes: &mut StorageWriteSet, json_ref: &JsonRef) {
28
+ writes.delete(store::JSON_SPACE, json_ref.as_hash_bytes().to_vec());
29
+ }
30
+
31
+ #[cfg(any(test, feature = "storage-benches"))]
32
+ pub(crate) fn stage_direct_json_payload_put(
33
+ writes: &mut StorageWriteSet,
34
+ json_ref: &JsonRef,
35
+ bytes: Vec<u8>,
36
+ ) {
37
+ writes.put(store::JSON_SPACE, json_ref.as_hash_bytes().to_vec(), bytes);
38
+ }