pub trait Subscription:
Send
+ Sync
+ 'static {
type Item: Async;
// Required method
fn subscribe<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Option<Pin<Box<dyn Stream<Item = Self::Item> + Send + Sync + 'static>>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait;
}Expand description
A Subscription is a multi-consumer abstraction over a single-consumer
Stream construct. A Subscription value can be shared by wrapping
it inside an Arc<dyn Subscription>. Each call to the
subscribe method would optionally return a Stream
that can be used by a single consumer.
The expected behavior of a Subscription implementation is that the
Streams returned from multiple calls to subscribe
should yield the same stream of items, modulo the race conditions between
each calls and errors from underlying sources.
A naive implementation of Subscription would subscribe from multiple
underlying sources, such as a network connection, each time
subscribe is called. This may be inefficient as each
stream would have to open new network connections, but it is simpler and
more resilient to error conditions such as network disconnections. A simple
way to implement a naive subscription is to use
CanCreateClosureSubscription to turn a closure into a Subscription.
A Subscription implementation could be made efficient by sharing one
incoming Stream with multiple consumers, by multiplexing them to multiple
outgoing Streams inside a background task. An example implementation of
this is CanStreamSubscription, which multiplexes a single stream into a
Subscription. A more advanced version of wrapping is provided by
CanMultiplexSubscription, which wraps around a naive Subscription and
perform both stream multiplexing and auto recovery from a background task by
calling the underlying subscribe function.
A Subscription do not guarantee whether the returned Stream is
finite or infinite (long-running). As a result, the Stream returned
from subscribe may terminate, in case if there is
underlying source encounter errors such as network disconnection. However,
a long-running consumer may call subscribe again in
attempt to obtain a new Stream.
A Subscription can be terminated by an underlying controller, such as
during program shutdown. When a subscription is terminated, it is expected
to return None for all subsequent calls to subscribe.
A long-running consumer can treat the returned None as a signal that
the subscription is terminated, and in turns terminate itself. The
underlying controller is also expected to terminate all currently running
Streams, so that the running consumers would receive the termination
signal.
Required Associated Types§
Required Methods§
Sourcefn subscribe<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Option<Pin<Box<dyn Stream<Item = Self::Item> + Send + Sync + 'static>>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
fn subscribe<'life0, 'async_trait>(
&'life0 self,
) -> Pin<Box<dyn Future<Output = Option<Pin<Box<dyn Stream<Item = Self::Item> + Send + Sync + 'static>>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
If the subscription is still active, returns a new single consumer
Stream which would produce a stream of items that are produced
after the method is called.
The items produced prior to the call to subscribe
are lost. This is to allow the underlying subscription implementation
to preserve memory and not store all items that are produced since the
subscription is created.
If the subscription is terminated, the method would return None.
Callers that receive None should expect all subsequent calls to
subscribe to also return None, and perform
appropriate actions for termination.