Skip to main content

SqliteMailStore

Struct SqliteMailStore 

Source
pub struct SqliteMailStore { /* private fields */ }
Expand description

A MailStore backed by SQLite through this crate’s own Db. Every mutating method below is exactly one transaction, matching the contract mail4agent_core::store’s module doc comment sets for a persistent implementation.

Implementations§

Source§

impl SqliteMailStore

Source

pub fn new(db: Db) -> Self

Wraps an already-open Db. The caller is responsible for having run crate::migrations against it first – typically the same main.rs boot sequence that opened db – so this constructor stays infallible and a daemon can hand in the very Db it opened itself.

Source

pub fn open_in_memory() -> Result<Self, StoreError>

Opens a fresh in-memory Db and runs this crate’s own migrations against it. Convenience for tests and small tools; a real daemon wants a file-backed Db it built (and migrated) itself and should use Self::new instead.

Source

pub fn db(&self) -> Db

The underlying Db handle. Clones share the same connection (see Db’s own doc comment) – useful when a daemon wants this store and some other subsystem sharing one sqlite file.

Trait Implementations§

Source§

impl MailStore for SqliteMailStore

Source§

fn register_participant( &mut self, id: ParticipantId, record: ParticipantRecord, ) -> Result<(), StoreError>

Registers a new participant. The caller (the engine) has already confirmed no participant is registered under this id.
Source§

fn set_listener_url( &mut self, id: &ParticipantId, url: Option<String>, ) -> Result<(), StoreError>

Replaces a participant’s registered delivery-listener URL – Some to register or replace one, None to remove it. The caller (the engine) has already confirmed id is registered and, on Some, already validated url’s shape.
Source§

fn deregister_participant( &mut self, id: &ParticipantId, ) -> Result<(), StoreError>

Removes a participant’s registration entirely, including its place in the secret-digest index. Room memberships naming this id are left as-is: the id can never authenticate again without a fresh registration, so a stale membership entry is inert, not a leak.
Source§

fn set_participant_secret_digest( &mut self, id: &ParticipantId, digest: SecretDigest, ) -> Result<(), StoreError>

Replaces a participant’s stored secret digest – the shared mechanism behind both revoking and rotating a secret (see crate::MailboxEngine::rotate_participant_secret).
Source§

fn get_participant( &self, id: &ParticipantId, ) -> Result<Option<ParticipantRecord>, StoreError>

Source§

fn find_participant_by_digest( &self, digest: &SecretDigest, ) -> Result<Option<(ParticipantId, ParticipantRecord)>, StoreError>

Looks a participant up by the exact digest of a presented secret. See crate::MailboxEngine::authenticate for why this is an index lookup, not a scan.
Source§

fn create_room( &mut self, id: RoomId, created_at_unix_ms: u64, ) -> Result<(), StoreError>

Creates a room with no members. The caller has already confirmed no room is registered under this id.
Source§

fn add_room_member( &mut self, room: &RoomId, participant: ParticipantId, ) -> Result<(), StoreError>

Idempotent: adding an existing member is a no-op.
Source§

fn remove_room_member( &mut self, room: &RoomId, participant: &ParticipantId, ) -> Result<(), StoreError>

Idempotent: removing a non-member is a no-op.
Source§

fn get_room(&self, id: &RoomId) -> Result<Option<RoomRecord>, StoreError>

Source§

fn insert_message( &mut self, message: Message, idempotency: Option<(Address, String)>, ) -> Result<InsertMessageOutcome, StoreError>

Stores message unless idempotency names a (sender address, key) pair already recorded against an earlier message, in which case nothing is created and that earlier message’s id is returned. One call, one transaction: a SQLite implementation satisfies this with an insert under a UNIQUE (sender, key) constraint (or an equivalent check-and-insert within one transaction), never a separate read-then-write pair that could race under concurrent callers. The sender is an Address rather than a ParticipantId so that a retry from one specific session is deduplicated against that session, not against every session of its account.
Source§

fn get_message(&self, id: &MessageId) -> Result<Option<Message>, StoreError>

Source§

fn messages_to_since( &self, to: &Address, since_unix_ms: u64, ) -> Result<Vec<Message>, StoreError>

Messages addressed to exactly to (a Address::Direct account address or a Address::Session one), no older than since_unix_ms. Never Address::Room – room mail is Self::room_messages_since, keyed by RoomId rather than by a full address, since it is never gated on the reader’s own identity the way this method’s result is.
Source§

fn room_messages_since( &self, room: &RoomId, since_unix_ms: u64, ) -> Result<Vec<Message>, StoreError>

Messages addressed to room, no older than since_unix_ms. Not gated on membership – the caller (the engine) decides who may see the result.
Source§

fn rooms_containing( &self, participant: &ParticipantId, ) -> Result<Vec<RoomId>, StoreError>

Every room participant currently belongs to. Membership stays on the account: a session looks its account’s rooms up through this same method, it does not have a membership set of its own (see SessionRecord).
Source§

fn record_ack(&mut self, ack: Ack) -> Result<Ack, StoreError>

Records an acknowledgement, or returns the one already on file for this (message_id, reader) pair unchanged. One call, one transaction, so two concurrent acks of the same message by the same reader cannot both “win” with different timestamps. reader is an Address so a session’s ack is tracked separately from its account’s and from its sibling sessions’, the way Matrix scopes a read marker to a (user_id, device_id) pair.
Source§

fn get_ack( &self, message_id: &MessageId, reader: &Address, ) -> Result<Option<Ack>, StoreError>

Source§

fn list_participants(&self) -> Result<Vec<ParticipantSummary>, StoreError>

Every registered participant, for the mailbox’s own directory (crate::MailboxEngine::directory). Returns the full set, always – this mailbox is a small, local directory, not a paginated social graph. Never returns a secret digest or a permission bit: see ParticipantSummary’s own doc comment for why the return type itself rules that out.
Source§

fn list_rooms(&self) -> Result<Vec<RoomSummary>, StoreError>

Every room the mailbox tracks, with its current membership, for the same directory. Also the full set, always, for the same reason.
Source§

fn get_session( &self, session: &SessionId, ) -> Result<Option<SessionRecord>, StoreError>

Looks a session up by its id. None until crate::MailboxEngine::ensure_session has registered it at least once.
Source§

fn upsert_session( &mut self, session: SessionId, record: SessionRecord, ) -> Result<(), StoreError>

Inserts or wholesale-replaces the record for session. The engine, not this trait, is responsible for merging a fresh reading into an existing record before calling this – see crate::MailboxEngine::ensure_session and ::set_declared, the only two callers, and the only two ways a SessionRecord ever changes.
Source§

fn sessions_of( &self, account: &ParticipantId, ) -> Result<Vec<(SessionId, SessionRecord)>, StoreError>

Every session currently registered under account, for the mailbox’s own directory (crate::MailboxEngine::directory), which nests them under their account the way Matrix nests devices under a user_id.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more