pub struct PulsarSubscription { /* private fields */ }Expand description
A subscription descriptor for one Pulsar subscription over one or more topics.
It names the subscription, the topics it reads and the settings its consumer opens with:
new reads one topic, topics a fixed list and
pattern every topic whose full name a regular expression matches. Where the
subscription starts reading is the framework’s start_at(..) clause over
PulsarPosition.
The registration declares the retry cap and the dead-letter topic at the mount site with
b.include(handler).max_attempts(nonzero!(5)).dead_letter("orders-dlq"), and this descriptor
turns the declaration into the consumer’s own DeadLetterPolicy. The Pulsar client moves a
spent delivery itself, so the registration takes no out_retry(..) step. The cap needs a
subscription that dispatches to competing consumers - Pulsar counts a message’s redeliveries
on Shared and KeyShared - so a
declaration over the other two types refuses to start.
§Examples
Implements SubscriptionSource for the broker, so the declaration sits inline in the
#[subscriber(..)] decorator:
use std::time::Duration;
use ruststream_pulsar::prelude::*;
use serde::Deserialize;
#[derive(Deserialize)]
struct Order {
id: u64,
}
#[subscriber(
PulsarSubscription::new("orders", "workers")
.subscription_type(SubscriptionType::Shared)
.ack_timeout(Duration::from_secs(30))
)]
async fn handle(order: &Order) -> HandlerOutcome {
tracing::info!(order.id, "accepted");
HandlerOutcome::ack()
}
#[ruststream::app]
fn app() -> impl App {
RustStream::new(AppInfo::new("orders", "0.1.0")).with_broker(
PulsarBroker::new("pulsar://localhost:6650"),
|b| {
b.include(handle).max_attempts(nonzero!(5)).dead_letter("orders-dlq");
},
)
}The three forms side by side, one handler each:
use std::time::Duration;
use ruststream_pulsar::prelude::*;
use serde::Deserialize;
#[derive(Deserialize)]
struct Order {
id: u64,
}
#[subscriber(PulsarSubscription::new("persistent://acme/orders/created", "workers"))]
async fn fulfil(order: &Order) -> HandlerOutcome {
tracing::info!(order.id, "fulfilling");
HandlerOutcome::ack()
}
#[subscriber(PulsarSubscription::topics(["orders-eu", "orders-us"], "regional"))]
async fn tally(order: &Order) -> HandlerOutcome {
tracing::info!(order.id, "counted");
HandlerOutcome::ack()
}
#[subscriber(
PulsarSubscription::pattern("persistent://public/default/orders-.*", "audit")
.subscription_type(SubscriptionType::KeyShared)
.ack_timeout(Duration::from_secs(30))
)]
async fn audit(order: &Order) -> HandlerOutcome {
tracing::info!(order.id, "audited");
HandlerOutcome::ack()
}
#[ruststream::app]
fn app() -> impl App {
RustStream::new(AppInfo::new("orders", "0.1.0")).with_broker(
PulsarBroker::new("pulsar://localhost:6650"),
|b| {
b.include(fulfil);
b.include(tally);
b.include(audit);
},
)
}Implementations§
Source§impl PulsarSubscription
impl PulsarSubscription
Sourcepub fn new(topic: impl Into<String>, subscription: impl Into<String>) -> Self
pub fn new(topic: impl Into<String>, subscription: impl Into<String>) -> Self
Subscribes subscription to topic (a bare name, a tenant/namespace/topic triple,
or a fully qualified name).
Sourcepub fn topics<I, S>(topics: I, subscription: impl Into<String>) -> Self
pub fn topics<I, S>(topics: I, subscription: impl Into<String>) -> Self
Subscribes to every topic in the list.
Sourcepub fn pattern(
pattern: impl Into<String>,
subscription: impl Into<String>,
) -> Self
pub fn pattern( pattern: impl Into<String>, subscription: impl Into<String>, ) -> Self
Subscribes to every topic of one namespace whose fully qualified name matches pattern,
a regular expression.
The namespace is the one the pattern’s prefix names: persistent://acme/orders/.* and
acme/orders/.* read acme/orders, and a pattern with no tenant/namespace/ part, such
as orders-.*, reads public/default. The scheme is part of the regular expression, so
one pattern may select persistent and non-persistent topics alike. The pattern is checked
on subscribe: one that is no regular expression, or whose tenant or namespace is itself a
regular expression and so names no single namespace, refuses to start with
PulsarError::Invalid.
Sourcepub fn subscription_type(self, sub_type: SubscriptionType) -> Self
pub fn subscription_type(self, sub_type: SubscriptionType) -> Self
Sets the subscription type. Defaults to SubscriptionType::Shared.
Only the two types that dispatch to competing consumers carry a retry cap: the broker
counts a message’s redeliveries there and nowhere else, so a registration that declares
max_attempts(..) over an Exclusive or a
Failover subscription refuses to start.
Sourcepub fn ack_timeout(self, timeout: Duration) -> Self
pub fn ack_timeout(self, timeout: Duration) -> Self
Redelivers messages that stay unacknowledged longer than timeout.
Sourcepub fn batch_wait(self, wait: Duration) -> Self
pub fn batch_wait(self, wait: Duration) -> Self
Caps how long a partial batch waits for more deliveries after its first one.
Only a batch handler observes this: the client hands over one delivery at a time, so a
batch(n) registration on this subscription assembles its batches here, and a batch
closes when it holds n deliveries or when this has elapsed, whichever comes first.
Defaults to 10 ms; raising it trades latency for fuller batches on a sparse topic.
§Examples
use std::time::Duration;
use ruststream_pulsar::prelude::*;
use serde::Deserialize;
#[derive(Deserialize)]
struct Reading {
value: f64,
}
#[subscriber(
PulsarSubscription::new("readings", "aggregator")
.batch_wait(Duration::from_millis(250))
)]
async fn aggregate(readings: &[Reading]) -> HandlerOutcome {
let total: f64 = readings.iter().map(|reading| reading.value).sum();
tracing::info!(count = readings.len(), total, "readings settled");
HandlerOutcome::ack()
}
#[ruststream::app]
fn app() -> impl App {
RustStream::new(AppInfo::new("readings", "0.1.0")).with_broker(
PulsarBroker::new("pulsar://localhost:6650"),
|b| {
b.include(aggregate.batch(nonzero!(64)));
},
)
}Sourcepub fn subscription(&self) -> &str
pub fn subscription(&self) -> &str
The subscription name.
Trait Implementations§
Source§impl Clone for PulsarSubscription
impl Clone for PulsarSubscription
Source§impl Debug for PulsarSubscription
impl Debug for PulsarSubscription
impl Eq for PulsarSubscription
Source§impl IntoSource for PulsarSubscription
impl IntoSource for PulsarSubscription
Source§type Source = PulsarSubscription
type Source = PulsarSubscription
Source§fn into_source(self) -> Self
fn into_source(self) -> Self
Source§impl PartialEq for PulsarSubscription
impl PartialEq for PulsarSubscription
impl StructuralPartialEq for PulsarSubscription
Source§impl SubscriptionSource<ConnectedPulsarBroker> for PulsarSubscription
The Pulsar client moves a spent delivery itself: it counts the redeliveries of a message and,
past the consumer’s limit, produces it to the dead-letter topic and acknowledges the original.
Nothing is republished from the service, on any of the three addressing forms, so
out_retry(..) over this descriptor is a compile error and the registration’s declaration
reaches the consumer instead.
impl SubscriptionSource<ConnectedPulsarBroker> for PulsarSubscription
The Pulsar client moves a spent delivery itself: it counts the redeliveries of a message and,
past the consumer’s limit, produces it to the dead-letter topic and acknowledges the original.
Nothing is republished from the service, on any of the three addressing forms, so
out_retry(..) over this descriptor is a compile error and the registration’s declaration
reaches the consumer instead.
Source§fn declare_retry(self, declaration: &RetryDeclaration) -> Self
fn declare_retry(self, declaration: &RetryDeclaration) -> Self
Records the declaration; the consumer is built from it in subscribe, where the
connection exists.
Source§type Subscriber = PulsarSubscriber
type Subscriber = PulsarSubscriber
Source§type Copies = BrokerMoves
type Copies = BrokerMoves
AddressedCopies, NamedCopies or BrokerMoves. Read moreSource§async fn subscribe(
self,
connected: &ConnectedPulsarBroker,
) -> Result<PulsarSubscriber, PulsarError>
async fn subscribe( self, connected: &ConnectedPulsarBroker, ) -> Result<PulsarSubscriber, PulsarError>
Source§fn channel_bindings(&self) -> Bindings
fn channel_bindings(&self) -> Bindings
AsyncAPI document. Read moreSource§fn operation_bindings(&self) -> Bindings
fn operation_bindings(&self) -> Bindings
receive operation in the document. Read moreSource§fn declare_retry_on(
&self,
connected: &C,
declaration: &RetryDeclaration,
) -> Result<(), DeclareRetryError>
fn declare_retry_on( &self, connected: &C, declaration: &RetryDeclaration, ) -> Result<(), DeclareRetryError>
Source§fn message_bindings(&self) -> Bindings
fn message_bindings(&self) -> Bindings
Auto Trait Implementations§
impl Freeze for PulsarSubscription
impl RefUnwindSafe for PulsarSubscription
impl Send for PulsarSubscription
impl Sync for PulsarSubscription
impl Unpin for PulsarSubscription
impl UnsafeUnpin for PulsarSubscription
impl UnwindSafe for PulsarSubscription
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
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.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