Skip to main content

NamedSubscriber

Struct NamedSubscriber 

Source
pub struct NamedSubscriber<DB, D = BuiltIn<DB>>
where DB: QueueDatabase + RoleColumns, D: ByName<DB> + 'static,
{ /* private fields */ }
Expand description

The subscriber a by-name subscription opens: the claim loop of the table its name’s route leads to.

It claims as an InboxSubscriber does, with the broker’s poll interval, on a broker whose dialect implements ByName for its database, as every built-in dialect does. A route whose row leaves every event to the crate, with role columns of types the crate reads itself, is read by those columns alone, in the row lock form and in the lease form: no box and no dynamic call per message. Each column is held to the type the struct reads it as, so a row that would not decode into the struct goes to the decode-failure policy here too. The types are an i16, i32, i64, String or Vec<u8> id, a Vec<u8> or String payload, headers as JSON, a text or byte key, an integer attempt, chrono or time times and leases, and SystemClock or DatabaseClock. Any other row runs its own code: each delivery is boxed, each settlement is a dynamic call whose future is boxed, and each poll of the stream is a dynamic call.

A mount that declares max_attempts(..) or dead_letter(..) on a name is refused at startup: an InboxQueue descriptor takes those.

§Examples

use ruststream::OutgoingMessage;
use ruststream_sqlx::prelude::*;
use serde::Deserialize;
use sqlx::{PgConnection, PgPool, Postgres};

#[derive(Inbox, sqlx::FromRow)]
#[inbox(table = "report_jobs")]
pub struct Report {
    #[field(id, generated)]
    id: i64,
    #[field(group)]
    name: String,
    #[field(payload)]
    payload: Vec<u8>,
}

impl Publish<Postgres> for Report {
    async fn publish(
        conn: &mut PgConnection,
        message: &OutgoingMessage<'_>,
    ) -> Result<(), sqlx::Error> {
        sqlx::query("INSERT INTO report_jobs (name, payload) VALUES ($1, $2)")
            .bind(message.name())
            .bind(message.payload())
            .execute(conn)
            .await?;
        Ok(())
    }
}

#[derive(Deserialize)]
struct Request {
    day: String,
}

// Each by-name mount opens a `NamedSubscriber`; the route's prefix leads both names into
// `report_jobs`, and each reads its own group.
#[subscriber("reports.daily")]
async fn daily(request: &Request) -> HandlerOutcome {
    tracing::info!(day = %request.day, "daily report");
    HandlerOutcome::ack()
}

#[subscriber("reports.weekly")]
async fn weekly(request: &Request) -> HandlerOutcome {
    tracing::info!(day = %request.day, "weekly report");
    HandlerOutcome::ack()
}

pub fn app(pool: PgPool) -> RustStream {
    RustStream::new(AppInfo::new("reports", "0.1.0")).with_broker(
        SqlxBroker::new(pool).route::<Report>("reports.*"),
        |b| {
            b.include(daily);
            b.include(weekly);
        },
    )
}

Trait Implementations§

Source§

impl<DB, D> Debug for NamedSubscriber<DB, D>
where DB: QueueDatabase + RoleColumns, D: ByName<DB> + 'static,

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<DB, D> Subscriber for NamedSubscriber<DB, D>
where DB: QueueDatabase + RoleColumns, D: ByName<DB> + 'static,

Source§

type Message = NamedDelivery<DB, D>

The message type yielded by this subscriber.
Source§

type Error = SqlxBrokerError

The error type yielded by the stream when delivery fails.
Source§

fn stream( &mut self, ) -> impl Stream<Item = Result<Self::Message, Self::Error>> + Send + '_

Returns a stream of broker deliveries. Read more

Auto Trait Implementations§

§

impl<DB, D = BuiltIn<DB>> !RefUnwindSafe for NamedSubscriber<DB, D>

§

impl<DB, D = BuiltIn<DB>> !UnwindSafe for NamedSubscriber<DB, D>

§

impl<DB, D> Freeze for NamedSubscriber<DB, D>
where Opened<DB, D>: Freeze,

§

impl<DB, D> Send for NamedSubscriber<DB, D>
where Opened<DB, D>: Send,

§

impl<DB, D> Sync for NamedSubscriber<DB, D>
where Opened<DB, D>: Sync,

§

impl<DB, D> Unpin for NamedSubscriber<DB, D>
where Opened<DB, D>: Unpin,

§

impl<DB, D> UnsafeUnpin for NamedSubscriber<DB, D>
where Opened<DB, D>: UnsafeUnpin,

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<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, W> HasTypeWitness<W> for T
where W: MakeTypeWitness<Arg = T>, T: ?Sized,

Source§

const WITNESS: W = W::MAKE

A constant of the type witness
Source§

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

Source§

const TYPE_EQ: TypeEq<T, <T as Identity>::Type> = TypeEq::NEW

Proof that Self is the same type as Self::Type, provides methods for casting between Self and Self::Type.
Source§

type Type = T

The same type as Self, used to emulate type equality bounds (T == U) with associated type equality constraints (T: Identity<Type = U>).
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> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> PublishedThrough<DefaultSlot> for T

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