@lix-js/sdk 0.6.0-preview.4 → 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 (234) hide show
  1. package/README.md +1 -1
  2. package/SKILL.md +65 -64
  3. package/dist/engine-wasm/index.js +4 -4
  4. package/dist/engine-wasm/wasm/lix_engine.d.ts +5 -5
  5. package/dist/engine-wasm/wasm/lix_engine.js +130 -118
  6. package/dist/engine-wasm/wasm/lix_engine.wasm +0 -0
  7. package/dist/engine-wasm/wasm/lix_engine.wasm.d.ts +9 -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 +33 -26
  11. package/dist/open-lix.js +10 -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 +803 -148
  94. package/dist-engine-src/src/session/create_branch.rs +94 -0
  95. package/dist-engine-src/src/session/execute.rs +223 -83
  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 +15 -12
  102. package/dist-engine-src/src/session/switch_branch.rs +113 -0
  103. package/dist-engine-src/src/session/transaction.rs +495 -14
  104. package/dist-engine-src/src/sql2/{classify.rs → bind/classify.rs} +3 -75
  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} +71 -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 +1 -1
  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 +28 -23
  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 -110
  218. package/dist-engine-src/src/sql2/entity_provider.rs +0 -3211
  219. package/dist-engine-src/src/sql2/execute.rs +0 -3533
  220. package/dist-engine-src/src/sql2/public_bind/assignment.rs +0 -46
  221. package/dist-engine-src/src/sql2/public_bind/capability.rs +0 -41
  222. package/dist-engine-src/src/sql2/public_bind/dml.rs +0 -172
  223. package/dist-engine-src/src/sql2/public_bind/mod.rs +0 -26
  224. package/dist-engine-src/src/sql2/public_bind/table.rs +0 -168
  225. package/dist-engine-src/src/sql2/version_scope.rs +0 -394
  226. package/dist-engine-src/src/storage/types.rs +0 -501
  227. package/dist-engine-src/src/tracked_state/by_file_index.rs +0 -98
  228. package/dist-engine-src/src/tracked_state/materializer.rs +0 -488
  229. package/dist-engine-src/src/transaction/live_state_overlay.rs +0 -35
  230. package/dist-engine-src/src/version/lifecycle.rs +0 -221
  231. package/dist-engine-src/src/version/mod.rs +0 -13
  232. package/dist-engine-src/src/version/refs.rs +0 -330
  233. package/dist-engine-src/src/version/stage_rows.rs +0 -67
  234. package/dist-engine-src/src/version/types.rs +0 -21
@@ -1,27 +1,26 @@
1
- use crate::entity_identity::EntityIdentity;
1
+ use crate::entity_pk::EntityPk;
2
2
  use crate::json_store::JsonRef;
3
3
  use crate::json_store::{JsonLoadRequestRef, JsonReadScopeRef, JsonStoreContext};
4
- use crate::storage::StorageReader;
4
+ use crate::storage::StorageRead;
5
5
  use crate::tracked_state::types::{TrackedStateIndexValue, TrackedStateKey};
6
6
  use crate::tracked_state::MaterializedTrackedStateRow;
7
7
  use crate::LixError;
8
- use std::collections::BTreeMap;
9
8
 
10
9
  /// Materializes tracked-state index entries.
11
10
  ///
12
- /// The durable tracked_state value is authoritative for scalar projection
13
- /// fields and stores the JSON refs needed for payload projections. Snapshot and
11
+ /// The durable tracked_state value is authoritative for scalar materialization
12
+ /// fields and stores the JSON refs needed for payload hydration. Snapshot and
14
13
  /// metadata bytes are hydrated from grouped json_store loads only when the
