mirror of
https://codeberg.org/JasterV/event_bus.rs.git
synced 2026-04-26 18:10:02 +00:00
refactor: make more clear internally the management of the channel
This commit is contained in:
parent
21d7c2257a
commit
fd0d761e17
3 changed files with 27 additions and 34 deletions
35
src/lib.rs
35
src/lib.rs
|
|
@ -1,10 +1,13 @@
|
||||||
#![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/README.md"))]
|
#![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/README.md"))]
|
||||||
|
|
||||||
|
mod rc_map;
|
||||||
|
mod subscription;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
rc_map::{InsertError, RcMap},
|
rc_map::{InsertError, RcMap},
|
||||||
subscription::Subscription,
|
subscription::Subscription,
|
||||||
};
|
};
|
||||||
use async_broadcast::{Sender, broadcast};
|
use async_broadcast::{InactiveReceiver, Sender, broadcast};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
/// The default topic capacity, it has been set to this value
|
/// The default topic capacity, it has been set to this value
|
||||||
|
|
@ -12,8 +15,17 @@ use std::sync::Arc;
|
||||||
/// set their preferred value.
|
/// set their preferred value.
|
||||||
pub const DEFAULT_TOPIC_CAPACITY: usize = 1000;
|
pub const DEFAULT_TOPIC_CAPACITY: usize = 1000;
|
||||||
|
|
||||||
mod rc_map;
|
/// Utility typed used to keep at least an instance of both a sender and a receiver
|
||||||
mod subscription;
|
/// in memory so the channel doesn't get closed.
|
||||||
|
///
|
||||||
|
/// `async_broadcast` will drop a channel if either all the receivers or all the senders get dropped.
|
||||||
|
#[derive(Clone)]
|
||||||
|
struct Channel(
|
||||||
|
pub Sender<Arc<[u8]>>,
|
||||||
|
// The inactive receiver is never used but it needs to be here
|
||||||
|
// otherwise we risk the channel being closed if all other receivers are dropped.
|
||||||
|
#[allow(dead_code)] InactiveReceiver<Arc<[u8]>>,
|
||||||
|
);
|
||||||
|
|
||||||
/// Error type returned by the `publish` method.
|
/// Error type returned by the `publish` method.
|
||||||
#[derive(thiserror::Error, Debug)]
|
#[derive(thiserror::Error, Debug)]
|
||||||
|
|
@ -32,7 +44,7 @@ pub enum PublishError {
|
||||||
/// When all the subscriptions to a topic get dropped, the topic itself is dropped from memory.
|
/// When all the subscriptions to a topic get dropped, the topic itself is dropped from memory.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct EventBus {
|
pub struct EventBus {
|
||||||
inner: RcMap<Arc<str>, Sender<Arc<[u8]>>>,
|
inner: RcMap<Arc<str>, Channel>,
|
||||||
topic_capacity: usize,
|
topic_capacity: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -64,17 +76,10 @@ impl EventBus {
|
||||||
/// the topic will automatically be dropped from memory.
|
/// the topic will automatically be dropped from memory.
|
||||||
pub fn subscribe(&self, topic: &str) -> Subscription {
|
pub fn subscribe(&self, topic: &str) -> Subscription {
|
||||||
let (tx, rx) = broadcast(self.topic_capacity);
|
let (tx, rx) = broadcast(self.topic_capacity);
|
||||||
|
let channel = Channel(tx, rx.deactivate());
|
||||||
|
|
||||||
match self.inner.insert(topic.into(), tx) {
|
match self.inner.insert(topic.into(), channel) {
|
||||||
Ok(object_ref) => {
|
Ok(object_ref) => Subscription::from(object_ref),
|
||||||
// If in the moment of the channel creation, either the sender or the receiver get dropped, the channel will immediately be closed.
|
|
||||||
//
|
|
||||||
// This is why we are not using `Subscription::from(object_ref)` in this scenario
|
|
||||||
// but rather we must make use of the receiver created or the channel will be closed.
|
|
||||||
Subscription::new_with_rx(object_ref, rx)
|
|
||||||
}
|
|
||||||
// In this case we are fine with the new channel we created being dropped.
|
|
||||||
// Since a channel already exists for this key we don't need to store the receiver and we can let the channel be closed.
|
|
||||||
Err(InsertError::AlreadyExists(_key, object_ref)) => Subscription::from(object_ref),
|
Err(InsertError::AlreadyExists(_key, object_ref)) => Subscription::from(object_ref),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -88,7 +93,7 @@ impl EventBus {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
||||||
let tx = object_ref.value();
|
let Channel(tx, _) = object_ref.value();
|
||||||
let result = tx.try_broadcast(Arc::from(data));
|
let result = tx.try_broadcast(Arc::from(data));
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ use std::{
|
||||||
/// A smart reference around a key value pair.
|
/// A smart reference around a key value pair.
|
||||||
///
|
///
|
||||||
/// Once it is dropped, it will decrease the reference counter of the pair and potentially remove the pair if the counter hits 0.
|
/// Once it is dropped, it will decrease the reference counter of the pair and potentially remove the pair if the counter hits 0.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ObjectRef<K, V>
|
pub struct ObjectRef<K, V>
|
||||||
where
|
where
|
||||||
K: Hash + Eq + Clone,
|
K: Hash + Eq + Clone,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::rc_map::ObjectRef;
|
use crate::{Channel, rc_map::ObjectRef};
|
||||||
use async_broadcast::{Receiver, Sender};
|
use async_broadcast::Receiver;
|
||||||
use futures::Stream;
|
use futures::Stream;
|
||||||
use std::{
|
use std::{
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
|
|
@ -24,25 +24,13 @@ pub struct Subscription {
|
||||||
// We need to keep the ownership of the object ref
|
// We need to keep the ownership of the object ref
|
||||||
// Otherwise if the object ref gets dropped, it might cleanup the topic
|
// Otherwise if the object ref gets dropped, it might cleanup the topic
|
||||||
// And the channel would get closed
|
// And the channel would get closed
|
||||||
_object_ref: ObjectRef<Arc<str>, Sender<Arc<[u8]>>>,
|
_object_ref: ObjectRef<Arc<str>, Channel>,
|
||||||
rx: Receiver<Arc<[u8]>>,
|
rx: Receiver<Arc<[u8]>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Subscription {
|
impl From<ObjectRef<Arc<str>, Channel>> for Subscription {
|
||||||
pub(crate) fn new_with_rx(
|
fn from(object_ref: ObjectRef<Arc<str>, Channel>) -> Self {
|
||||||
object_ref: ObjectRef<Arc<str>, Sender<Arc<[u8]>>>,
|
let Channel(tx, _) = object_ref.value();
|
||||||
rx: Receiver<Arc<[u8]>>,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
_object_ref: object_ref,
|
|
||||||
rx,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<ObjectRef<Arc<str>, Sender<Arc<[u8]>>>> for Subscription {
|
|
||||||
fn from(object_ref: ObjectRef<Arc<str>, Sender<Arc<[u8]>>>) -> Self {
|
|
||||||
let tx = object_ref.value();
|
|
||||||
let rx = tx.new_receiver();
|
let rx = tx.new_receiver();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue