Subscriptions
Subscriptions are long-running async tasks which listen for external events passively, and forward Messages back to the application runtime. They can be used to continuously monitor events for the entire lifetime of the application.
Channels
The most common form of a subscription will be that of a channel. This will effectively behave as an async generator which yields messages to the application runtime. The source of your events could be from a channel, async stream, or a custom event loop.
struct MySubscription;
let subscription = cosmic::subscription::channel(
std::any::TypeId::of::<MySubscription>(),
4,
move |mut output| async move {
let stream = streamable_operation();
while let Some(event) = stream.next().await {
let _res = output.send(Message::StreamedMessage(event)).await;
}
futures::future::pending().await
},
);
Batches
If your application needs more than one Subscription, you can batch them together in one with Subscription::batch
.
Subscription::batch(vec![
subscription1,
subscription2,
subscription3,
])
Forwarding messages from commands
This trick enables Commands to yield Messages to the application before they are finished.
struct MessageForwarder;
let subscription = cosmic::subscription::channel(
std::any::TypeId::of::<MessageForwarder>(),
4,
move |mut output| async move {
let (tx, mut rx) = tokio::sync::mpsc::channel::<Message>(4);
let _res = output.send(Message::RegisterSubscriptionSender(tx)).await;
while let Some(event) = rx.recv().await {
let _res = output.send(event).await;
}
futures::future::pending().await
},
);
A channel will be created which sends its Sender directly to the application with a Message. You will store this message inside of your application like so:
Message::RegisterSubscriptionSender(sender) => {
self.sender = Some(sender);
}
Then you can clone the sender when creating commands that need to forward messages back to the runtime.