Skip to main content

substrate_core/
mailbox_port.rs

1//! MailboxStore port — durable mailbox and tasklist backed by a concrete store.
2//!
3//! This port is implemented by `store-sqlite`; the core crate only defines the
4//! contract. No IO, no adapter dependencies here.
5//!
6//! The port uses its own mirror types so that `substrate-core` stays free of
7//! any dependency on `a2a` or adapter crates. `store-sqlite` maps between the
8//! `a2a` types and these port-level types internally.
9
10use uuid::Uuid;
11
12/// Opaque task state at the port boundary.
13///
14/// Adapters convert to/from `a2a::TaskState` internally.
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum MailboxTaskState {
17    /// Submitted, not yet started.
18    Submitted,
19    /// Actively being worked on.
20    Working,
21    /// Waiting for caller input.
22    InputRequired,
23    /// Finished successfully.
24    Completed,
25    /// Ended in error.
26    Failed,
27    /// Explicitly cancelled.
28    Cancelled,
29}
30
31/// The MailboxStore port: durable mailbox + task list.
32///
33/// Implementations MUST guarantee atomic claim semantics: at most one caller
34/// wins the race to claim a given message (i.e. `Unread → Delivered` is
35/// exclusive).
36pub trait MailboxStore: Send + Sync {
37    /// The message type stored by this implementation.
38    type Msg;
39    /// The task type stored by this implementation.
40    type Task;
41    /// The error type returned by store operations.
42    type Error: std::error::Error + Send + Sync + 'static;
43
44    /// Post a message into the mailbox.
45    fn post(&self, msg: &Self::Msg) -> Result<(), Self::Error>;
46
47    /// Return all unread messages addressed to `to` in `team_id`.
48    fn inbox(&self, team_id: &str, to: &str) -> Result<Vec<Self::Msg>, Self::Error>;
49
50    /// Atomic claim: transition message state from `Unread` to `Delivered`.
51    ///
52    /// Returns `true` iff this caller won the race (SQLite rowcount == 1).
53    fn claim(&self, message_id: Uuid) -> Result<bool, Self::Error>;
54
55    /// Mark a message as `Consumed`.
56    fn consume(&self, message_id: Uuid) -> Result<(), Self::Error>;
57
58    /// Roll back a claim: transition message state from `Delivered` to `Unread`.
59    fn unclaim(&self, message_id: Uuid) -> Result<(), Self::Error>;
60
61    /// Insert a new task.
62    fn task_create(&self, task: &Self::Task) -> Result<(), Self::Error>;
63
64    /// Advance a task's state, optionally recording a note.
65    fn task_update(
66        &self,
67        id: Uuid,
68        state: MailboxTaskState,
69        note: Option<&str>,
70    ) -> Result<(), Self::Error>;
71
72    /// Return all tasks for a team.
73    fn task_list(&self, team_id: &str) -> Result<Vec<Self::Task>, Self::Error>;
74}