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}