15
- /// requested projection needs them.
16
- pub(crate) async fn materialize_index_entries<S>(
17
- store: &mut S,
14
+ /// requested materialization needs them.
15
+ pub(crate) async fn materialize_rows_from_index_entries<S>(
16
+ store: &S,
18
17
  entries: Vec<(TrackedStateKey, TrackedStateIndexValue)>,
19
- projection: &TrackedMaterializationProjection,
18
+ materialization: &TrackedRowMaterialization,
20
19
  ) -> Result<Vec<MaterializedTrackedStateRow>, LixError>
21
20
  where
22
- S: StorageReader,
21
+ S: StorageRead + Send + Sync,
23
22
  {
24
- if !projection.snapshot_content && !projection.metadata {
23
+ if !materialization.snapshot_content && !materialization.metadata {
25
24
  return Ok(entries
26
25
  .into_iter()
27
26
  .map(materialize_entry_without_json)
@@ -29,45 +28,40 @@ where
29
28
  }
30
29
 
31
30
  let json_slots_per_row =
32
- usize::from(projection.snapshot_content) + usize::from(projection.metadata);
31
+ usize::from(materialization.snapshot_content) + usize::from(materialization.metadata);
33
32
  let json_ref_capacity = entries.len().saturating_mul(json_slots_per_row);
34
33
  let mut row_plans = Vec::with_capacity(entries.len());
35
34
  let mut json_refs = Vec::with_capacity(json_ref_capacity);
36
35
  let mut json_ref_localities = Vec::with_capacity(json_ref_capacity);
37
36
  for (key, value) in entries {
38
- let row_index = row_plans.len();
39
- let snapshot_ref_index = projected_json_ref_index(
40
- projection.snapshot_content,
37
+ let snapshot_ref_index = materialized_json_ref_index(
38
+ materialization.snapshot_content,
41
39
  value.snapshot_ref,
42
- row_index,
43
- value.change_locator.source_pack_id,
44
40
  &mut json_refs,
45
41
  &mut json_ref_localities,
46
42
  );
47
- let metadata_ref_index = projected_json_ref_index(
48
- projection.metadata,
43
+ let metadata_ref_index = materialized_json_ref_index(
44
+ materialization.metadata,
49
45
  value.metadata_ref,
50
- row_index,
51
- value.change_locator.source_pack_id,
52
46
  &mut json_refs,
53
47
  &mut json_ref_localities,
54
48
  );
55
- row_plans.push(MaterializedTrackedStateRowPlan {
56
- entity_id: key.entity_id,
49
+ row_plans.push(TrackedRowMaterializationPlan {
50
+ entity_pk: key.entity_pk,
57
51
  schema_key: key.schema_key,
58
52
  file_id: key.file_id,
59
53
  deleted: value.deleted,
60
54
  created_at: value.created_at,
61
55
  updated_at: value.updated_at,
62
- change_id: value.change_locator.change_id,
63
- commit_id: value.change_locator.source_commit_id,
56
+ change_id: value.change_id,
57
+ commit_id: value.commit_id,
64
58
  snapshot_ref_index,
65
59
  metadata_ref_index,
66
60
  });
67
61
  }
68
62
 
69
63
  let mut json_values =
70
- load_projection_json_values(store, &json_refs, &json_ref_localities, &row_plans).await?;
64
+ load_materialization_json_values(store, &json_refs, &json_ref_localities).await?;
71
65
  row_plans
72
66
  .into_iter()
73
67
  .map(|plan| materialize_row_plan(plan, &json_refs, &mut json_values))
@@ -78,7 +72,7 @@ fn materialize_entry_without_json(
78
72
  (key, value): (TrackedStateKey, TrackedStateIndexValue),
79
73
  ) -> MaterializedTrackedStateRow {
80
74
  MaterializedTrackedStateRow {
81
- entity_id: key.entity_id,
75
+ entity_pk: key.entity_pk,
82
76
  schema_key: key.schema_key,
83
77
  file_id: key.file_id,
84
78
  snapshot_content: None,
@@ -86,13 +80,13 @@ fn materialize_entry_without_json(
86
80
  deleted: value.deleted,
87
81
  created_at: value.created_at,
88
82
  updated_at: value.updated_at,
89
- change_id: value.change_locator.change_id,
90
- commit_id: value.change_locator.source_commit_id,
83
+ change_id: value.change_id,
84
+ commit_id: value.commit_id,
91
85
  }
92
86
  }
93
87
 
94
- struct MaterializedTrackedStateRowPlan {
95
- entity_id: EntityIdentity,
88
+ struct TrackedRowMaterializationPlan {
89
+ entity_pk: EntityPk,
96
90
  schema_key: String,
97
91
  file_id: Option<String>,
98
92
  deleted: bool,
@@ -104,11 +98,9 @@ struct MaterializedTrackedStateRowPlan {
104
98
  metadata_ref_index: Option<usize>,
105
99
  }
106
100
 
107
- fn projected_json_ref_index(
101
+ fn materialized_json_ref_index(
108
102
  include: bool,
109
103
  json_ref: Option<JsonRef>,
110
- row_index: usize,
111
- pack_id: u32,
112
104
  json_refs: &mut Vec<JsonRef>,
113
105
  json_ref_localities: &mut Vec<JsonRefLocality>,
114
106
  ) -> Option<usize> {
@@ -117,23 +109,19 @@ fn projected_json_ref_index(
117
109
  }
118
110
  let index = json_refs.len();
119
111
  json_refs.push(json_ref?);
120
- json_ref_localities.push(JsonRefLocality { row_index, pack_id });
112
+ json_ref_localities.push(JsonRefLocality);
121
113
  Some(index)
122
114
  }
123
115
 
124
- struct JsonRefLocality {
125
- row_index: usize,
126
- pack_id: u32,
127
- }
116
+ struct JsonRefLocality;
128
117
 
129
- async fn load_projection_json_values<S>(
130
- store: &mut S,
118
+ async fn load_materialization_json_values<S>(
119
+ store: &S,
131
120
  json_refs: &[JsonRef],
132
121
  json_ref_localities: &[JsonRefLocality],
133
- row_plans: &[MaterializedTrackedStateRowPlan],
134
122
  ) -> Result<Vec<Option<Vec<u8>>>, LixError>
135
123
  where
136
- S: StorageReader,
124
+ S: StorageRead + Send + Sync,
137
125
  {
138
126
  if json_refs.len() != json_ref_localities.len() {
139
127
  return Err(LixError::new(
@@ -142,109 +130,48 @@ where
142
130
  ));
143
131
  }
144
132
 
145
- let json_store = JsonStoreContext::new();
146
- if let Some((commit_id, pack_id)) = single_projection_pack(json_ref_localities, row_plans)? {
147
- let pack_ids = [pack_id];
148
- return json_store
149
- .load_bytes_many(
150
- store,
151
- JsonLoadRequestRef {
152
- refs: json_refs,
153
- scope: JsonReadScopeRef::CommitPacks {
154
- commit_id,
155
- pack_ids: &pack_ids,
156
- },
157
- },
158
- )
159
- .await
160
- .map(|batch| batch.into_values());
161
- }
162
-
163
133
  let mut json_values = vec![None; json_refs.len()];
164
- let mut refs_by_pack = BTreeMap::<(&str, u32), Vec<(usize, JsonRef)>>::new();
134
+ let mut out_of_band_indexes = Vec::new();
135
+ let mut out_of_band_refs = Vec::new();
165
136
  for (index, json_ref) in json_refs.iter().copied().enumerate() {
166
- let locality = json_ref_localities.get(index).ok_or_else(|| {
137
+ let _locality = json_ref_localities.get(index).ok_or_else(|| {
167
138
  LixError::new(
168
139
  LixError::CODE_INTERNAL_ERROR,
169
140
  "tracked_state materialization lost JSON locality index",
170
141
  )
171
142
  })?;
172
- let row_plan = row_plans.get(locality.row_index).ok_or_else(|| {
173
- LixError::new(
174
- LixError::CODE_INTERNAL_ERROR,
175
- "tracked_state materialization lost JSON row locality index",
176
- )
177
- })?;
178
- refs_by_pack
179
- .entry((row_plan.commit_id.as_str(), locality.pack_id))
180
- .or_default()
181
- .push((index, json_ref));
143
+ out_of_band_indexes.push(index);
144
+ out_of_band_refs.push(json_ref);
182
145
  }
183
146
 
184
- for ((commit_id, pack_id), refs) in refs_by_pack {
185
- let indexes = refs.iter().map(|(index, _)| *index).collect::<Vec<_>>();
186
- let refs = refs
187
- .into_iter()
188
- .map(|(_, json_ref)| json_ref)
189
- .collect::<Vec<_>>();
190
- let pack_ids = [pack_id];
191
- let values = json_store
147
+ if !out_of_band_refs.is_empty() {
148
+ let values = JsonStoreContext::new()
192
149
  .load_bytes_many(
193
150
  store,
194
151
  JsonLoadRequestRef {
195
- refs: &refs,
196
- scope: JsonReadScopeRef::CommitPacks {
197
- commit_id: &commit_id,
198
- pack_ids: &pack_ids,
199
- },
152
+ refs: &out_of_band_refs,
153
+ scope: JsonReadScopeRef::OutOfBand,
200
154
  },
201
155
  )
202
156
  .await?
203
157
  .into_values();
204
- for (index, value) in indexes.into_iter().zip(values) {
205
- json_values[index] = value;
158
+ for (index, value) in out_of_band_indexes.into_iter().zip(values) {
159
+ if value.is_some() {
160
+ json_values[index] = value;
161
+ }
206
162
  }
207
163
  }
208
- Ok(json_values)
209
- }
210
164
 
211
- fn single_projection_pack<'a>(
212
- json_ref_localities: &[JsonRefLocality],
213
- row_plans: &'a [MaterializedTrackedStateRowPlan],
214
- ) -> Result<Option<(&'a str, u32)>, LixError> {
215
- let Some(first_locality) = json_ref_localities.first() else {
216
- return Ok(None);
217
- };
218
- let first_plan = row_plans.get(first_locality.row_index).ok_or_else(|| {
219
- LixError::new(
220
- LixError::CODE_INTERNAL_ERROR,
221
- "tracked_state materialization lost JSON row locality index",
222
- )
223
- })?;
224
- let commit_id = first_plan.commit_id.as_str();
225
- let pack_id = first_locality.pack_id;
226
-
227
- for locality in &json_ref_localities[1..] {
228
- let row_plan = row_plans.get(locality.row_index).ok_or_else(|| {
229
- LixError::new(
230
- LixError::CODE_INTERNAL_ERROR,
231
- "tracked_state materialization lost JSON row locality index",
232
- )
233
- })?;
234
- if row_plan.commit_id != commit_id || locality.pack_id != pack_id {
235
- return Ok(None);
236
- }
237
- }
238
- Ok(Some((commit_id, pack_id)))
165
+ Ok(json_values)
239
166
  }
240
167
 
241
168
  fn materialize_row_plan(
242
- plan: MaterializedTrackedStateRowPlan,
169
+ plan: TrackedRowMaterializationPlan,
243
170
  json_refs: &[JsonRef],
244
171
  json_values: &mut [Option<Vec<u8>>],
245
172
  ) -> Result<MaterializedTrackedStateRow, LixError> {
246
173
  Ok(MaterializedTrackedStateRow {
247
- entity_id: plan.entity_id,
174
+ entity_pk: plan.entity_pk,
248
175
  schema_key: plan.schema_key,
249
176
  file_id: plan.file_id,
250
177
  snapshot_content: materialized_json_string(
@@ -275,7 +202,7 @@ fn materialized_json_string(
275
202
  "tracked_state materialization lost JSON ref index",
276
203
  )
277
204
  })?;
278
- // Each row plan owns its projected JSON slots. If this path starts
205
+ // Each row plan owns its materialized JSON slots. If this path starts
279
206
  // deduplicating refs, duplicate consumers must clone intentionally.
280
207
  let bytes = json_values
281
208
  .get_mut(index)
@@ -305,12 +232,12 @@ fn materialized_json_string(
305
232
  }
306
233
 
307
234
  #[derive(Debug, Clone, Copy, PartialEq, Eq)]
308
- pub(crate) struct TrackedMaterializationProjection {
235
+ pub(crate) struct TrackedRowMaterialization {
309
236
  pub(crate) snapshot_content: bool,
310
237
  pub(crate) metadata: bool,
311
238
  }
312
239
 
313
- impl TrackedMaterializationProjection {
240
+ impl TrackedRowMaterialization {
314
241
  pub(crate) fn full() -> Self {
315
242
  Self {
316
243
  snapshot_content: true,
@@ -333,61 +260,6 @@ impl TrackedMaterializationProjection {
333
260
  mod tests {
334
261
  use super::*;
335
262
 
336
- fn row_plan(commit_id: &str) -> MaterializedTrackedStateRowPlan {
337
- MaterializedTrackedStateRowPlan {
338
- entity_id: EntityIdentity::single("entity"),
339
- schema_key: "schema".to_string(),
340
- file_id: None,
341
- deleted: false,
342
- created_at: "2024-01-01T00:00:00.000Z".to_string(),
343
- updated_at: "2024-01-01T00:00:00.000Z".to_string(),
344
- change_id: "change".to_string(),
345
- commit_id: commit_id.to_string(),
346
- snapshot_ref_index: None,
347
- metadata_ref_index: None,
348
- }
349
- }
350
-
351
- #[test]
352
- fn single_projection_pack_accepts_duplicate_slots_from_same_pack() {
353
- let row_plans = vec![row_plan("commit-a")];
354
- let localities = vec![
355
- JsonRefLocality {
356
- row_index: 0,
357
- pack_id: 7,
358
- },
359
- JsonRefLocality {
360
- row_index: 0,
361
- pack_id: 7,
362
- },
363
- ];
364
-
365
- assert_eq!(
366
- single_projection_pack(&localities, &row_plans).expect("pack detection should succeed"),
367
- Some(("commit-a", 7))
368
- );
369
- }
370
-
371
- #[test]
372
- fn single_projection_pack_rejects_mixed_packs() {
373
- let row_plans = vec![row_plan("commit-a")];
374
- let localities = vec![
375
- JsonRefLocality {
376
- row_index: 0,
377
- pack_id: 7,
378
- },
379
- JsonRefLocality {
380
- row_index: 0,
381
- pack_id: 8,
382
- },
383
- ];
384
-
385
- assert_eq!(
386
- single_projection_pack(&localities, &row_plans).expect("pack detection should succeed"),
387
- None
388
- );
389
- }
390
-
391
263
  #[test]
392
264
  fn materialized_json_string_consumes_owned_payload_bytes() {
393
265
  let json = br#"{"value":1}"#.to_vec();