Harden worker IPC and recoverable runtime staging
This commit is contained in:
1 parent
0bba1a0aa7
commit
b3ebd7a894
12 files changed
+1152
-75
No files matched your search
@@ -94,6 +94,27 @@ pub fn default_model_directory() -> Result<PathBuf> {
|
||||
.join("embeddinggemma2"))
|
||||
}
|
||||
|
||||
/// Cheap location selection for optional bundled assets. This checks regular
|
||||
/// files and expected lengths only; `verify_cached` still verifies SHA-256
|
||||
/// before setup considers the model usable. Partial bundles use managed cache.
|
||||
pub fn has_model_files(directory: &Path) -> Result<bool> {
|
||||
model_files_present(directory, &manifest()?.files)
|
||||
}
|
||||
|
||||
fn model_files_present(directory: &Path, artifacts: &[Artifact]) -> Result<bool> {
|
||||
for artifact in artifacts {
|
||||
let metadata = match fs::metadata(directory.join(&artifact.path)) {
|
||||
Ok(metadata) => metadata,
|
||||
Err(error) if error.kind() == std::io::ErrorKind::NotFound => return Ok(false),
|
||||
Err(error) => return Err(error).context("inspect bundled model artifact"),
|
||||
};
|
||||
if !metadata.is_file() || metadata.len() != artifact.bytes {
|
||||
return Ok(false);
|
||||
}
|
||||
}
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
/// Offline validation includes file length and full SHA-256, not mere existence.
|
||||
pub fn verify_cached(directory: &Path) -> Result<bool> {
|
||||
for artifact in manifest()?.files {
|
||||
@@ -383,6 +404,32 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn optional_bundle_requires_both_regular_files_at_expected_sizes() {
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let artifacts = [artifact("one.gguf", b"abc"), artifact("two.gguf", b"xyz")];
|
||||
assert!(!model_files_present(directory.path(), &artifacts).unwrap());
|
||||
fs::write(directory.path().join("one.gguf"), b"abc").unwrap();
|
||||
assert!(!model_files_present(directory.path(), &artifacts).unwrap());
|
||||
fs::create_dir(directory.path().join("two.gguf")).unwrap();
|
||||
assert!(!model_files_present(directory.path(), &artifacts).unwrap());
|
||||
fs::remove_dir(directory.path().join("two.gguf")).unwrap();
|
||||
fs::write(directory.path().join("two.gguf"), b"xyz").unwrap();
|
||||
assert!(model_files_present(directory.path(), &artifacts).unwrap());
|
||||
fs::write(directory.path().join("one.gguf"), b"ab").unwrap();
|
||||
assert!(!model_files_present(directory.path(), &artifacts).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bundled_file_presence_never_substitutes_for_sha_verification() {
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
let artifact = artifact("one.gguf", b"abc");
|
||||
let path = directory.path().join(&artifact.path);
|
||||
fs::write(&path, b"xyz").unwrap();
|
||||
assert!(model_files_present(directory.path(), std::slice::from_ref(&artifact)).unwrap());
|
||||
assert!(!verified(&path, &artifact).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn same_size_corruption_is_detected_and_missing_cache_is_offline() {
|
||||
let directory = tempfile::tempdir().unwrap();
|
||||
|
||||
Reference in new issue
Block a user