grafos_jobs/
output_store.rs

1//! Output store trait and in-memory implementation.
2
3use alloc::collections::BTreeMap;
4use alloc::vec::Vec;
5use grafos_std::error::FabricError;
6
7use crate::work_chunk::ChunkId;
8
9/// Trait for storing and retrieving chunk outputs by ID.
10///
11/// Implementations can back this with memory, block storage, or any other
12/// durable medium. The coordinator uses the store for idempotent output
13/// capture — if a chunk's output already exists, it is skipped on retry.
14pub trait JobOutputStore {
15    /// Store output bytes for a chunk.
16    ///
17    /// # Errors
18    ///
19    /// Returns a `FabricError` if the store cannot persist the output.
20    fn put(&mut self, id: ChunkId, data: Vec<u8>) -> Result<(), FabricError>;
21
22    /// Retrieve output bytes for a chunk, if present.
23    ///
24    /// # Errors
25    ///
26    /// Returns a `FabricError` on read failure (not on missing key —
27    /// that returns `Ok(None)`).
28    fn get(&self, id: ChunkId) -> Result<Option<Vec<u8>>, FabricError>;
29
30    /// Check whether output exists for a chunk.
31    fn contains(&self, id: ChunkId) -> bool;
32
33    /// Remove all stored outputs (teardown).
34    fn clear(&mut self);
35}
36
37/// In-memory output store backed by a `BTreeMap`.
38///
39/// Suitable for testing and jobs where outputs fit in memory.
40#[derive(Debug, Default)]
41pub struct MemoryOutputStore {
42    data: BTreeMap<ChunkId, Vec<u8>>,
43}
44
45impl MemoryOutputStore {
46    /// Create a new empty store.
47    pub fn new() -> Self {
48        MemoryOutputStore {
49            data: BTreeMap::new(),
50        }
51    }
52}
53
54impl JobOutputStore for MemoryOutputStore {
55    fn put(&mut self, id: ChunkId, data: Vec<u8>) -> Result<(), FabricError> {
56        self.data.insert(id, data);
57        Ok(())
58    }
59
60    fn get(&self, id: ChunkId) -> Result<Option<Vec<u8>>, FabricError> {
61        Ok(self.data.get(&id).cloned())
62    }
63
64    fn contains(&self, id: ChunkId) -> bool {
65        self.data.contains_key(&id)
66    }
67
68    fn clear(&mut self) {
69        self.data.clear();
70    }
71}