Skip to main content

photon_backend/backend/
photon_backend.rs

1//! Object-safe backend trait for Photon publish/subscribe runtimes.
2//!
3//! Implement this trait and install via
4//! [`PhotonBuilder::backend_with_context`](https://docs.rs/uf-photon/latest/photon/struct.PhotonBuilder.html#method.backend_with_context).
5//!
6//! See also: [`crate::storage::StoragePort`], [`crate::GenericPhotonBackend`].
7
8use std::pin::Pin;
9
10use async_trait::async_trait;
11use futures::stream::Stream;
12use serde_json::Value;
13
14use crate::backend::BackendCapabilities;
15use crate::error::Result;
16use crate::models::Event;
17use crate::registry::TopicRegistry;
18
19/// Backend for publish/subscribe delivery and checkpoint persistence.
20#[async_trait]
21pub trait PhotonBackend: Send + Sync {
22    /// Stable telemetry label for ops metrics (e.g. `"mem"`, `"nats"`).
23    fn telemetry_label(&self) -> &'static str {
24        "custom"
25    }
26
27    /// Adapter capabilities (replay window, get-by-id support, …).
28    fn capabilities(&self) -> BackendCapabilities {
29        BackendCapabilities::mem()
30    }
31
32    /// Append an event and return its event id.
33    ///
34    /// # Contract
35    ///
36    /// - Returns the stable `event_id` assigned by the underlying storage port.
37    /// - Ordering and dedupe are per `(topic_name, topic_key)` partition, not global.
38    async fn publish(
39        &self,
40        topic_name: &str,
41        topic_key: Option<&str>,
42        actor_json: Value,
43        payload_json: Value,
44    ) -> Result<String>;
45
46    /// Stream events for a topic partition, optionally replaying after `after_seq`.
47    ///
48    /// # Contract
49    ///
50    /// - Same semantics as [`crate::storage::StoragePort::subscribe`].
51    fn subscribe(
52        &self,
53        topic_name: String,
54        topic_key_filter: Option<String>,
55        after_seq: Option<i64>,
56    ) -> Pin<Box<dyn Stream<Item = Result<Event>> + Send>>;
57
58    /// Load a single event by id.
59    ///
60    /// # Contract
61    ///
62    /// - Returns `None` when unknown or truncated; see backend [`BackendCapabilities`].
63    async fn get_event(&self, event_id: &str) -> Result<Option<Event>>;
64
65    /// Inventory-discovered topic descriptors.
66    fn registry(&self) -> &TopicRegistry;
67
68    /// Load the last committed checkpoint seq for a subscription partition.
69    ///
70    /// # Contract
71    ///
72    /// - Returns `None` when no checkpoint exists.
73    async fn get_checkpoint_seq(
74        &self,
75        subscription_name: &str,
76        topic_name: &str,
77        topic_key: Option<&str>,
78    ) -> Result<Option<i64>>;
79
80    /// Persist the high-water checkpoint seq for a subscription partition.
81    ///
82    /// # Contract
83    ///
84    /// - `last_seq` must not regress; coalesced writes may batch behind the scenes.
85    async fn set_checkpoint(
86        &self,
87        subscription_name: &str,
88        topic_name: &str,
89        topic_key: Option<&str>,
90        last_seq: i64,
91    ) -> Result<()>;
92}