use std::fs::OpenOptions;
use std::io::Write;
use std::path::Path;
pub const MAX_MODEL_BYTES: usize = 200_000_000;
fn current_max_model_bytes() -> usize {
if let Ok(s) = std::env::var("JSON_ENGINE_MAX_MODEL_BYTES") {
if let Ok(n) = s.parse::<usize>() {
return n;
}
}
MAX_MODEL_BYTES
}
pub fn save_model(
path: &Path,
data: &[u8],
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let limit = current_max_model_bytes();
if data.len() > limit {
return Err(format!("model size {} exceeds limit {}", data.len(), limit).into());
}
if let Some(parent) = path.parent() {
std::fs::create_dir_all(parent)?;
}
let ts = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)?
.as_nanos();
let tmp = path.with_extension(format!("tmp.{}", ts));
{
let mut f = OpenOptions::new()
.write(true)
.create(true)
.truncate(true)
.open(&tmp)?;
f.write_all(data)?;
f.sync_all()?;
}
std::fs::rename(&tmp, path)?;
if let Some(dir) = path.parent() {
if let Ok(dir_file) = OpenOptions::new().read(true).open(dir) {
if let Err(e) = dir_file.sync_all() {
eprintln!(
"{{\"msg\":\"model_store: dir sync failed\",\"path\":\"{}\",\"error\":\"{}\"}}",
dir.display(),
e
);
}
}
}
Ok(())
}