@lix-js/sdk 0.6.0-preview.1 → 0.6.0-preview.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.
- package/SKILL.md +304 -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/generated/builtin-schemas.d.ts +87 -162
- package/dist/generated/builtin-schemas.js +139 -236
- 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 +121 -0
- package/dist-engine-src/src/catalog/context.rs +412 -0
- package/dist-engine-src/src/catalog/mod.rs +10 -0
- package/dist-engine-src/src/catalog/schema.rs +4 -0
- package/dist-engine-src/src/catalog/snapshot.rs +1114 -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/commit_graph/context.rs +901 -0
- package/dist-engine-src/src/commit_graph/mod.rs +11 -0
- package/dist-engine-src/src/commit_graph/types.rs +109 -0
- package/dist-engine-src/src/commit_graph/walker.rs +756 -0
- package/dist-engine-src/src/commit_store/codec.rs +887 -0
- package/dist-engine-src/src/commit_store/context.rs +944 -0
- package/dist-engine-src/src/commit_store/materialization.rs +84 -0
- package/dist-engine-src/src/commit_store/mod.rs +16 -0
- package/dist-engine-src/src/commit_store/storage.rs +600 -0
- package/dist-engine-src/src/commit_store/types.rs +215 -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 +145 -0
- package/dist-engine-src/src/common/json_pointer.rs +67 -0
- package/dist-engine-src/src/common/metadata.rs +40 -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/domain.rs +324 -0
- package/dist-engine-src/src/engine.rs +225 -0
- package/dist-engine-src/src/entity_identity.rs +405 -0
- package/dist-engine-src/src/functions/context.rs +292 -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 +336 -0
- package/dist-engine-src/src/functions/types.rs +37 -0
- package/dist-engine-src/src/init.rs +558 -0
- package/dist-engine-src/src/json_store/compression.rs +77 -0
- package/dist-engine-src/src/json_store/context.rs +423 -0
- package/dist-engine-src/src/json_store/encoded.rs +15 -0
- package/dist-engine-src/src/json_store/mod.rs +12 -0
- package/dist-engine-src/src/json_store/store.rs +1109 -0
- package/dist-engine-src/src/json_store/types.rs +217 -0
- package/dist-engine-src/src/lib.rs +62 -0
- package/dist-engine-src/src/live_state/context.rs +2019 -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 +222 -0
- package/dist-engine-src/src/live_state/visibility.rs +223 -0
- package/dist-engine-src/src/plugin/archive.rs +438 -0
- package/dist-engine-src/src/plugin/component.rs +183 -0
- package/dist-engine-src/src/plugin/install.rs +619 -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 +118 -0
- package/dist-engine-src/src/plugin/storage.rs +74 -0
- package/dist-engine-src/src/schema/annotations/defaults.rs +275 -0
- package/dist-engine-src/src/schema/annotations/mod.rs +1 -0
- package/dist-engine-src/src/schema/builtin/lix_account.json +21 -0
- package/dist-engine-src/src/schema/builtin/lix_active_account.json +29 -0
- package/dist-engine-src/src/schema/builtin/lix_binary_blob_ref.json +29 -0
- package/dist-engine-src/src/schema/builtin/lix_change.json +63 -0
- package/dist-engine-src/src/schema/builtin/lix_change_author.json +45 -0
- package/dist-engine-src/src/schema/builtin/lix_commit.json +24 -0
- package/dist-engine-src/src/schema/builtin/lix_commit_edge.json +53 -0
- package/dist-engine-src/src/schema/builtin/lix_directory_descriptor.json +52 -0
- package/dist-engine-src/src/schema/builtin/lix_file_descriptor.json +52 -0
- package/dist-engine-src/src/schema/builtin/lix_key_value.json +40 -0
- package/dist-engine-src/src/schema/builtin/lix_label.json +29 -0
- package/dist-engine-src/src/schema/builtin/lix_label_assignment.json +74 -0
- package/dist-engine-src/src/schema/builtin/lix_registered_schema.json +25 -0
- package/dist-engine-src/src/schema/builtin/lix_version_descriptor.json +34 -0
- package/dist-engine-src/src/schema/builtin/lix_version_ref.json +48 -0
- package/dist-engine-src/src/schema/builtin/mod.rs +222 -0
- package/dist-engine-src/src/schema/compatibility.rs +787 -0
- package/dist-engine-src/src/schema/definition.json +187 -0
- package/dist-engine-src/src/schema/definition.rs +742 -0
- package/dist-engine-src/src/schema/key.rs +138 -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 +780 -0
- package/dist-engine-src/src/session/context.rs +364 -0
- package/dist-engine-src/src/session/create_version.rs +88 -0
- package/dist-engine-src/src/session/execute.rs +478 -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 +63 -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 +427 -0
- package/dist-engine-src/src/session/mod.rs +27 -0
- package/dist-engine-src/src/session/optimization9_sql2_bench.rs +100 -0
- package/dist-engine-src/src/session/switch_version.rs +109 -0
- package/dist-engine-src/src/sql2/change_provider.rs +331 -0
- package/dist-engine-src/src/sql2/classify.rs +182 -0
- package/dist-engine-src/src/sql2/context.rs +311 -0
- package/dist-engine-src/src/sql2/directory_history_provider.rs +631 -0
- package/dist-engine-src/src/sql2/directory_provider.rs +2453 -0
- package/dist-engine-src/src/sql2/dml.rs +148 -0
- package/dist-engine-src/src/sql2/entity_history_provider.rs +440 -0
- package/dist-engine-src/src/sql2/entity_provider.rs +3211 -0
- package/dist-engine-src/src/sql2/error.rs +216 -0
- package/dist-engine-src/src/sql2/execute.rs +3440 -0
- package/dist-engine-src/src/sql2/file_history_provider.rs +910 -0
- package/dist-engine-src/src/sql2/file_provider.rs +3679 -0
- package/dist-engine-src/src/sql2/filesystem_planner.rs +1490 -0
- package/dist-engine-src/src/sql2/filesystem_predicates.rs +159 -0
- package/dist-engine-src/src/sql2/filesystem_visibility.rs +383 -0
- package/dist-engine-src/src/sql2/history_projection.rs +56 -0
- package/dist-engine-src/src/sql2/history_provider.rs +412 -0
- package/dist-engine-src/src/sql2/history_route.rs +657 -0
- package/dist-engine-src/src/sql2/lix_state_provider.rs +2512 -0
- package/dist-engine-src/src/sql2/mod.rs +46 -0
- package/dist-engine-src/src/sql2/predicate_typecheck.rs +246 -0
- package/dist-engine-src/src/sql2/public_bind/assignment.rs +46 -0
- package/dist-engine-src/src/sql2/public_bind/capability.rs +41 -0
- package/dist-engine-src/src/sql2/public_bind/dml.rs +166 -0
- package/dist-engine-src/src/sql2/public_bind/mod.rs +25 -0
- package/dist-engine-src/src/sql2/public_bind/table.rs +168 -0
- package/dist-engine-src/src/sql2/read_only.rs +63 -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 +132 -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_timestamp.rs +76 -0
- package/dist-engine-src/src/sql2/udfs/lix_uuid_v7.rs +76 -0
- package/dist-engine-src/src/sql2/udfs/mod.rs +89 -0
- package/dist-engine-src/src/sql2/udfs/public_call.rs +211 -0
- package/dist-engine-src/src/sql2/version_provider.rs +1202 -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 +4863 -0
- package/dist-engine-src/src/test_support.rs +228 -0
- package/dist-engine-src/src/tracked_state/by_file_index.rs +98 -0
- package/dist-engine-src/src/tracked_state/codec.rs +2085 -0
- package/dist-engine-src/src/tracked_state/context.rs +1867 -0
- package/dist-engine-src/src/tracked_state/diff.rs +686 -0
- package/dist-engine-src/src/tracked_state/materialization.rs +403 -0
- package/dist-engine-src/src/tracked_state/materializer.rs +488 -0
- package/dist-engine-src/src/tracked_state/merge.rs +492 -0
- package/dist-engine-src/src/tracked_state/mod.rs +32 -0
- package/dist-engine-src/src/tracked_state/storage.rs +375 -0
- package/dist-engine-src/src/tracked_state/tree.rs +3187 -0
- package/dist-engine-src/src/tracked_state/types.rs +231 -0
- package/dist-engine-src/src/transaction/commit.rs +1484 -0
- package/dist-engine-src/src/transaction/context.rs +1548 -0
- package/dist-engine-src/src/transaction/live_state_overlay.rs +35 -0
- package/dist-engine-src/src/transaction/mod.rs +13 -0
- package/dist-engine-src/src/transaction/normalization.rs +890 -0
- package/dist-engine-src/src/transaction/prep.rs +37 -0
- package/dist-engine-src/src/transaction/schema_resolver.rs +149 -0
- package/dist-engine-src/src/transaction/staging.rs +1731 -0
- package/dist-engine-src/src/transaction/types.rs +460 -0
- package/dist-engine-src/src/transaction/validation.rs +5830 -0
- package/dist-engine-src/src/untracked_state/codec.rs +307 -0
- package/dist-engine-src/src/untracked_state/context.rs +98 -0
- package/dist-engine-src/src/untracked_state/materialization.rs +63 -0
- package/dist-engine-src/src/untracked_state/mod.rs +15 -0
- package/dist-engine-src/src/untracked_state/storage.rs +396 -0
- package/dist-engine-src/src/untracked_state/types.rs +146 -0
- package/dist-engine-src/src/version/context.rs +40 -0
- package/dist-engine-src/src/version/lifecycle.rs +221 -0
- package/dist-engine-src/src/version/mod.rs +13 -0
- package/dist-engine-src/src/version/refs.rs +330 -0
- package/dist-engine-src/src/version/stage_rows.rs +67 -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,364 @@
|
|
|
1
|
+
use std::future::Future;
|
|
2
|
+
use std::pin::Pin;
|
|
3
|
+
use std::sync::atomic::{AtomicBool, Ordering};
|
|
4
|
+
use std::sync::Arc;
|
|
5
|
+
|
|
6
|
+
use serde_json::Value as JsonValue;
|
|
7
|
+
|
|
8
|
+
use crate::binary_cas::{BinaryCasContext, BlobDataReader};
|
|
9
|
+
use crate::catalog::CatalogContext;
|
|
10
|
+
use crate::commit_graph::{CommitGraphContext, CommitGraphReader};
|
|
11
|
+
use crate::commit_store::CommitStoreContext;
|
|
12
|
+
use crate::entity_identity::EntityIdentity;
|
|
13
|
+
use crate::functions::FunctionProviderHandle;
|
|
14
|
+
use crate::json_store::JsonStoreContext;
|
|
15
|
+
use crate::live_state::{LiveStateContext, LiveStateReader, LiveStateRowRequest};
|
|
16
|
+
use crate::sql2::{CommitStoreQuerySource, SqlCommitStoreQuerySource, SqlExecutionContext};
|
|
17
|
+
use crate::storage::{
|
|
18
|
+
ScopedStorageReader, StorageContext, StorageReadScope, StorageReadTransaction, StorageReader,
|
|
19
|
+
};
|
|
20
|
+
use crate::tracked_state::TrackedStateContext;
|
|
21
|
+
use crate::transaction::{open_transaction, Transaction};
|
|
22
|
+
use crate::version::{
|
|
23
|
+
VersionContext, VersionLifecycle, VersionOperation, VersionRefReader, VersionReferenceRole,
|
|
24
|
+
};
|
|
25
|
+
use crate::GLOBAL_VERSION_ID;
|
|
26
|
+
use crate::{LixError, NullableKeyFilter};
|
|
27
|
+
|
|
28
|
+
pub(crate) const WORKSPACE_VERSION_KEY: &str = "lix_workspace_version_id";
|
|
29
|
+
|
|
30
|
+
#[derive(Clone)]
|
|
31
|
+
pub(crate) enum SessionMode {
|
|
32
|
+
Pinned { version_id: String },
|
|
33
|
+
Workspace,
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/// Session-context state for engine execution.
|
|
37
|
+
///
|
|
38
|
+
/// A session context pins the active version selector and shared execution
|
|
39
|
+
/// services. Each call to `execute(...)` projects this state into a read-only
|
|
40
|
+
/// SQL context or a transaction-owned write context.
|
|
41
|
+
///
|
|
42
|
+
/// Write transaction invariant: any engine operation that may write must enter
|
|
43
|
+
/// through `SessionContext::with_write_transaction`. Reads that influence writes
|
|
44
|
+
/// are only available from that transaction capability, not from session-level
|
|
45
|
+
/// helpers.
|
|
46
|
+
#[derive(Clone)]
|
|
47
|
+
pub struct SessionContext {
|
|
48
|
+
pub(super) mode: SessionMode,
|
|
49
|
+
pub(super) storage: StorageContext,
|
|
50
|
+
pub(super) live_state: Arc<LiveStateContext>,
|
|
51
|
+
pub(super) tracked_state: Arc<TrackedStateContext>,
|
|
52
|
+
pub(super) binary_cas: Arc<BinaryCasContext>,
|
|
53
|
+
pub(super) commit_store: Arc<CommitStoreContext>,
|
|
54
|
+
pub(super) version_ctx: Arc<VersionContext>,
|
|
55
|
+
pub(super) catalog_context: Arc<CatalogContext>,
|
|
56
|
+
closed: Arc<AtomicBool>,
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
impl SessionContext {
|
|
60
|
+
pub(crate) async fn open_workspace(
|
|
61
|
+
storage: StorageContext,
|
|
62
|
+
live_state: Arc<LiveStateContext>,
|
|
63
|
+
tracked_state: Arc<TrackedStateContext>,
|
|
64
|
+
binary_cas: Arc<BinaryCasContext>,
|
|
65
|
+
commit_store: Arc<CommitStoreContext>,
|
|
66
|
+
version_ctx: Arc<VersionContext>,
|
|
67
|
+
catalog_context: Arc<CatalogContext>,
|
|
68
|
+
) -> Result<Self, LixError> {
|
|
69
|
+
let session = Self::new(
|
|
70
|
+
SessionMode::Workspace,
|
|
71
|
+
storage,
|
|
72
|
+
live_state,
|
|
73
|
+
tracked_state,
|
|
74
|
+
binary_cas,
|
|
75
|
+
commit_store,
|
|
76
|
+
version_ctx,
|
|
77
|
+
catalog_context,
|
|
78
|
+
);
|
|
79
|
+
session.active_version_id().await?;
|
|
80
|
+
Ok(session)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
pub(crate) async fn open(
|
|
84
|
+
active_version_id: String,
|
|
85
|
+
storage: StorageContext,
|
|
86
|
+
live_state: Arc<LiveStateContext>,
|
|
87
|
+
tracked_state: Arc<TrackedStateContext>,
|
|
88
|
+
binary_cas: Arc<BinaryCasContext>,
|
|
89
|
+
commit_store: Arc<CommitStoreContext>,
|
|
90
|
+
version_ctx: Arc<VersionContext>,
|
|
91
|
+
catalog_context: Arc<CatalogContext>,
|
|
92
|
+
) -> Result<Self, LixError> {
|
|
93
|
+
Ok(Self::new(
|
|
94
|
+
SessionMode::Pinned {
|
|
95
|
+
version_id: active_version_id,
|
|
96
|
+
},
|
|
97
|
+
storage,
|
|
98
|
+
live_state,
|
|
99
|
+
tracked_state,
|
|
100
|
+
binary_cas,
|
|
101
|
+
commit_store,
|
|
102
|
+
version_ctx,
|
|
103
|
+
catalog_context,
|
|
104
|
+
))
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
pub(super) fn new(
|
|
108
|
+
mode: SessionMode,
|
|
109
|
+
storage: StorageContext,
|
|
110
|
+
live_state: Arc<LiveStateContext>,
|
|
111
|
+
tracked_state: Arc<TrackedStateContext>,
|
|
112
|
+
binary_cas: Arc<BinaryCasContext>,
|
|
113
|
+
commit_store: Arc<CommitStoreContext>,
|
|
114
|
+
version_ctx: Arc<VersionContext>,
|
|
115
|
+
catalog_context: Arc<CatalogContext>,
|
|
116
|
+
) -> Self {
|
|
117
|
+
Self::new_with_closed(
|
|
118
|
+
mode,
|
|
119
|
+
storage,
|
|
120
|
+
live_state,
|
|
121
|
+
tracked_state,
|
|
122
|
+
binary_cas,
|
|
123
|
+
commit_store,
|
|
124
|
+
version_ctx,
|
|
125
|
+
catalog_context,
|
|
126
|
+
Arc::new(AtomicBool::new(false)),
|
|
127
|
+
)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
pub(super) fn new_with_closed(
|
|
131
|
+
mode: SessionMode,
|
|
132
|
+
storage: StorageContext,
|
|
133
|
+
live_state: Arc<LiveStateContext>,
|
|
134
|
+
tracked_state: Arc<TrackedStateContext>,
|
|
135
|
+
binary_cas: Arc<BinaryCasContext>,
|
|
136
|
+
commit_store: Arc<CommitStoreContext>,
|
|
137
|
+
version_ctx: Arc<VersionContext>,
|
|
138
|
+
catalog_context: Arc<CatalogContext>,
|
|
139
|
+
closed: Arc<AtomicBool>,
|
|
140
|
+
) -> Self {
|
|
141
|
+
Self {
|
|
142
|
+
mode,
|
|
143
|
+
storage,
|
|
144
|
+
live_state,
|
|
145
|
+
tracked_state,
|
|
146
|
+
binary_cas,
|
|
147
|
+
commit_store,
|
|
148
|
+
version_ctx,
|
|
149
|
+
catalog_context,
|
|
150
|
+
closed,
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/// Releases this logical session handle. This is a lifecycle boundary only:
|
|
155
|
+
/// successful writes are committed before their operation returns.
|
|
156
|
+
pub async fn close(&self) -> Result<(), LixError> {
|
|
157
|
+
self.closed.store(true, Ordering::SeqCst);
|
|
158
|
+
Ok(())
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
pub fn is_closed(&self) -> bool {
|
|
162
|
+
self.closed.load(Ordering::SeqCst)
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
pub(crate) fn closed_flag(&self) -> Arc<AtomicBool> {
|
|
166
|
+
Arc::clone(&self.closed)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
pub(crate) fn ensure_open(&self) -> Result<(), LixError> {
|
|
170
|
+
if self.is_closed() {
|
|
171
|
+
return Err(closed_error());
|
|
172
|
+
}
|
|
173
|
+
Ok(())
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/// Resolves the version this session should operate on right now.
|
|
177
|
+
///
|
|
178
|
+
/// This is a read-path helper. Write flows must resolve the active version
|
|
179
|
+
/// through the transaction capability so the read is scoped to the
|
|
180
|
+
/// same backend transaction as the writes it influences.
|
|
181
|
+
///
|
|
182
|
+
/// Pinned sessions are pure in-memory views over one version. Workspace
|
|
183
|
+
/// sessions read the shared workspace selector from untracked global
|
|
184
|
+
/// `lix_key_value` state so multiple open app sessions can observe the same
|
|
185
|
+
/// active workspace version.
|
|
186
|
+
pub async fn active_version_id(&self) -> Result<String, LixError> {
|
|
187
|
+
let mut transaction = self.storage.begin_read_transaction().await?;
|
|
188
|
+
let result = self
|
|
189
|
+
.active_version_id_from_reader(transaction.as_mut())
|
|
190
|
+
.await;
|
|
191
|
+
match result {
|
|
192
|
+
Ok(version_id) => {
|
|
193
|
+
transaction.rollback().await?;
|
|
194
|
+
Ok(version_id)
|
|
195
|
+
}
|
|
196
|
+
Err(error) => {
|
|
197
|
+
let _ = transaction.rollback().await;
|
|
198
|
+
Err(error)
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
pub(super) async fn active_version_id_from_reader<S>(
|
|
204
|
+
&self,
|
|
205
|
+
reader: &mut S,
|
|
206
|
+
) -> Result<String, LixError>
|
|
207
|
+
where
|
|
208
|
+
S: StorageReader + ?Sized,
|
|
209
|
+
{
|
|
210
|
+
self.ensure_open()?;
|
|
211
|
+
match &self.mode {
|
|
212
|
+
SessionMode::Pinned { version_id } => Ok(version_id.clone()),
|
|
213
|
+
SessionMode::Workspace => self.load_workspace_version_id(reader).await,
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
async fn load_workspace_version_id<S>(&self, reader: &mut S) -> Result<String, LixError>
|
|
218
|
+
where
|
|
219
|
+
S: StorageReader + ?Sized,
|
|
220
|
+
{
|
|
221
|
+
let row = self
|
|
222
|
+
.live_state
|
|
223
|
+
.reader(&mut *reader)
|
|
224
|
+
.load_row(&LiveStateRowRequest {
|
|
225
|
+
schema_key: "lix_key_value".to_string(),
|
|
226
|
+
version_id: GLOBAL_VERSION_ID.to_string(),
|
|
227
|
+
entity_id: EntityIdentity::single(WORKSPACE_VERSION_KEY),
|
|
228
|
+
file_id: NullableKeyFilter::Null,
|
|
229
|
+
})
|
|
230
|
+
.await?
|
|
231
|
+
.ok_or_else(|| {
|
|
232
|
+
LixError::new(
|
|
233
|
+
"LIX_ERROR_UNKNOWN",
|
|
234
|
+
"workspace version selector is missing lix_key_value:lix_workspace_version_id",
|
|
235
|
+
)
|
|
236
|
+
})?;
|
|
237
|
+
let snapshot_content = row.snapshot_content.as_deref().ok_or_else(|| {
|
|
238
|
+
LixError::new(
|
|
239
|
+
"LIX_ERROR_UNKNOWN",
|
|
240
|
+
"workspace version selector is missing snapshot_content",
|
|
241
|
+
)
|
|
242
|
+
})?;
|
|
243
|
+
let snapshot = serde_json::from_str::<JsonValue>(snapshot_content).map_err(|error| {
|
|
244
|
+
LixError::new(
|
|
245
|
+
"LIX_ERROR_UNKNOWN",
|
|
246
|
+
format!("workspace version selector snapshot is invalid JSON: {error}"),
|
|
247
|
+
)
|
|
248
|
+
})?;
|
|
249
|
+
let version_id = snapshot
|
|
250
|
+
.get("value")
|
|
251
|
+
.and_then(JsonValue::as_str)
|
|
252
|
+
.filter(|value| !value.is_empty())
|
|
253
|
+
.ok_or_else(|| {
|
|
254
|
+
LixError::new(
|
|
255
|
+
"LIX_ERROR_UNKNOWN",
|
|
256
|
+
"workspace version selector value must be a non-empty string",
|
|
257
|
+
)
|
|
258
|
+
})?
|
|
259
|
+
.to_string();
|
|
260
|
+
|
|
261
|
+
let version_ref = self.version_ctx.ref_reader(&mut *reader);
|
|
262
|
+
VersionLifecycle::new(&version_ref)
|
|
263
|
+
.require_existing_ref(
|
|
264
|
+
&version_id,
|
|
265
|
+
VersionOperation::LoadWorkspaceSelector,
|
|
266
|
+
VersionReferenceRole::WorkspaceSelector,
|
|
267
|
+
)
|
|
268
|
+
.await?;
|
|
269
|
+
|
|
270
|
+
Ok(version_id)
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
pub(crate) async fn with_write_transaction<T, F>(&self, f: F) -> Result<T, LixError>
|
|
274
|
+
where
|
|
275
|
+
F: for<'tx> FnOnce(
|
|
276
|
+
&'tx mut Transaction,
|
|
277
|
+
) -> Pin<Box<dyn Future<Output = Result<T, LixError>> + 'tx>>,
|
|
278
|
+
{
|
|
279
|
+
self.ensure_open()?;
|
|
280
|
+
let opened = open_transaction(
|
|
281
|
+
&self.mode,
|
|
282
|
+
self.storage.clone(),
|
|
283
|
+
Arc::clone(&self.live_state),
|
|
284
|
+
Arc::clone(&self.tracked_state),
|
|
285
|
+
Arc::clone(&self.binary_cas),
|
|
286
|
+
Arc::clone(&self.commit_store),
|
|
287
|
+
Arc::clone(&self.version_ctx),
|
|
288
|
+
Arc::clone(&self.catalog_context),
|
|
289
|
+
)
|
|
290
|
+
.await?;
|
|
291
|
+
let mut transaction = opened.transaction;
|
|
292
|
+
let runtime_functions = opened.runtime_functions;
|
|
293
|
+
|
|
294
|
+
match f(&mut transaction).await {
|
|
295
|
+
Ok(value) => {
|
|
296
|
+
transaction.commit(&runtime_functions).await?;
|
|
297
|
+
Ok(value)
|
|
298
|
+
}
|
|
299
|
+
Err(error) => {
|
|
300
|
+
let _ = transaction.rollback().await;
|
|
301
|
+
Err(error)
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
fn closed_error() -> LixError {
|
|
308
|
+
LixError::new(LixError::CODE_CLOSED, "Lix handle is closed")
|
|
309
|
+
.with_hint("Open a new Lix handle before calling this method.")
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/// Read-only SQL execution context derived from a session.
|
|
313
|
+
///
|
|
314
|
+
/// Write statements re-plan against `Transaction`; this context intentionally
|
|
315
|
+
/// has no write stager.
|
|
316
|
+
pub(super) struct SessionSqlExecutionContext<'a> {
|
|
317
|
+
pub(super) active_version_id: &'a str,
|
|
318
|
+
pub(super) read_store:
|
|
319
|
+
ScopedStorageReader<Box<dyn StorageReadTransaction + Send + Sync + 'static>>,
|
|
320
|
+
pub(super) live_state: Arc<LiveStateContext>,
|
|
321
|
+
pub(super) binary_cas: Arc<BinaryCasContext>,
|
|
322
|
+
pub(super) commit_store: Arc<CommitStoreContext>,
|
|
323
|
+
pub(super) version_ctx: Arc<VersionContext>,
|
|
324
|
+
pub(super) visible_schemas: Vec<JsonValue>,
|
|
325
|
+
pub(super) functions: FunctionProviderHandle,
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
impl SqlExecutionContext for SessionSqlExecutionContext<'_> {
|
|
329
|
+
fn active_version_id(&self) -> &str {
|
|
330
|
+
self.active_version_id
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
fn live_state(&self) -> Arc<dyn LiveStateReader> {
|
|
334
|
+
Arc::new(self.live_state.reader(self.read_store.clone())) as Arc<dyn LiveStateReader>
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
fn commit_store_query_source(&self) -> SqlCommitStoreQuerySource {
|
|
338
|
+
let read_scope = StorageReadScope::new(self.read_store.clone());
|
|
339
|
+
CommitStoreQuerySource {
|
|
340
|
+
commit_store_reader: Arc::new(self.commit_store.reader(read_scope.store())),
|
|
341
|
+
json_reader: JsonStoreContext::new().reader(read_scope.store()),
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
fn commit_graph(&self) -> Box<dyn CommitGraphReader> {
|
|
346
|
+
Box::new(CommitGraphContext::new().reader(self.read_store.clone()))
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
fn version_ref(&self) -> Arc<dyn VersionRefReader> {
|
|
350
|
+
Arc::new(self.version_ctx.ref_reader(self.read_store.clone()))
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
fn functions(&self) -> FunctionProviderHandle {
|
|
354
|
+
self.functions.clone()
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
fn blob_reader(&self) -> Arc<dyn BlobDataReader> {
|
|
358
|
+
Arc::new(self.binary_cas.reader(self.read_store.clone())) as Arc<dyn BlobDataReader>
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
fn list_visible_schemas(&self) -> Result<Vec<JsonValue>, LixError> {
|
|
362
|
+
Ok(self.visible_schemas.clone())
|
|
363
|
+
}
|
|
364
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
use crate::transaction::types::{TransactionWrite, TransactionWriteMode};
|
|
2
|
+
use crate::version::{
|
|
3
|
+
version_descriptor_stage_row, version_ref_stage_row, VersionLifecycle, VersionOperation,
|
|
4
|
+
VersionReferenceRole,
|
|
5
|
+
};
|
|
6
|
+
use crate::LixError;
|
|
7
|
+
|
|
8
|
+
use super::context::SessionContext;
|
|
9
|
+
|
|
10
|
+
/// Options for creating a new version from the session's active version.
|
|
11
|
+
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
12
|
+
pub struct CreateVersionOptions {
|
|
13
|
+
/// Optional caller-provided version id. If omitted, engine generates one.
|
|
14
|
+
pub id: Option<String>,
|
|
15
|
+
/// User-facing version name.
|
|
16
|
+
pub name: String,
|
|
17
|
+
/// Optional commit id for the new version head. If omitted, the current
|
|
18
|
+
/// active version head is used.
|
|
19
|
+
pub from_commit_id: Option<String>,
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/// Receipt returned after creating a version.
|
|
23
|
+
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
24
|
+
pub struct CreateVersionReceipt {
|
|
25
|
+
pub id: String,
|
|
26
|
+
pub name: String,
|
|
27
|
+
pub hidden: bool,
|
|
28
|
+
pub commit_id: String,
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
impl SessionContext {
|
|
32
|
+
/// Creates a new version from this session's current version head.
|
|
33
|
+
///
|
|
34
|
+
/// Version descriptors are tracked global facts so every version agrees on
|
|
35
|
+
/// which versions exist. Version refs are untracked global moving pointers,
|
|
36
|
+
/// so creating a ref does not add another changelog fact.
|
|
37
|
+
pub async fn create_version(
|
|
38
|
+
&self,
|
|
39
|
+
options: CreateVersionOptions,
|
|
40
|
+
) -> Result<CreateVersionReceipt, LixError> {
|
|
41
|
+
self.with_write_transaction(|transaction| {
|
|
42
|
+
Box::pin(async move {
|
|
43
|
+
let version_id = options
|
|
44
|
+
.id
|
|
45
|
+
.unwrap_or_else(|| transaction.functions().call_uuid_v7());
|
|
46
|
+
let source_head = if let Some(from_commit_id) = options.from_commit_id {
|
|
47
|
+
let mut commit_graph = transaction.commit_graph_reader();
|
|
48
|
+
VersionLifecycle::require_existing_commit(
|
|
49
|
+
&mut commit_graph,
|
|
50
|
+
&from_commit_id,
|
|
51
|
+
VersionOperation::CreateVersion,
|
|
52
|
+
VersionReferenceRole::CommitSource,
|
|
53
|
+
)
|
|
54
|
+
.await?;
|
|
55
|
+
from_commit_id
|
|
56
|
+
} else {
|
|
57
|
+
let active_version_id = transaction.active_version_id().to_string();
|
|
58
|
+
let reader = transaction.version_ref_reader();
|
|
59
|
+
VersionLifecycle::new(&reader)
|
|
60
|
+
.require_existing_commit_id(
|
|
61
|
+
&active_version_id,
|
|
62
|
+
VersionOperation::CreateVersion,
|
|
63
|
+
VersionReferenceRole::Source,
|
|
64
|
+
)
|
|
65
|
+
.await?
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
transaction
|
|
69
|
+
.stage_write(TransactionWrite::Rows {
|
|
70
|
+
mode: TransactionWriteMode::Insert,
|
|
71
|
+
rows: vec![
|
|
72
|
+
version_descriptor_stage_row(&version_id, &options.name, false),
|
|
73
|
+
version_ref_stage_row(&version_id, &source_head),
|
|
74
|
+
],
|
|
75
|
+
})
|
|
76
|
+
.await?;
|
|
77
|
+
|
|
78
|
+
Ok(CreateVersionReceipt {
|
|
79
|
+
id: version_id,
|
|
80
|
+
name: options.name,
|
|
81
|
+
hidden: false,
|
|
82
|
+
commit_id: source_head,
|
|
83
|
+
})
|
|
84
|
+
})
|
|
85
|
+
})
|
|
86
|
+
.await
|
|
87
|
+
}
|
|
88
|
+
}
|