From a045ea4cb02635b87184cac20819f49c39b75fd5 Mon Sep 17 00:00:00 2001 From: Scott Werner Date: Mon, 17 Aug 2026 12:02:10 -0400 Subject: [PATCH] Remove the unused list_blobs API from fabro-store RunDatabase::list_blobs and BlobStore::list have had no production callers since the store-dump export switched from enumerating the whole blob namespace to hydrating only referenced blob refs. The semantics have also gone stale: blobs now live in one content-addressed store shared across run handles, so list_blobs on a per-run handle returned every blob from every run, inviting exactly the per-run-enumeration misuse the old dump loop would be today. Co-Authored-By: Claude Fable 5 --- .../fabro-store/src/slate/blob_store.rs | 49 +------------------ lib/components/fabro-store/src/slate/mod.rs | 2 - .../fabro-store/src/slate/run_store.rs | 21 -------- 3 files changed, 1 insertion(+), 71 deletions(-) diff --git a/lib/components/fabro-store/src/slate/blob_store.rs b/lib/components/fabro-store/src/slate/blob_store.rs index 68c6a9a54..cb168cd2b 100644 --- a/lib/components/fabro-store/src/slate/blob_store.rs +++ b/lib/components/fabro-store/src/slate/blob_store.rs @@ -2,11 +2,9 @@ use std::sync::Arc; use bytes::Bytes; use fabro_types::BlobHash; -use futures::StreamExt; -use tracing::warn; +use crate::Result; use crate::record::{RawBytesCodec, Record, Repository}; -use crate::{Error, Result}; #[derive(Debug, Clone, PartialEq, Eq)] pub struct Blob(pub Bytes); @@ -65,22 +63,6 @@ impl BlobStore { pub async fn exists(&self, id: &BlobHash) -> Result { self.repo.exists(id).await } - - pub(crate) async fn list(&self) -> Result> { - let mut stream = self.repo.scan_ids_stream(); - let mut ids = Vec::new(); - while let Some(result) = stream.next().await { - match result { - Ok(id) => ids.push(id), - Err(Error::KeyParse(err)) => { - warn!(error = %err, "Skipping malformed blob key during listing"); - } - Err(err) => return Err(err), - } - } - ids.sort(); - Ok(ids) - } } #[cfg(test)] @@ -139,35 +121,6 @@ mod tests { assert_eq!(store.read(&id).await.unwrap(), Some(Bytes::new())); } - #[tokio::test] - async fn list_returns_sorted_ids_and_handles_empty_store() { - let store = store().await; - assert!(store.list().await.unwrap().is_empty()); - - let first_id = store.write(br#"{"z":1}"#).await.unwrap(); - let second_id = store.write(br#"{"a":1}"#).await.unwrap(); - let mut expected = vec![first_id, second_id]; - expected.sort(); - - assert_eq!(store.list().await.unwrap(), expected); - } - - #[tokio::test] - async fn list_skips_malformed_blob_ids() { - let (raw_db, store) = raw_store("blob-store-list-tests").await; - let id = store.write(b"valid").await.unwrap(); - - raw_db - .put( - SlateKey::new("blobs").with("sha256").with("not-a-blob-id"), - b"malformed", - ) - .await - .unwrap(); - - assert_eq!(store.list().await.unwrap(), vec![id]); - } - #[tokio::test] async fn raw_db_reads_exact_blob_bytes() { let (raw_db, store) = raw_store("blob-store-tests").await; diff --git a/lib/components/fabro-store/src/slate/mod.rs b/lib/components/fabro-store/src/slate/mod.rs index 8f9c16ac7..21e410c71 100644 --- a/lib/components/fabro-store/src/slate/mod.rs +++ b/lib/components/fabro-store/src/slate/mod.rs @@ -862,8 +862,6 @@ mod tests { reader.read_blob(&blob_id).await.unwrap().as_deref(), Some(blob.as_slice()) ); - assert_eq!(reader.list_blobs().await.unwrap(), vec![blob_id]); - let err = reader.write_blob(b"blocked").await.unwrap_err(); assert!(matches!(err, Error::ReadOnly)); diff --git a/lib/components/fabro-store/src/slate/run_store.rs b/lib/components/fabro-store/src/slate/run_store.rs index 646b636ab..9148ede95 100644 --- a/lib/components/fabro-store/src/slate/run_store.rs +++ b/lib/components/fabro-store/src/slate/run_store.rs @@ -565,10 +565,6 @@ impl RunDatabase { self.inner.blob_store.read(id).await } - pub async fn list_blobs(&self) -> Result> { - self.inner.blob_store.list().await - } - pub async fn state(&self) -> Result { Ok(Arc::unwrap_or_clone(self.projected_state().await?)) } @@ -896,23 +892,6 @@ mod tests { use crate::{Database, Error, EventPayload, keys}; - #[tokio::test] - async fn list_blobs_reads_global_cas_namespace() { - let object_store = Arc::new(InMemory::new()); - let store = Database::new(object_store, "", Duration::from_millis(1), None); - let run_id = "01JT56VE4Z5NZ814GZN2JZD65A".parse().unwrap(); - let run = store.create_run(&run_id).await.unwrap(); - let first_blob = br#"{"a":1}"#; - let second_blob = br#"{"b":2}"#; - - let first_id = run.write_blob(first_blob).await.unwrap(); - let second_id = run.write_blob(second_blob).await.unwrap(); - let mut blob_ids = run.list_blobs().await.unwrap(); - blob_ids.sort(); - - assert_eq!(blob_ids, vec![first_id, second_id]); - } - fn stage_prompt_payload(run_id: &RunId, idx: u32, node_id: Option<&str>) -> EventPayload { stage_prompt_payload_for_stage(run_id, idx, node_id, None) }