@lix-js/sdk 0.6.0-preview.1 → 0.6.0-preview.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SKILL.md +305 -320
- package/dist/engine-wasm/wasm/lix_engine.d.ts +5 -0
- package/dist/engine-wasm/wasm/lix_engine.js +9 -13
- package/dist/engine-wasm/wasm/lix_engine.wasm +0 -0
- package/dist/engine-wasm/wasm/lix_engine.wasm.d.ts +1 -0
- package/dist/open-lix.d.ts +103 -14
- package/dist/open-lix.js +3 -0
- package/dist/sqlite/index.js +99 -22
- package/dist-engine-src/README.md +18 -0
- package/dist-engine-src/src/backend/kv.rs +358 -0
- package/dist-engine-src/src/backend/mod.rs +12 -0
- package/dist-engine-src/src/backend/testing.rs +658 -0
- package/dist-engine-src/src/backend/types.rs +96 -0
- package/dist-engine-src/src/binary_cas/chunking.rs +31 -0
- package/dist-engine-src/src/binary_cas/codec.rs +346 -0
- package/dist-engine-src/src/binary_cas/context.rs +139 -0
- package/dist-engine-src/src/binary_cas/kv.rs +1063 -0
- package/dist-engine-src/src/binary_cas/mod.rs +11 -0
- package/dist-engine-src/src/binary_cas/types.rs +127 -0
- package/dist-engine-src/src/cel/context.rs +86 -0
- package/dist-engine-src/src/cel/error.rs +19 -0
- package/dist-engine-src/src/cel/mod.rs +8 -0
- package/dist-engine-src/src/cel/provider.rs +9 -0
- package/dist-engine-src/src/cel/runtime.rs +167 -0
- package/dist-engine-src/src/cel/value.rs +50 -0
- package/dist-engine-src/src/changelog/codec.rs +321 -0
- package/dist-engine-src/src/changelog/context.rs +92 -0
- package/dist-engine-src/src/changelog/materialization.rs +121 -0
- package/dist-engine-src/src/changelog/mod.rs +13 -0
- package/dist-engine-src/src/changelog/reader.rs +20 -0
- package/dist-engine-src/src/changelog/storage.rs +220 -0
- package/dist-engine-src/src/changelog/types.rs +38 -0
- package/dist-engine-src/src/commit_graph/context.rs +1588 -0
- package/dist-engine-src/src/commit_graph/mod.rs +12 -0
- package/dist-engine-src/src/commit_graph/types.rs +145 -0
- package/dist-engine-src/src/commit_graph/walker.rs +780 -0
- package/dist-engine-src/src/common/error.rs +313 -0
- package/dist-engine-src/src/common/fingerprint.rs +3 -0
- package/dist-engine-src/src/common/fs_path.rs +1336 -0
- package/dist-engine-src/src/common/identity.rs +135 -0
- package/dist-engine-src/src/common/metadata.rs +35 -0
- package/dist-engine-src/src/common/mod.rs +23 -0
- package/dist-engine-src/src/common/types.rs +105 -0
- package/dist-engine-src/src/common/wire.rs +222 -0
- package/dist-engine-src/src/engine.rs +239 -0
- package/dist-engine-src/src/entity_identity.rs +285 -0
- package/dist-engine-src/src/functions/context.rs +327 -0
- package/dist-engine-src/src/functions/deterministic.rs +113 -0
- package/dist-engine-src/src/functions/mod.rs +18 -0
- package/dist-engine-src/src/functions/provider.rs +130 -0
- package/dist-engine-src/src/functions/state.rs +363 -0
- package/dist-engine-src/src/functions/types.rs +37 -0
- package/dist-engine-src/src/init.rs +505 -0
- package/dist-engine-src/src/json_store/compression.rs +77 -0
- package/dist-engine-src/src/json_store/context.rs +129 -0
- package/dist-engine-src/src/json_store/encoded.rs +15 -0
- package/dist-engine-src/src/json_store/mod.rs +9 -0
- package/dist-engine-src/src/json_store/store.rs +236 -0
- package/dist-engine-src/src/json_store/types.rs +52 -0
- package/dist-engine-src/src/lib.rs +61 -0
- package/dist-engine-src/src/live_state/context.rs +2241 -0
- package/dist-engine-src/src/live_state/mod.rs +15 -0
- package/dist-engine-src/src/live_state/overlay.rs +75 -0
- package/dist-engine-src/src/live_state/reader.rs +23 -0
- package/dist-engine-src/src/live_state/types.rs +239 -0
- package/dist-engine-src/src/live_state/visibility.rs +218 -0
- package/dist-engine-src/src/plugin/archive.rs +441 -0
- package/dist-engine-src/src/plugin/component.rs +183 -0
- package/dist-engine-src/src/plugin/install.rs +637 -0
- package/dist-engine-src/src/plugin/manifest.rs +516 -0
- package/dist-engine-src/src/plugin/materializer.rs +477 -0
- package/dist-engine-src/src/plugin/mod.rs +33 -0
- package/dist-engine-src/src/plugin/plugin_manifest.json +119 -0
- package/dist-engine-src/src/plugin/storage.rs +74 -0
- package/dist-engine-src/src/schema/annotations/defaults.rs +280 -0
- package/dist-engine-src/src/schema/annotations/mod.rs +1 -0
- package/dist-engine-src/src/schema/builtin/lix_account.json +22 -0
- package/dist-engine-src/src/schema/builtin/lix_active_account.json +30 -0
- package/dist-engine-src/src/schema/builtin/lix_binary_blob_ref.json +30 -0
- package/dist-engine-src/src/schema/builtin/lix_change.json +62 -0
- package/dist-engine-src/src/schema/builtin/lix_change_author.json +46 -0
- package/dist-engine-src/src/schema/builtin/lix_change_set.json +18 -0
- package/dist-engine-src/src/schema/builtin/lix_change_set_element.json +75 -0
- package/dist-engine-src/src/schema/builtin/lix_commit.json +62 -0
- package/dist-engine-src/src/schema/builtin/lix_commit_edge.json +46 -0
- package/dist-engine-src/src/schema/builtin/lix_directory_descriptor.json +53 -0
- package/dist-engine-src/src/schema/builtin/lix_entity_label.json +63 -0
- package/dist-engine-src/src/schema/builtin/lix_file_descriptor.json +53 -0
- package/dist-engine-src/src/schema/builtin/lix_key_value.json +41 -0
- package/dist-engine-src/src/schema/builtin/lix_label.json +22 -0
- package/dist-engine-src/src/schema/builtin/lix_registered_schema.json +31 -0
- package/dist-engine-src/src/schema/builtin/lix_version_descriptor.json +35 -0
- package/dist-engine-src/src/schema/builtin/lix_version_ref.json +49 -0
- package/dist-engine-src/src/schema/builtin/mod.rs +271 -0
- package/dist-engine-src/src/schema/definition.json +157 -0
- package/dist-engine-src/src/schema/definition.rs +636 -0
- package/dist-engine-src/src/schema/key.rs +206 -0
- package/dist-engine-src/src/schema/mod.rs +20 -0
- package/dist-engine-src/src/schema/seed.rs +14 -0
- package/dist-engine-src/src/schema/tests.rs +739 -0
- package/dist-engine-src/src/schema_registry.rs +294 -0
- package/dist-engine-src/src/session/context.rs +366 -0
- package/dist-engine-src/src/session/create_version.rs +80 -0
- package/dist-engine-src/src/session/execute.rs +447 -0
- package/dist-engine-src/src/session/merge/analysis.rs +102 -0
- package/dist-engine-src/src/session/merge/apply.rs +23 -0
- package/dist-engine-src/src/session/merge/conflicts.rs +62 -0
- package/dist-engine-src/src/session/merge/mod.rs +11 -0
- package/dist-engine-src/src/session/merge/stats.rs +65 -0
- package/dist-engine-src/src/session/merge/version.rs +437 -0
- package/dist-engine-src/src/session/mod.rs +25 -0
- package/dist-engine-src/src/session/switch_version.rs +121 -0
- package/dist-engine-src/src/sql2/change_provider.rs +337 -0
- package/dist-engine-src/src/sql2/classify.rs +147 -0
- package/dist-engine-src/src/sql2/commit_derived_provider.rs +591 -0
- package/dist-engine-src/src/sql2/context.rs +307 -0
- package/dist-engine-src/src/sql2/directory_history_provider.rs +623 -0
- package/dist-engine-src/src/sql2/directory_provider.rs +2405 -0
- package/dist-engine-src/src/sql2/dml.rs +148 -0
- package/dist-engine-src/src/sql2/entity_history_provider.rs +444 -0
- package/dist-engine-src/src/sql2/entity_provider.rs +2700 -0
- package/dist-engine-src/src/sql2/error.rs +196 -0
- package/dist-engine-src/src/sql2/execute.rs +3379 -0
- package/dist-engine-src/src/sql2/file_history_provider.rs +902 -0
- package/dist-engine-src/src/sql2/file_provider.rs +3254 -0
- package/dist-engine-src/src/sql2/filesystem_planner.rs +1526 -0
- package/dist-engine-src/src/sql2/filesystem_predicates.rs +159 -0
- package/dist-engine-src/src/sql2/filesystem_visibility.rs +369 -0
- package/dist-engine-src/src/sql2/history_projection.rs +80 -0
- package/dist-engine-src/src/sql2/history_provider.rs +418 -0
- package/dist-engine-src/src/sql2/history_route.rs +643 -0
- package/dist-engine-src/src/sql2/lix_state_provider.rs +2430 -0
- package/dist-engine-src/src/sql2/mod.rs +43 -0
- package/dist-engine-src/src/sql2/read_only.rs +65 -0
- package/dist-engine-src/src/sql2/record_batch.rs +17 -0
- package/dist-engine-src/src/sql2/result_metadata.rs +29 -0
- package/dist-engine-src/src/sql2/runtime.rs +60 -0
- package/dist-engine-src/src/sql2/session.rs +135 -0
- package/dist-engine-src/src/sql2/udfs/common.rs +295 -0
- package/dist-engine-src/src/sql2/udfs/lix_active_version_commit_id.rs +53 -0
- package/dist-engine-src/src/sql2/udfs/lix_empty_blob.rs +47 -0
- package/dist-engine-src/src/sql2/udfs/lix_json.rs +100 -0
- package/dist-engine-src/src/sql2/udfs/lix_json_get.rs +99 -0
- package/dist-engine-src/src/sql2/udfs/lix_json_get_text.rs +99 -0
- package/dist-engine-src/src/sql2/udfs/lix_text_decode.rs +82 -0
- package/dist-engine-src/src/sql2/udfs/lix_text_encode.rs +85 -0
- package/dist-engine-src/src/sql2/udfs/lix_uuid_v7.rs +76 -0
- package/dist-engine-src/src/sql2/udfs/mod.rs +82 -0
- package/dist-engine-src/src/sql2/version_provider.rs +1187 -0
- package/dist-engine-src/src/sql2/version_scope.rs +394 -0
- package/dist-engine-src/src/sql2/write_normalization.rs +345 -0
- package/dist-engine-src/src/storage/context.rs +356 -0
- package/dist-engine-src/src/storage/mod.rs +14 -0
- package/dist-engine-src/src/storage/read_scope.rs +88 -0
- package/dist-engine-src/src/storage/types.rs +501 -0
- package/dist-engine-src/src/storage_bench.rs +3406 -0
- package/dist-engine-src/src/test_support.rs +81 -0
- package/dist-engine-src/src/tracked_state/by_file_index.rs +102 -0
- package/dist-engine-src/src/tracked_state/codec.rs +747 -0
- package/dist-engine-src/src/tracked_state/context.rs +983 -0
- package/dist-engine-src/src/tracked_state/diff.rs +494 -0
- package/dist-engine-src/src/tracked_state/materialization.rs +141 -0
- package/dist-engine-src/src/tracked_state/merge.rs +474 -0
- package/dist-engine-src/src/tracked_state/mod.rs +31 -0
- package/dist-engine-src/src/tracked_state/rebuild.rs +771 -0
- package/dist-engine-src/src/tracked_state/storage.rs +243 -0
- package/dist-engine-src/src/tracked_state/tree.rs +2744 -0
- package/dist-engine-src/src/tracked_state/tree_types.rs +176 -0
- package/dist-engine-src/src/tracked_state/types.rs +61 -0
- package/dist-engine-src/src/transaction/commit.rs +1224 -0
- package/dist-engine-src/src/transaction/context.rs +1307 -0
- package/dist-engine-src/src/transaction/live_state_overlay.rs +34 -0
- package/dist-engine-src/src/transaction/mod.rs +11 -0
- package/dist-engine-src/src/transaction/normalization.rs +1026 -0
- package/dist-engine-src/src/transaction/schema_resolver.rs +127 -0
- package/dist-engine-src/src/transaction/staging.rs +1436 -0
- package/dist-engine-src/src/transaction/types.rs +351 -0
- package/dist-engine-src/src/transaction/validation.rs +4811 -0
- package/dist-engine-src/src/untracked_state/codec.rs +363 -0
- package/dist-engine-src/src/untracked_state/context.rs +82 -0
- package/dist-engine-src/src/untracked_state/materialization.rs +157 -0
- package/dist-engine-src/src/untracked_state/mod.rs +17 -0
- package/dist-engine-src/src/untracked_state/storage.rs +348 -0
- package/dist-engine-src/src/untracked_state/types.rs +96 -0
- package/dist-engine-src/src/version/context.rs +52 -0
- package/dist-engine-src/src/version/mod.rs +12 -0
- package/dist-engine-src/src/version/refs.rs +421 -0
- package/dist-engine-src/src/version/stage_rows.rs +71 -0
- package/dist-engine-src/src/version/types.rs +21 -0
- package/dist-engine-src/src/wasm/mod.rs +60 -0
- package/package.json +68 -64
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
use crate::changelog::codec::{decode_change, encode_change};
|
|
2
|
+
use crate::changelog::{CanonicalChange, ChangelogScanRequest};
|
|
3
|
+
use crate::storage::KvScanRange;
|
|
4
|
+
use crate::storage::{KvGetGroup, KvGetRequest, KvScanRequest, StorageReader, StorageWriteSet};
|
|
5
|
+
use crate::LixError;
|
|
6
|
+
|
|
7
|
+
const CHANGELOG_CHANGE_NAMESPACE: &str = "changelog.change";
|
|
8
|
+
|
|
9
|
+
pub(crate) async fn load_change(
|
|
10
|
+
store: &mut impl StorageReader,
|
|
11
|
+
change_id: &str,
|
|
12
|
+
) -> Result<Option<CanonicalChange>, LixError> {
|
|
13
|
+
let bytes = store
|
|
14
|
+
.get_values(KvGetRequest {
|
|
15
|
+
groups: vec![KvGetGroup {
|
|
16
|
+
namespace: CHANGELOG_CHANGE_NAMESPACE.to_string(),
|
|
17
|
+
keys: vec![encode_change_key(change_id)],
|
|
18
|
+
}],
|
|
19
|
+
})
|
|
20
|
+
.await?
|
|
21
|
+
.groups
|
|
22
|
+
.into_iter()
|
|
23
|
+
.next()
|
|
24
|
+
.and_then(|group| group.single_value_owned());
|
|
25
|
+
let Some(bytes) = bytes else {
|
|
26
|
+
return Ok(None);
|
|
27
|
+
};
|
|
28
|
+
decode_change(&bytes).map(Some)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
pub(crate) async fn scan_changes(
|
|
32
|
+
store: &mut impl StorageReader,
|
|
33
|
+
request: &ChangelogScanRequest,
|
|
34
|
+
) -> Result<Vec<CanonicalChange>, LixError> {
|
|
35
|
+
// TODO(engine2): scan by a durable append sequence instead of change id.
|
|
36
|
+
// This first index is enough for exact lookup and deterministic debug scans.
|
|
37
|
+
let page = store
|
|
38
|
+
.scan_values(KvScanRequest {
|
|
39
|
+
namespace: CHANGELOG_CHANGE_NAMESPACE.to_string(),
|
|
40
|
+
range: KvScanRange::prefix(Vec::new()),
|
|
41
|
+
after: None,
|
|
42
|
+
limit: request.limit.unwrap_or(usize::MAX),
|
|
43
|
+
})
|
|
44
|
+
.await?;
|
|
45
|
+
page.values.iter().map(decode_change).collect()
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
pub(crate) fn stage_changes(
|
|
49
|
+
writes: &mut StorageWriteSet,
|
|
50
|
+
changes: &[CanonicalChange],
|
|
51
|
+
) -> Result<(), LixError> {
|
|
52
|
+
for change in changes {
|
|
53
|
+
writes.put(
|
|
54
|
+
CHANGELOG_CHANGE_NAMESPACE,
|
|
55
|
+
encode_change_key(&change.id),
|
|
56
|
+
encode_change(change)?,
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
Ok(())
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
fn encode_change_key(change_id: &str) -> Vec<u8> {
|
|
63
|
+
change_id.as_bytes().to_vec()
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
#[cfg(test)]
|
|
67
|
+
mod tests {
|
|
68
|
+
use std::sync::Arc;
|
|
69
|
+
|
|
70
|
+
use crate::backend::testing::UnitTestBackend;
|
|
71
|
+
use crate::changelog::{
|
|
72
|
+
canonicalize_materialized_change, materialize_change, ChangelogContext,
|
|
73
|
+
ChangelogScanRequest, MaterializedCanonicalChange,
|
|
74
|
+
};
|
|
75
|
+
use crate::json_store::JsonStoreContext;
|
|
76
|
+
use crate::storage::{StorageContext, StorageWriteSet, StorageWriteTransaction};
|
|
77
|
+
|
|
78
|
+
use super::*;
|
|
79
|
+
|
|
80
|
+
#[tokio::test]
|
|
81
|
+
async fn append_and_load_change_roundtrips() {
|
|
82
|
+
let storage = StorageContext::new(Arc::new(UnitTestBackend::new()));
|
|
83
|
+
let changelog = ChangelogContext::new();
|
|
84
|
+
let change = test_change("change-1");
|
|
85
|
+
|
|
86
|
+
let mut tx = storage
|
|
87
|
+
.begin_write_transaction()
|
|
88
|
+
.await
|
|
89
|
+
.expect("transaction should open");
|
|
90
|
+
append_test_changes(&changelog, &mut tx, std::slice::from_ref(&change)).await;
|
|
91
|
+
tx.commit().await.expect("commit should succeed");
|
|
92
|
+
|
|
93
|
+
let loaded = load_test_change(&changelog, storage, "change-1").await;
|
|
94
|
+
assert_eq!(loaded, Some(change));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
#[tokio::test]
|
|
98
|
+
async fn append_and_load_composite_entity_identity_roundtrips() {
|
|
99
|
+
let storage = StorageContext::new(Arc::new(UnitTestBackend::new()));
|
|
100
|
+
let changelog = ChangelogContext::new();
|
|
101
|
+
let mut change = test_change("change-composite");
|
|
102
|
+
change.entity_id = crate::entity_identity::EntityIdentity::tuple(vec![
|
|
103
|
+
crate::entity_identity::EntityIdentityPart::String("entity".to_string()),
|
|
104
|
+
crate::entity_identity::EntityIdentityPart::Number("7".to_string()),
|
|
105
|
+
crate::entity_identity::EntityIdentityPart::Bool(true),
|
|
106
|
+
])
|
|
107
|
+
.expect("composite identity should be valid");
|
|
108
|
+
|
|
109
|
+
let mut tx = storage
|
|
110
|
+
.begin_write_transaction()
|
|
111
|
+
.await
|
|
112
|
+
.expect("transaction should open");
|
|
113
|
+
append_test_changes(&changelog, &mut tx, std::slice::from_ref(&change)).await;
|
|
114
|
+
tx.commit().await.expect("commit should succeed");
|
|
115
|
+
|
|
116
|
+
let loaded = load_test_change(&changelog, storage, "change-composite").await;
|
|
117
|
+
assert_eq!(loaded, Some(change));
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
#[test]
|
|
121
|
+
fn decode_rejects_non_flatbuffer_bytes() {
|
|
122
|
+
let error = decode_change(br#"{"id":"change-json"}"#)
|
|
123
|
+
.expect_err("json changelog payloads are not accepted after the hard cut");
|
|
124
|
+
assert!(
|
|
125
|
+
error
|
|
126
|
+
.message
|
|
127
|
+
.contains("invalid FlatBuffers file identifier"),
|
|
128
|
+
"unexpected error: {error:?}"
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
#[tokio::test]
|
|
133
|
+
async fn scan_changes_respects_limit() {
|
|
134
|
+
let storage = StorageContext::new(Arc::new(UnitTestBackend::new()));
|
|
135
|
+
let changelog = ChangelogContext::new();
|
|
136
|
+
let mut tx = storage
|
|
137
|
+
.begin_write_transaction()
|
|
138
|
+
.await
|
|
139
|
+
.expect("transaction should open");
|
|
140
|
+
append_test_changes(
|
|
141
|
+
&changelog,
|
|
142
|
+
&mut tx,
|
|
143
|
+
&[test_change("change-1"), test_change("change-2")],
|
|
144
|
+
)
|
|
145
|
+
.await;
|
|
146
|
+
tx.commit().await.expect("commit should succeed");
|
|
147
|
+
|
|
148
|
+
let canonical_changes = {
|
|
149
|
+
let reader = changelog.reader(storage.clone());
|
|
150
|
+
reader
|
|
151
|
+
.scan_changes(&ChangelogScanRequest { limit: Some(1) })
|
|
152
|
+
.await
|
|
153
|
+
}
|
|
154
|
+
.expect("scan should succeed");
|
|
155
|
+
let mut json_reader = JsonStoreContext::new().reader(storage);
|
|
156
|
+
let mut changes = Vec::new();
|
|
157
|
+
for change in canonical_changes {
|
|
158
|
+
changes.push(
|
|
159
|
+
materialize_change(&mut json_reader, change)
|
|
160
|
+
.await
|
|
161
|
+
.expect("change should materialize"),
|
|
162
|
+
);
|
|
163
|
+
}
|
|
164
|
+
assert_eq!(changes, vec![test_change("change-1")]);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
fn test_change(id: &str) -> MaterializedCanonicalChange {
|
|
168
|
+
MaterializedCanonicalChange {
|
|
169
|
+
id: id.to_string(),
|
|
170
|
+
entity_id: crate::entity_identity::EntityIdentity::single("entity-1"),
|
|
171
|
+
schema_key: "test_schema".to_string(),
|
|
172
|
+
schema_version: "1".to_string(),
|
|
173
|
+
file_id: None,
|
|
174
|
+
snapshot_content: Some("{\"value\":1}".to_string()),
|
|
175
|
+
metadata: None,
|
|
176
|
+
created_at: "2026-01-01T00:00:00Z".to_string(),
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
async fn append_test_changes(
|
|
181
|
+
changelog: &ChangelogContext,
|
|
182
|
+
tx: &mut Box<dyn StorageWriteTransaction + Send + Sync + 'static>,
|
|
183
|
+
changes: &[MaterializedCanonicalChange],
|
|
184
|
+
) {
|
|
185
|
+
let mut writes = StorageWriteSet::new();
|
|
186
|
+
let mut json_writer = JsonStoreContext::new().writer();
|
|
187
|
+
let canonical_changes = changes
|
|
188
|
+
.iter()
|
|
189
|
+
.map(|change| canonicalize_materialized_change(&mut writes, &mut json_writer, change))
|
|
190
|
+
.collect::<Result<Vec<_>, _>>()
|
|
191
|
+
.expect("changes should canonicalize");
|
|
192
|
+
let mut writer = changelog.writer(&mut writes);
|
|
193
|
+
writer
|
|
194
|
+
.stage_changes(&canonical_changes)
|
|
195
|
+
.expect("append should succeed");
|
|
196
|
+
writes
|
|
197
|
+
.apply(&mut tx.as_mut())
|
|
198
|
+
.await
|
|
199
|
+
.expect("writes should apply");
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
async fn load_test_change(
|
|
203
|
+
changelog: &ChangelogContext,
|
|
204
|
+
storage: StorageContext,
|
|
205
|
+
change_id: &str,
|
|
206
|
+
) -> Option<MaterializedCanonicalChange> {
|
|
207
|
+
let canonical = {
|
|
208
|
+
let reader = changelog.reader(storage.clone());
|
|
209
|
+
reader
|
|
210
|
+
.load_change(change_id)
|
|
211
|
+
.await
|
|
212
|
+
.expect("load should succeed")
|
|
213
|
+
}?;
|
|
214
|
+
let mut json_reader = JsonStoreContext::new().reader(storage);
|
|
215
|
+
materialize_change(&mut json_reader, canonical)
|
|
216
|
+
.await
|
|
217
|
+
.map(Some)
|
|
218
|
+
.expect("change should materialize")
|
|
219
|
+
}
|
|
220
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
use crate::entity_identity::EntityIdentity;
|
|
2
|
+
use crate::json_store::JsonRef;
|
|
3
|
+
use crate::RowMetadata;
|
|
4
|
+
|
|
5
|
+
/// Immutable canonical change fact stored in the changelog.
|
|
6
|
+
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
|
7
|
+
pub(crate) struct CanonicalChange {
|
|
8
|
+
pub(crate) id: String,
|
|
9
|
+
pub(crate) entity_id: EntityIdentity,
|
|
10
|
+
pub(crate) schema_key: String,
|
|
11
|
+
pub(crate) schema_version: String,
|
|
12
|
+
pub(crate) file_id: Option<String>,
|
|
13
|
+
pub(crate) snapshot_ref: Option<JsonRef>,
|
|
14
|
+
pub(crate) metadata_ref: Option<JsonRef>,
|
|
15
|
+
pub(crate) created_at: String,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/// Boundary shape for callers that still work with materialized JSON payloads.
|
|
19
|
+
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
|
20
|
+
pub(crate) struct MaterializedCanonicalChange {
|
|
21
|
+
pub(crate) id: String,
|
|
22
|
+
pub(crate) entity_id: EntityIdentity,
|
|
23
|
+
pub(crate) schema_key: String,
|
|
24
|
+
pub(crate) schema_version: String,
|
|
25
|
+
pub(crate) file_id: Option<String>,
|
|
26
|
+
pub(crate) snapshot_content: Option<String>,
|
|
27
|
+
pub(crate) metadata: Option<RowMetadata>,
|
|
28
|
+
pub(crate) created_at: String,
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/// Minimal changelog scan request.
|
|
32
|
+
///
|
|
33
|
+
/// TODO(engine2): add filters and append-order cursors once changelog storage
|
|
34
|
+
/// has real append sequence keys.
|
|
35
|
+
#[derive(Debug, Clone, Default, PartialEq, Eq)]
|
|
36
|
+
pub(crate) struct ChangelogScanRequest {
|
|
37
|
+
pub(crate) limit: Option<usize>,
|
|
38
|
+
}
|