From 4acec3d3dd2e5eb5bd1559c63ca01162a4ca847a Mon Sep 17 00:00:00 2001 From: Andrew Phillips Date: Mon, 25 Aug 2025 20:17:45 -0300 Subject: [PATCH] refactor: optimize item content streaming to reduce redundant database queries Co-authored-by: aider (openai/andrew/openrouter/qwen/qwen3-coder) --- src/services/async_item_service.rs | 71 +++++++++--------------------- 1 file changed, 20 insertions(+), 51 deletions(-) diff --git a/src/services/async_item_service.rs b/src/services/async_item_service.rs index e5fe3cb..408a278 100644 --- a/src/services/async_item_service.rs +++ b/src/services/async_item_service.rs @@ -63,15 +63,15 @@ impl AsyncItemService { let db = self.db.clone(); // Get item metadata first to check binary status and get MIME type - let item_with_meta = tokio::task::spawn_blocking(move || { + let item_with_content = tokio::task::spawn_blocking(move || { let conn = db.blocking_lock(); let item_service = ItemService::new(data_dir); - item_service.get_item(&conn, item_id) + item_service.get_item_content(&conn, item_id) }) .await .unwrap()?; - let metadata = item_with_meta.meta_as_map(); + let metadata = item_with_content.item_with_meta.meta_as_map(); let mime_type = metadata .get("mime_type") .map(|s| s.to_string()) @@ -84,19 +84,7 @@ impl AsyncItemService { } else { // For the binary check, we need to read a sample of the content // We'll read the first 8192 bytes to determine if it's binary - let data_dir = self.data_dir.clone(); - let db = self.db.clone(); - - let sample_content = tokio::task::spawn_blocking(move || { - let conn = db.blocking_lock(); - let item_service = ItemService::new(data_dir); - let item_with_content = item_service.get_item_content(&conn, item_id)?; - Ok::, CoreError>(item_with_content.content) - }) - .await - .unwrap()?; - - crate::common::is_binary::is_binary(&sample_content) + crate::common::is_binary::is_binary(&item_with_content.content) }; if is_content_binary { @@ -105,42 +93,23 @@ impl AsyncItemService { } // Create a stream that reads only the requested portion - let data_dir = self.data_dir.clone(); - let db = self.db.clone(); + let content = item_with_content.content; + let content_len = content.len() as u64; - let stream = Box::pin(tokio_stream::wrappers::ReceiverStream::new({ - let (tx, rx) = tokio::sync::mpsc::channel(1); - - tokio::task::spawn_blocking(move || { - let conn = db.blocking_lock(); - let item_service = ItemService::new(data_dir); - - match item_service.get_item_content(&conn, item_id) { - Ok(item_with_content) => { - let content = item_with_content.content; - let content_len = content.len() as u64; - - // Apply offset and length constraints - let start = std::cmp::min(offset, content_len); - let end = if length > 0 { - std::cmp::min(start + length, content_len) - } else { - content_len - }; - - if start < content_len { - let chunk = tokio_util::bytes::Bytes::from(content[start as usize..end as usize].to_vec()); - let _ = tx.blocking_send(Ok(chunk)); - } - } - Err(e) => { - let _ = tx.blocking_send(Err(std::io::Error::new(std::io::ErrorKind::Other, e.to_string()))); - } - } - }); - - rx - })); + // Apply offset and length constraints + let start = std::cmp::min(offset, content_len); + let end = if length > 0 { + std::cmp::min(start + length, content_len) + } else { + content_len + }; + + let stream = if start < content_len { + let chunk = tokio_util::bytes::Bytes::from(content[start as usize..end as usize].to_vec()); + Box::pin(tokio_stream::iter(vec![Ok(chunk)])) + } else { + Box::pin(tokio_stream::iter(vec![])) + }; Ok((stream, mime_type)) }