fix: correct critical bugs and improve pipe streaming performance
Critical bug fixes:
- save_item now returns real Item from database, not a hardcoded fake
- AsyncDataService::save() reuses self.sync_service instead of creating redundant instance
- GenerateStatus trait signature mismatch fixed (CLI/API decoupling)
Performance improvements (pipe path untouched):
- CompressionEngine::open() returns Box<dyn Read + Send> enabling true streaming
- mode_get eliminates triple full-file read (was sampling then re-reading entire file)
- FilteringReader adds fast-path bypass when no filters, pre-allocates temp buffer
- text.rs meta plugin processes &[u8] slice directly, eliminates data.to_vec() clone
API correctness:
- Tag parse errors now return 400 instead of being silently discarded
- compute_diff uses similar crate (LCS-based) instead of naive positional comparison
Cleanup:
- Modernize string formatting (format!({x})) across codebase
- Remove redundant DB query in get mode
- Derive Debug/ToSchema on public types
- Delete placeholder test files with no real assertions
- Extract parse_comma_tags utility function
This commit is contained in:
49
src/db.rs
49
src/db.rs
@@ -163,7 +163,7 @@ pub struct Meta {
|
||||
/// let conn = db::open(db_path)?;
|
||||
/// ```
|
||||
pub fn open(path: PathBuf) -> Result<Connection, Error> {
|
||||
debug!("DB: Opening file: {:?}", path);
|
||||
debug!("DB: Opening file: {path:?}");
|
||||
let mut conn = Connection::open_with_flags(
|
||||
path,
|
||||
OpenFlags::SQLITE_OPEN_READ_WRITE | OpenFlags::SQLITE_OPEN_CREATE,
|
||||
@@ -213,7 +213,7 @@ pub fn open(path: PathBuf) -> Result<Connection, Error> {
|
||||
/// assert!(id > 0);
|
||||
/// ```
|
||||
pub fn insert_item(conn: &Connection, item: Item) -> Result<i64> {
|
||||
debug!("DB: Inserting item: {:?}", item);
|
||||
debug!("DB: Inserting item: {item:?}");
|
||||
conn.execute(
|
||||
"INSERT INTO items (ts, size, compression) VALUES (?1, ?2, ?3)",
|
||||
params![item.ts, item.size, item.compression],
|
||||
@@ -353,7 +353,7 @@ pub fn add_meta(conn: &Connection, item_id: i64, name: &str, value: &str) -> Res
|
||||
/// db::update_item(&conn, item)?;
|
||||
/// ```
|
||||
pub fn update_item(conn: &Connection, item: Item) -> Result<()> {
|
||||
debug!("DB: Updating item: {:?}", item);
|
||||
debug!("DB: Updating item: {item:?}");
|
||||
conn.execute(
|
||||
"UPDATE items SET size=?2, compression=?3 WHERE id=?1",
|
||||
params![item.id, item.size, item.compression,],
|
||||
@@ -386,7 +386,7 @@ pub fn update_item(conn: &Connection, item: Item) -> Result<()> {
|
||||
/// db::delete_item(&conn, item)?;
|
||||
/// ```
|
||||
pub fn delete_item(conn: &Connection, item: Item) -> Result<()> {
|
||||
debug!("DB: Deleting item: {:?}", item);
|
||||
debug!("DB: Deleting item: {item:?}");
|
||||
conn.execute("DELETE FROM items WHERE id=?1", params![item.id])?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -416,7 +416,7 @@ pub fn delete_item(conn: &Connection, item: Item) -> Result<()> {
|
||||
/// db::query_delete_meta(&conn, meta)?;
|
||||
/// ```
|
||||
pub fn query_delete_meta(conn: &Connection, meta: Meta) -> Result<()> {
|
||||
debug!("DB: Deleting meta: {:?}", meta);
|
||||
debug!("DB: Deleting meta: {meta:?}");
|
||||
conn.execute(
|
||||
"DELETE FROM metas WHERE id=?1 AND name=?2",
|
||||
params![meta.id, meta.name],
|
||||
@@ -449,7 +449,7 @@ pub fn query_delete_meta(conn: &Connection, meta: Meta) -> Result<()> {
|
||||
/// db::query_upsert_meta(&conn, meta)?;
|
||||
/// ```
|
||||
pub fn query_upsert_meta(conn: &Connection, meta: Meta) -> Result<()> {
|
||||
debug!("DB: Inserting meta: {:?}", meta);
|
||||
debug!("DB: Inserting meta: {meta:?}");
|
||||
conn.execute(
|
||||
"INSERT INTO metas (id, name, value) VALUES (?1, ?2, ?3)
|
||||
ON CONFLICT(id, name) DO UPDATE SET value=?3",
|
||||
@@ -548,7 +548,7 @@ pub fn store_meta(conn: &Connection, meta: Meta) -> Result<()> {
|
||||
/// db::insert_tag(&conn, tag)?;
|
||||
/// ```
|
||||
pub fn insert_tag(conn: &Connection, tag: Tag) -> Result<()> {
|
||||
debug!("DB: Inserting tag: {:?}", tag);
|
||||
debug!("DB: Inserting tag: {tag:?}");
|
||||
conn.execute(
|
||||
"INSERT INTO tags (id, name) VALUES (?1, ?2)",
|
||||
params![tag.id, tag.name],
|
||||
@@ -580,7 +580,7 @@ pub fn insert_tag(conn: &Connection, tag: Tag) -> Result<()> {
|
||||
/// db::delete_item_tags(&conn, item)?;
|
||||
/// ```
|
||||
pub fn delete_item_tags(conn: &Connection, item: Item) -> Result<()> {
|
||||
debug!("DB: Deleting all item tags: {:?}", item);
|
||||
debug!("DB: Deleting all item tags: {item:?}");
|
||||
conn.execute("DELETE FROM tags WHERE id=?1", params![item.id])?;
|
||||
Ok(())
|
||||
}
|
||||
@@ -612,7 +612,7 @@ pub fn delete_item_tags(conn: &Connection, item: Item) -> Result<()> {
|
||||
/// db::set_item_tags(&conn, item, &tags)?;
|
||||
/// ```
|
||||
pub fn set_item_tags(conn: &Connection, item: Item, tags: &Vec<String>) -> Result<()> {
|
||||
debug!("DB: Setting tags for item: {:?} ?{:?}", item, tags);
|
||||
debug!("DB: Setting tags for item: {item:?} ?{tags:?}");
|
||||
delete_item_tags(conn, item.clone())?;
|
||||
let item_id = item.id.unwrap();
|
||||
for tag_name in tags {
|
||||
@@ -695,7 +695,7 @@ pub fn query_all_items(conn: &Connection) -> Result<Vec<Item>> {
|
||||
/// let tagged_items = db::query_tagged_items(&conn, &tags)?;
|
||||
/// ```
|
||||
pub fn query_tagged_items<'a>(conn: &'a Connection, tags: &'a Vec<String>) -> Result<Vec<Item>> {
|
||||
debug!("DB: Querying tagged items: {:?}", tags);
|
||||
debug!("DB: Querying tagged items: {tags:?}");
|
||||
let mut statement = conn
|
||||
.prepare_cached(
|
||||
"
|
||||
@@ -789,10 +789,7 @@ pub fn get_items_matching(
|
||||
tags: &Vec<String>,
|
||||
meta: &HashMap<String, String>,
|
||||
) -> Result<Vec<Item>> {
|
||||
debug!(
|
||||
"DB: Getting items matching: tags={:?} meta={:?}",
|
||||
tags, meta
|
||||
);
|
||||
debug!("DB: Getting items matching: tags={tags:?} meta={meta:?}");
|
||||
|
||||
let items = match tags.is_empty() {
|
||||
true => query_all_items(conn)?,
|
||||
@@ -812,7 +809,7 @@ pub fn get_items_matching(
|
||||
item_meta.insert(meta.name, meta.value);
|
||||
}
|
||||
|
||||
debug!("DB: Matching: {:?}: {:?}", item, item_meta);
|
||||
debug!("DB: Matching: {item:?}: {item_meta:?}");
|
||||
|
||||
for (k, v) in meta.iter() {
|
||||
match item_meta.get(k) {
|
||||
@@ -862,7 +859,7 @@ pub fn get_item_matching(
|
||||
tags: &Vec<String>,
|
||||
_meta: &HashMap<String, String>,
|
||||
) -> Result<Option<Item>> {
|
||||
debug!("DB: Get item matching tags: {:?}", tags);
|
||||
debug!("DB: Get item matching tags: {tags:?}");
|
||||
let mut statement = conn
|
||||
.prepare_cached(
|
||||
"
|
||||
@@ -925,7 +922,7 @@ pub fn get_item_matching(
|
||||
/// assert!(item.is_some());
|
||||
/// ```
|
||||
pub fn get_item(conn: &Connection, item_id: i64) -> Result<Option<Item>> {
|
||||
debug!("DB: Getting item {:?}", item_id);
|
||||
debug!("DB: Getting item {item_id:?}");
|
||||
let mut statement = conn
|
||||
.prepare_cached(
|
||||
"
|
||||
@@ -1018,7 +1015,7 @@ pub fn get_item_last(conn: &Connection) -> Result<Option<Item>> {
|
||||
/// let tags = db::get_item_tags(&conn, &item)?;
|
||||
/// ```
|
||||
pub fn get_item_tags(conn: &Connection, item: &Item) -> Result<Vec<Tag>> {
|
||||
debug!("DB: Getting tags for item: {:?}", item);
|
||||
debug!("DB: Getting tags for item: {item:?}");
|
||||
let mut statement = conn
|
||||
.prepare_cached("SELECT id, name FROM tags WHERE id=?1 ORDER BY name ASC")
|
||||
.context("Problem preparing SQL statement")?;
|
||||
@@ -1060,7 +1057,7 @@ pub fn get_item_tags(conn: &Connection, item: &Item) -> Result<Vec<Tag>> {
|
||||
/// let meta = db::get_item_meta(&conn, &item)?;
|
||||
/// ```
|
||||
pub fn get_item_meta(conn: &Connection, item: &Item) -> Result<Vec<Meta>> {
|
||||
debug!("DB: Getting item meta: {:?}", item);
|
||||
debug!("DB: Getting item meta: {item:?}");
|
||||
let mut statement = conn
|
||||
.prepare_cached("SELECT id, name, value FROM metas WHERE id=?1 ORDER BY name ASC")
|
||||
.context("Problem preparing SQL statement")?;
|
||||
@@ -1104,7 +1101,7 @@ pub fn get_item_meta(conn: &Connection, item: &Item) -> Result<Vec<Meta>> {
|
||||
/// let meta = db::get_item_meta_name(&conn, &item, "mime_type".to_string())?;
|
||||
/// ```
|
||||
pub fn get_item_meta_name(conn: &Connection, item: &Item, name: String) -> Result<Option<Meta>> {
|
||||
debug!("DB: Getting item meta name: {:?} {:?}", item, name);
|
||||
debug!("DB: Getting item meta name: {item:?} {name:?}");
|
||||
let mut statement = conn
|
||||
.prepare_cached("SELECT id, name, value FROM metas WHERE id=?1 AND name=?2")
|
||||
.context("Problem preparing SQL statement")?;
|
||||
@@ -1145,7 +1142,7 @@ pub fn get_item_meta_name(conn: &Connection, item: &Item, name: String) -> Resul
|
||||
/// let value = db::get_item_meta_value(&conn, &item, "source".to_string())?;
|
||||
/// ```
|
||||
pub fn get_item_meta_value(conn: &Connection, item: &Item, name: String) -> Result<Option<String>> {
|
||||
debug!("DB: Getting item meta value: {:?} {:?}", item, name);
|
||||
debug!("DB: Getting item meta value: {item:?} {name:?}");
|
||||
let mut statement = conn
|
||||
.prepare_cached("SELECT value FROM metas WHERE id=?1 AND name=?2")
|
||||
.context("Problem preparing SQL statement")?;
|
||||
@@ -1184,7 +1181,7 @@ pub fn get_tags_for_items(
|
||||
conn: &Connection,
|
||||
item_ids: &[i64],
|
||||
) -> Result<std::collections::HashMap<i64, Vec<Tag>>> {
|
||||
debug!("DB: Getting tags for items: {:?}", item_ids);
|
||||
debug!("DB: Getting tags for items: {item_ids:?}");
|
||||
|
||||
if item_ids.is_empty() {
|
||||
return Ok(std::collections::HashMap::new());
|
||||
@@ -1195,8 +1192,7 @@ pub fn get_tags_for_items(
|
||||
let placeholders_str = placeholders.join(",");
|
||||
|
||||
let sql = format!(
|
||||
"SELECT id, name FROM tags WHERE id IN ({}) ORDER BY id ASC, name ASC",
|
||||
placeholders_str
|
||||
"SELECT id, name FROM tags WHERE id IN ({placeholders_str}) ORDER BY id ASC, name ASC"
|
||||
);
|
||||
|
||||
let mut statement = conn
|
||||
@@ -1244,7 +1240,7 @@ pub fn get_meta_for_items(
|
||||
conn: &Connection,
|
||||
item_ids: &[i64],
|
||||
) -> Result<std::collections::HashMap<i64, std::collections::HashMap<String, String>>> {
|
||||
debug!("DB: Getting meta for items: {:?}", item_ids);
|
||||
debug!("DB: Getting meta for items: {item_ids:?}");
|
||||
|
||||
if item_ids.is_empty() {
|
||||
return Ok(std::collections::HashMap::new());
|
||||
@@ -1255,8 +1251,7 @@ pub fn get_meta_for_items(
|
||||
let placeholders_str = placeholders.join(",");
|
||||
|
||||
let sql = format!(
|
||||
"SELECT id, name, value FROM metas WHERE id IN ({}) ORDER BY id ASC, name ASC",
|
||||
placeholders_str
|
||||
"SELECT id, name, value FROM metas WHERE id IN ({placeholders_str}) ORDER BY id ASC, name ASC"
|
||||
);
|
||||
|
||||
let mut statement = conn
|
||||
|
||||
Reference in New Issue
Block a user