feat: add native zstd compression plugin and deduplicate shared compression/meta utilities
- Add zstd crate (v0.13) with native Rust compression engine (level 3) - Gate behind 'zstd' feature flag, fall back to program-based when disabled - Extract CompressionService::decompressing_reader/compressing_writer with zstd support - Extract MetaService::with_collector() to eliminate Arc<Mutex<Vec>> boilerplate - Extract read_with_bounds() helper for skip+read pattern - Add input validation for mutually exclusive --id and --tags flags - Add zstd round-trip tests
This commit is contained in:
@@ -656,17 +656,7 @@ impl ItemService {
|
||||
// Collect metadata from plugins into a Vec, then write to DB after plugins finish.
|
||||
// This avoids capturing &Connection in the save_meta closure (which would need unsafe
|
||||
// and wouldn't be Send for parallel plugins).
|
||||
let collected_meta: std::sync::Arc<std::sync::Mutex<Vec<(String, String)>>> =
|
||||
std::sync::Arc::new(std::sync::Mutex::new(Vec::new()));
|
||||
let collector = collected_meta.clone();
|
||||
let save_meta: crate::meta_plugin::SaveMetaFn =
|
||||
std::sync::Arc::new(std::sync::Mutex::new(move |name: &str, value: &str| {
|
||||
if let Ok(mut v) = collector.lock() {
|
||||
v.push((name.to_string(), value.to_string()));
|
||||
}
|
||||
}));
|
||||
|
||||
let meta_service = MetaService::new(save_meta);
|
||||
let (meta_service, collected_meta) = MetaService::with_collector();
|
||||
let mut plugins = meta_service.get_plugins(cmd, settings);
|
||||
debug!("ITEM_SERVICE: Got {} meta plugins", plugins.len());
|
||||
meta_service.initialize_plugins(&mut plugins);
|
||||
@@ -852,17 +842,7 @@ impl ItemService {
|
||||
db::set_item_tags(conn, item.clone(), &tags)?;
|
||||
}
|
||||
|
||||
let collected_meta: std::sync::Arc<std::sync::Mutex<Vec<(String, String)>>> =
|
||||
std::sync::Arc::new(std::sync::Mutex::new(Vec::new()));
|
||||
let collector = collected_meta.clone();
|
||||
let save_meta: crate::meta_plugin::SaveMetaFn =
|
||||
std::sync::Arc::new(std::sync::Mutex::new(move |name: &str, value: &str| {
|
||||
if let Ok(mut v) = collector.lock() {
|
||||
v.push((name.to_string(), value.to_string()));
|
||||
}
|
||||
}));
|
||||
|
||||
let meta_service = MetaService::new(save_meta);
|
||||
let (meta_service, collected_meta) = MetaService::with_collector();
|
||||
let mut plugins = if run_meta {
|
||||
meta_service.get_plugins(&mut cmd, settings)
|
||||
} else {
|
||||
@@ -926,17 +906,7 @@ impl ItemService {
|
||||
) -> Result<ItemWithMeta, CoreError> {
|
||||
let item = db::get_item(conn, item_id)?.ok_or_else(|| CoreError::ItemNotFound(item_id))?;
|
||||
|
||||
let collected_meta: std::sync::Arc<std::sync::Mutex<Vec<(String, String)>>> =
|
||||
std::sync::Arc::new(std::sync::Mutex::new(Vec::new()));
|
||||
let collector = collected_meta.clone();
|
||||
let save_meta: crate::meta_plugin::SaveMetaFn =
|
||||
std::sync::Arc::new(std::sync::Mutex::new(move |name: &str, value: &str| {
|
||||
if let Ok(mut v) = collector.lock() {
|
||||
v.push((name.to_string(), value.to_string()));
|
||||
}
|
||||
}));
|
||||
|
||||
let meta_service = MetaService::new(save_meta);
|
||||
let (meta_service, collected_meta) = MetaService::with_collector();
|
||||
let mut cmd = Command::new("keep");
|
||||
|
||||
let all_plugins = meta_service.get_plugins(&mut cmd, settings);
|
||||
|
||||
Reference in New Issue
Block a user