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 every 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,
impl<DB, D> Debug for NamedSubscriber<DB, D>where
DB: QueueDatabase + RoleColumns,
D: ByName<DB> + 'static,
Source§impl<DB, D> Subscriber for NamedSubscriber<DB, D>where
DB: QueueDatabase + RoleColumns,
D: ByName<DB> + 'static,
impl<DB, D> Subscriber for NamedSubscriber<DB, D>where
DB: QueueDatabase + RoleColumns,
D: ByName<DB> + 'static,
Source§type Message = NamedDelivery<DB, D>
type Message = NamedDelivery<DB, D>
Source§type Error = SqlxBrokerError
type Error = SqlxBrokerError
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> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T, W> HasTypeWitness<W> for Twhere
W: MakeTypeWitness<Arg = T>,
T: ?Sized,
impl<T, W> HasTypeWitness<W> for Twhere
W: MakeTypeWitness<Arg = T>,
T: ?Sized,
Source§impl<T> Identity for Twhere
T: ?Sized,
impl<T> Identity for Twhere
T: ?Sized,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
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