radicle_feed/
storage.rs

1use std::fmt;
2use std::future::Future;
3
4use radicle::cob::{ObjectId, TypeName};
5use radicle::git::Oid;
6use radicle::prelude::RepoId;
7
8use crate::entry::{OperationEntry, TimelineEntry};
9use crate::radicle_extra::sql;
10
11/// Trait for abstracting storage operations used by the rad-feed library.
12/// Consumers can implement this trait to provide their own storage backend.
13pub trait FeedStorage {
14    type Error: snafu::Error + 'static;
15
16    /// Get the last processed operation ID for a specific repository and COB (Collaborative Object)
17    fn get_last_processed_operation(
18        &self,
19        rid: &RepoId,
20        cob_id: &ObjectId,
21        typename: &TypeName,
22    ) -> impl Future<Output = Result<Option<sql::Oid>, Self::Error>>;
23
24    fn insert_timeline_entry(
25        &mut self,
26        entry: &TimelineEntry,
27    ) -> impl Future<Output = Result<(), Self::Error>>;
28
29    /// Check if an operation already exists in storage (for duplicate prevention)
30    fn operation_exists(
31        &self,
32        operation_id: &Oid,
33    ) -> impl Future<Output = Result<bool, Self::Error>>;
34
35    /// Insert a batch of operations entries into storage
36    fn insert_batch(
37        &mut self,
38        entries: &[OperationEntry],
39    ) -> impl Future<Output = Result<(), Self::Error>>;
40
41    /// Get statistics about stored data (optional, used for debugging/monitoring)
42    fn get_stats(&self) -> impl Future<Output = Result<StorageStats, Self::Error>>;
43}
44
45/// Statistics about the storage backend
46#[derive(Debug, Default)]
47pub struct StorageStats {
48    pub total_operations: u64,
49    pub operations_by_type: std::collections::HashMap<String, u64>,
50    pub tracked_objects: u64,
51}
52
53impl fmt::Display for StorageStats {
54    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
55        writeln!(f, "=== Storage Statistics ===")?;
56        writeln!(f, "Total operations: {}", self.total_operations)?;
57
58        for (kind, count) in &self.operations_by_type {
59            writeln!(f, "{}: {}", kind, count)?;
60        }
61
62        writeln!(f, "Tracked objects: {}", self.tracked_objects)?;
63        Ok(())
64    }
65}
66
67#[cfg(feature = "postgres")]
68pub mod postgres;