tensorfs 0.3.8__tar.gz → 0.3.9__tar.gz
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.
- {tensorfs-0.3.8 → tensorfs-0.3.9}/Cargo.lock +2 -2
- {tensorfs-0.3.8 → tensorfs-0.3.9}/Cargo.toml +1 -1
- {tensorfs-0.3.8 → tensorfs-0.3.9}/PKG-INFO +1 -1
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/derived.rs +16 -9
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/durability.rs +54 -7
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/ingest/source.rs +60 -15
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-py/src/store.rs +18 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/pyproject.toml +1 -1
- {tensorfs-0.3.8 → tensorfs-0.3.9}/python/tensorfs/_ext.pyi +4 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/Cargo.toml +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/b64.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/bin/tfs/ckpt.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/bin/tfs/conform.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/bin/tfs/fetch.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/bin/tfs/ingest.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/bin/tfs/main.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/bin/tfs/rd.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/bin/tfs/repo.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/bin/tfs/snap.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/bin/tfs/watch.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/canon.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/capability.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/catalog.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/cbor.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/checkpoint.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/corpus.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/derived/roots.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/dtype.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/err.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/fetch.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/fill.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/fit.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/gc.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/header.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/home.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/ids.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/ingest/carrier.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/ingest/convert.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/ingest/fingerprint.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/ingest/gguf.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/ingest/journal.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/ingest/mod.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/ingest/preflight.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/ingest/stamp.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/ingest/transaction.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/jcs.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/lib.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/limits.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/machine.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/manifest.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/meta.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/project.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/providers.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/read.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/receipt.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/reclaim.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/registry.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/relation.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/repo_cache.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/repository.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/sha256.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/spec.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/staging.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/storage.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/store.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/transport/api.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/transport/http.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/transport/hub.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/transport/ledger.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/transport/mod.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/transport/policy.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/transport/pull.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/transport/push.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/transport/ranged.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/transport/tests.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/src/vectors.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/tests/fetch_url_progress.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/tests/fit.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/tests/fixtures/repo_apply/blobs.jsonl +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/tests/fixtures/repo_apply/expected_list.jsonl +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/tests/fixtures/repo_apply/expected_repository.json +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/tests/fixtures/repo_apply/expected_rows.jsonl +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/tests/fixtures/repo_apply/header.cbor +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/tests/fixtures/repo_apply/manifest.json +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/tests/fixtures/repo_apply/mutation.json +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/tests/home.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/tests/liveness.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/tests/reclaim.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/tests/reclaim_run.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/tests/repo_cache.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/tests/repo_store.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/tests/sha256_backends.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/tests/sharded_cas.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/tests/source_plan.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/tests/source_preflight.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/tests/staging.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/tests/store_boundaries.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/tests/tensor_schema.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/tests/version.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/tests/write_through.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-py/Cargo.toml +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-py/src/docs.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-py/src/errors.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-py/src/lib.rs +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/python/tensorfs/__init__.py +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/python/tensorfs/errors.py +0 -0
- {tensorfs-0.3.8 → tensorfs-0.3.9}/python/tensorfs/py.typed +0 -0
|
@@ -392,7 +392,7 @@ checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
|
|
|
392
392
|
|
|
393
393
|
[[package]]
|
|
394
394
|
name = "tensorfs-core"
|
|
395
|
-
version = "0.3.
|
|
395
|
+
version = "0.3.9"
|
|
396
396
|
dependencies = [
|
|
397
397
|
"fs2",
|
|
398
398
|
"minicbor",
|
|
@@ -404,7 +404,7 @@ dependencies = [
|
|
|
404
404
|
|
|
405
405
|
[[package]]
|
|
406
406
|
name = "tensorfs-py"
|
|
407
|
-
version = "0.3.
|
|
407
|
+
version = "0.3.9"
|
|
408
408
|
dependencies = [
|
|
409
409
|
"pyo3",
|
|
410
410
|
"tensorfs-core",
|
|
@@ -143,6 +143,20 @@ pub struct Declaration {
|
|
|
143
143
|
}
|
|
144
144
|
|
|
145
145
|
impl Declaration {
|
|
146
|
+
/// The native declaration encoder shared by Runtime intents and writers.
|
|
147
|
+
pub fn canonical_bytes(&mut self) -> Result<Vec<u8>> {
|
|
148
|
+
self.normalize_and_validate()?;
|
|
149
|
+
self.require_order()?;
|
|
150
|
+
let bytes = crate::canon::write(&self.to_value());
|
|
151
|
+
if bytes.len() > limits::DOC_MAX_BYTES / 2 {
|
|
152
|
+
return refuse(
|
|
153
|
+
Code::SIZE_CAP,
|
|
154
|
+
"derived declaration is over its metadata budget",
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
Ok(bytes)
|
|
158
|
+
}
|
|
159
|
+
|
|
146
160
|
fn require_order(&self) -> Result<()> {
|
|
147
161
|
if self.order.is_empty() {
|
|
148
162
|
return refuse(
|
|
@@ -1862,15 +1876,8 @@ pub fn begin(
|
|
|
1862
1876
|
"WriterSessionId must be positive and inside the canonical integer range",
|
|
1863
1877
|
);
|
|
1864
1878
|
}
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
let declaration_text = declaration.canonical_text();
|
|
1868
|
-
if declaration_text.len() > limits::DOC_MAX_BYTES / 2 {
|
|
1869
|
-
return refuse(
|
|
1870
|
-
Code::SIZE_CAP,
|
|
1871
|
-
"derived declaration is over its metadata budget",
|
|
1872
|
-
);
|
|
1873
|
-
}
|
|
1879
|
+
let declaration_text =
|
|
1880
|
+
String::from_utf8(declaration.canonical_bytes()?).expect("canonical JSON is UTF-8");
|
|
1874
1881
|
|
|
1875
1882
|
// The writer hold is registered before source metadata is touched. It is the live
|
|
1876
1883
|
// process proof that keeps exclusive GC out even for a source-free create.
|
|
@@ -185,21 +185,34 @@ pub fn canonical_refs(mut refs: Vec<ObjectRef>) -> Vec<ObjectRef> {
|
|
|
185
185
|
/// Read an admitted link from the local Store. Unlike `chain`, this does not require an
|
|
186
186
|
/// NFS binding: the ordinary transfer plane may have obtained it from the hub.
|
|
187
187
|
pub fn local_link(store: &Store, object: &ObjectRef) -> Result<Link> {
|
|
188
|
-
|
|
188
|
+
Link::parse(&read_document(store, object, Link::MAX_BYTES)?)
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/// Bound the actual pinned file before allocation, not only the untrusted claimed length.
|
|
192
|
+
/// Source and derived progress use the same exact ObjectRef admission contract as links.
|
|
193
|
+
pub(crate) fn read_document(store: &Store, object: &ObjectRef, cap: usize) -> Result<Vec<u8>> {
|
|
194
|
+
if object.length > cap as u64 {
|
|
195
|
+
return refuse(Code::COUNT_CAP, "checkpoint document exceeds its byte cap");
|
|
196
|
+
}
|
|
197
|
+
let mut file = store.open_verified(&object.sha256)?;
|
|
198
|
+
if file.len() != object.length {
|
|
189
199
|
return refuse(
|
|
190
|
-
Code::
|
|
191
|
-
"checkpoint
|
|
200
|
+
Code::LENGTH_MISMATCH,
|
|
201
|
+
"checkpoint document differs from its ObjectRef length",
|
|
192
202
|
);
|
|
193
203
|
}
|
|
194
|
-
let mut bytes =
|
|
195
|
-
|
|
204
|
+
let mut bytes = vec![0; object.length as usize];
|
|
205
|
+
std::io::Read::read_exact(&mut file, &mut bytes).map_err(|error| crate::err::Refusal {
|
|
206
|
+
code: Code::IO_FAILED,
|
|
207
|
+
detail: format!("read checkpoint document: {error}"),
|
|
208
|
+
})?;
|
|
196
209
|
if ObjectRef::of(&bytes) != *object {
|
|
197
210
|
return refuse(
|
|
198
211
|
Code::OBJECT_ID_MISMATCH,
|
|
199
|
-
"checkpoint
|
|
212
|
+
"checkpoint document differs from its ObjectRef",
|
|
200
213
|
);
|
|
201
214
|
}
|
|
202
|
-
|
|
215
|
+
Ok(bytes)
|
|
203
216
|
}
|
|
204
217
|
|
|
205
218
|
/// Each call reads one link and returns a bounded window, so a caller can fetch links and
|
|
@@ -1030,6 +1043,40 @@ pub fn restore_conversion(
|
|
|
1030
1043
|
mod tests {
|
|
1031
1044
|
use super::*;
|
|
1032
1045
|
|
|
1046
|
+
#[test]
|
|
1047
|
+
fn checkpoint_documents_refuse_wrong_lengths_before_reading_into_memory() {
|
|
1048
|
+
let root = std::env::temp_dir().join(format!(
|
|
1049
|
+
"tensorfs-document-bound-{}",
|
|
1050
|
+
crate::meta::now_nanos_unique()
|
|
1051
|
+
));
|
|
1052
|
+
let store = Store::init(&root).unwrap();
|
|
1053
|
+
let bytes = b"a verified resident object";
|
|
1054
|
+
let object = store
|
|
1055
|
+
.put_stream(
|
|
1056
|
+
&mut bytes.as_slice(),
|
|
1057
|
+
Some(&ObjectRef::of(bytes)),
|
|
1058
|
+
&Default::default(),
|
|
1059
|
+
)
|
|
1060
|
+
.unwrap()
|
|
1061
|
+
.obj;
|
|
1062
|
+
let mut short = object.clone();
|
|
1063
|
+
short.length = 1;
|
|
1064
|
+
assert_eq!(
|
|
1065
|
+
local_link(&store, &short).unwrap_err().code,
|
|
1066
|
+
Code::LENGTH_MISMATCH
|
|
1067
|
+
);
|
|
1068
|
+
assert_eq!(
|
|
1069
|
+
read_document(&store, &short, 1).unwrap_err().code,
|
|
1070
|
+
Code::LENGTH_MISMATCH
|
|
1071
|
+
);
|
|
1072
|
+
assert_eq!(
|
|
1073
|
+
read_document(&store, &object, 1).unwrap_err().code,
|
|
1074
|
+
Code::COUNT_CAP
|
|
1075
|
+
);
|
|
1076
|
+
assert_eq!(read_document(&store, &object, bytes.len()).unwrap(), bytes);
|
|
1077
|
+
std::fs::remove_dir_all(root).unwrap();
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1033
1080
|
fn object(byte: &str, length: u64) -> ObjectRef {
|
|
1034
1081
|
ObjectRef {
|
|
1035
1082
|
sha256: byte.repeat(32),
|
|
@@ -1207,11 +1207,51 @@ fn prepare_model_source_with_registry(
|
|
|
1207
1207
|
for source in &sources {
|
|
1208
1208
|
validate_prepared_result(store, source)?;
|
|
1209
1209
|
}
|
|
1210
|
+
// The final response can be lost after its catalog commit. Its existing local
|
|
1211
|
+
// cursors must remain discoverable without converting or reading source bodies.
|
|
1212
|
+
let mut checkpoints = Vec::new();
|
|
1213
|
+
let dir = transaction::candidate_dir(store.root(), &request.operation_id);
|
|
1214
|
+
for (requested, (plan_hex, _)) in request.profiles.iter().zip(&plans) {
|
|
1215
|
+
let plan_digest = format!("sha256:{plan_hex}");
|
|
1216
|
+
let chain = format!("{}/{}", request.operation_id, requested.slot);
|
|
1217
|
+
let journal = super::journal::Journal::open(&dir, plan_hex)?;
|
|
1218
|
+
let local = journal.local_head()?.ok_or_else(|| Refusal {
|
|
1219
|
+
code: Code::DURABILITY_UNPROVEN,
|
|
1220
|
+
detail: "completed source has no local checkpoint cursor".into(),
|
|
1221
|
+
})?;
|
|
1222
|
+
let supplied = request
|
|
1223
|
+
.checkpoints
|
|
1224
|
+
.iter()
|
|
1225
|
+
.find(|(slot, _)| slot == &requested.slot)
|
|
1226
|
+
.map(|(_, head)| head);
|
|
1227
|
+
let head = durability::checkpoint_predecessor(
|
|
1228
|
+
store,
|
|
1229
|
+
&durability::Policy {
|
|
1230
|
+
chain: &chain,
|
|
1231
|
+
operation: &request.operation_id,
|
|
1232
|
+
plan: &plan_digest,
|
|
1233
|
+
interval: durability::INTERVAL_BYTES,
|
|
1234
|
+
},
|
|
1235
|
+
Some(&local),
|
|
1236
|
+
supplied,
|
|
1237
|
+
)?
|
|
1238
|
+
.expect("a local cursor was supplied");
|
|
1239
|
+
let held = durability::local_chain(store, &head, &plan_digest)?;
|
|
1240
|
+
checkpoints.push(SourceCheckpoint {
|
|
1241
|
+
slot: requested.slot.clone(),
|
|
1242
|
+
plan_digest,
|
|
1243
|
+
head: durability::Head {
|
|
1244
|
+
head: Some(head),
|
|
1245
|
+
links: held.links,
|
|
1246
|
+
bytes: held.bytes,
|
|
1247
|
+
},
|
|
1248
|
+
});
|
|
1249
|
+
}
|
|
1210
1250
|
return Ok(PreparedModelSources {
|
|
1211
1251
|
replayed: true,
|
|
1212
1252
|
complete: true,
|
|
1213
1253
|
sources,
|
|
1214
|
-
checkpoints
|
|
1254
|
+
checkpoints,
|
|
1215
1255
|
spent: request
|
|
1216
1256
|
.roster
|
|
1217
1257
|
.iter()
|
|
@@ -1257,20 +1297,8 @@ fn prepare_model_source_with_registry(
|
|
|
1257
1297
|
durability::retain_local_chain(store, head, &request.operation_id)?;
|
|
1258
1298
|
if journal.is_empty() {
|
|
1259
1299
|
if let Some(progress) = held.progress.last() {
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
Code::COUNT_CAP,
|
|
1263
|
-
"checkpoint progress exceeds the document byte cap",
|
|
1264
|
-
);
|
|
1265
|
-
}
|
|
1266
|
-
let mut bytes = Vec::with_capacity(progress.length as usize);
|
|
1267
|
-
store.read_into(&progress.sha256, &mut bytes)?;
|
|
1268
|
-
if ObjectRef::of(&bytes) != *progress {
|
|
1269
|
-
return refuse(
|
|
1270
|
-
Code::OBJECT_ID_MISMATCH,
|
|
1271
|
-
"checkpoint progress differs from its ObjectRef",
|
|
1272
|
-
);
|
|
1273
|
-
}
|
|
1300
|
+
let bytes =
|
|
1301
|
+
durability::read_document(store, progress, crate::limits::DOC_MAX_BYTES)?;
|
|
1274
1302
|
drop(journal);
|
|
1275
1303
|
super::journal::install(&dir, &plan_hex, &bytes)?;
|
|
1276
1304
|
journal = super::journal::Journal::open(&dir, &plan_hex)?;
|
|
@@ -1583,6 +1611,19 @@ mod tests {
|
|
|
1583
1611
|
.unwrap();
|
|
1584
1612
|
assert!(replay.replayed);
|
|
1585
1613
|
assert_eq!(replay.sources, first.sources);
|
|
1614
|
+
assert_eq!(replay.checkpoints, first.checkpoints);
|
|
1615
|
+
let mut bodies_gone = request.clone();
|
|
1616
|
+
bodies_gone.landed.clear();
|
|
1617
|
+
for row in &bodies_gone.roster {
|
|
1618
|
+
fs::remove_file(&row.path).unwrap();
|
|
1619
|
+
}
|
|
1620
|
+
let recovered_heads =
|
|
1621
|
+
prepare_model_source_with_registry(&store, &bodies_gone, "fixture:registry", ®istry)
|
|
1622
|
+
.unwrap();
|
|
1623
|
+
assert_eq!(recovered_heads.checkpoints, first.checkpoints);
|
|
1624
|
+
// Remaining arms need their original carriers again.
|
|
1625
|
+
carrier(&request.roster[0].path, "weight", [1, 2, 3, 4]);
|
|
1626
|
+
carrier(&request.roster[1].path, "weight", [5, 6, 7, 8]);
|
|
1586
1627
|
|
|
1587
1628
|
let mut changed = request.clone();
|
|
1588
1629
|
changed.roster[0].object_id = format!("sha256:{}", "33".repeat(32));
|
|
@@ -2239,6 +2280,10 @@ mod tests {
|
|
|
2239
2280
|
)
|
|
2240
2281
|
.unwrap();
|
|
2241
2282
|
assert!(replay.replayed && replay.complete);
|
|
2283
|
+
assert_eq!(
|
|
2284
|
+
replay.checkpoints, resumed.checkpoints,
|
|
2285
|
+
"a lost final response replays even with an old ACK"
|
|
2286
|
+
);
|
|
2242
2287
|
let mut unrelated = registry.clone();
|
|
2243
2288
|
unrelated.entries[0]
|
|
2244
2289
|
.provenance
|
|
@@ -1437,6 +1437,24 @@ impl PyStore {
|
|
|
1437
1437
|
Ok(out)
|
|
1438
1438
|
}
|
|
1439
1439
|
|
|
1440
|
+
/// Canonical TensorFS declaration bytes for the current producer intent.
|
|
1441
|
+
#[allow(clippy::too_many_arguments)]
|
|
1442
|
+
#[pyo3(signature = (sources, targets, configs, order, max_new_bytes))]
|
|
1443
|
+
fn derived_declaration<'p>(
|
|
1444
|
+
&self,
|
|
1445
|
+
py: Python<'p>,
|
|
1446
|
+
sources: &Bound<'_, PyDict>,
|
|
1447
|
+
targets: &Bound<'_, PyDict>,
|
|
1448
|
+
configs: &Bound<'_, PyDict>,
|
|
1449
|
+
order: Vec<(String, String)>,
|
|
1450
|
+
max_new_bytes: u64,
|
|
1451
|
+
) -> PyResult<Bound<'p, PyBytes>> {
|
|
1452
|
+
let mut declaration =
|
|
1453
|
+
parse_declaration(py, sources, targets, configs, order, max_new_bytes)?;
|
|
1454
|
+
let bytes = declaration.canonical_bytes().or_refuse(py)?;
|
|
1455
|
+
Ok(PyBytes::new(py, &bytes))
|
|
1456
|
+
}
|
|
1457
|
+
|
|
1440
1458
|
/// Open one exact tfs-019 transaction. Python supplies typed plain values; canonical
|
|
1441
1459
|
/// declaration bytes are constructed and locked only by the compiled core.
|
|
1442
1460
|
// PyO3 exposes these as six named boundary fields. Packing them into an opaque dict
|
|
@@ -481,6 +481,10 @@ class Store:
|
|
|
481
481
|
components: Sequence[str],
|
|
482
482
|
configs: Sequence[str],
|
|
483
483
|
) -> dict[str, Any]: ...
|
|
484
|
+
def derived_declaration(
|
|
485
|
+
self, sources: dict[str, Any], targets: dict[str, Any], configs: dict[str, Any],
|
|
486
|
+
order: Sequence[tuple[str, str]], max_new_bytes: int,
|
|
487
|
+
) -> bytes: ...
|
|
484
488
|
def begin_derived(
|
|
485
489
|
self,
|
|
486
490
|
transaction_id: str,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/tests/fixtures/repo_apply/blobs.jsonl
RENAMED
|
File without changes
|
{tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/tests/fixtures/repo_apply/expected_list.jsonl
RENAMED
|
File without changes
|
|
File without changes
|
{tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/tests/fixtures/repo_apply/expected_rows.jsonl
RENAMED
|
File without changes
|
{tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/tests/fixtures/repo_apply/header.cbor
RENAMED
|
File without changes
|
{tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/tests/fixtures/repo_apply/manifest.json
RENAMED
|
File without changes
|
{tensorfs-0.3.8 → tensorfs-0.3.9}/crates/tensorfs-core/tests/fixtures/repo_apply/mutation.json
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|