use crate::Error;
use async_trait::async_trait;
use std::any::Any;
pub trait Event: Clone + Send + Sync + 'static {
fn name(&self) -> &'static str;
fn as_any(&self) -> &dyn Any
where
Self: Sized,
{
self
}
fn dispatch(
self,
) -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<(), Error>> + Send>>
where
Self: Sized,
{
Box::pin(crate::dispatch(self))
}
fn dispatch_sync(self)
where
Self: Sized,
{
crate::dispatch_sync(self)
}
}
#[async_trait]
pub trait Listener<E: Event>: Send + Sync + 'static {
async fn handle(&self, event: &E) -> Result<(), Error>;
fn name(&self) -> &'static str {
std::any::type_name::<Self>()
}
fn should_stop_propagation(&self) -> bool {
false
}
}
pub trait ShouldQueue {
fn queue(&self) -> &'static str {
"default"
}
fn delay(&self) -> Option<u64> {
None
}
fn max_retries(&self) -> u32 {
3
}
}
#[cfg(test)]
mod tests {
use super::*;
#[derive(Clone)]
struct TestEvent {
message: String,
}
impl Event for TestEvent {
fn name(&self) -> &'static str {
"TestEvent"
}
}
struct TestListener;
#[async_trait]
impl Listener<TestEvent> for TestListener {
async fn handle(&self, event: &TestEvent) -> Result<(), Error> {
assert_eq!(event.message, "hello");
Ok(())
}
}
#[tokio::test]
async fn test_listener_handle() {
let listener = TestListener;
let event = TestEvent {
message: "hello".into(),
};
let result = listener.handle(&event).await;
assert!(result.is_ok());
}
#[test]
fn test_event_name() {
let event = TestEvent {
message: "test".into(),
};
assert_eq!(event.name(), "TestEvent");
}
#[derive(Clone)]
struct DispatchTestEvent {
value: u32,
}
impl Event for DispatchTestEvent {
fn name(&self) -> &'static str {
"DispatchTestEvent"
}
}
#[tokio::test]
async fn test_event_dispatch_method() {
use crate::global_dispatcher;
use std::sync::atomic::{AtomicU32, Ordering};
use std::sync::Arc;
let counter = Arc::new(AtomicU32::new(0));
let counter_clone = Arc::clone(&counter);
global_dispatcher().on::<DispatchTestEvent, _, _>(move |event| {
let counter = Arc::clone(&counter_clone);
async move {
counter.fetch_add(event.value, Ordering::SeqCst);
Ok(())
}
});
let event = DispatchTestEvent { value: 42 };
let result = event.dispatch().await;
assert!(result.is_ok());
assert_eq!(counter.load(Ordering::SeqCst), 42);
}
#[derive(Clone)]
struct SyncDispatchTestEvent {
value: u32,
}
impl Event for SyncDispatchTestEvent {
fn name(&self) -> &'static str {
"SyncDispatchTestEvent"
}
}
#[tokio::test]
async fn test_event_dispatch_sync_method() {
use crate::global_dispatcher;
use std::sync::atomic::{AtomicU32, Ordering};
use std::sync::Arc;
use tokio::time::{sleep, Duration};
let counter = Arc::new(AtomicU32::new(0));
let counter_clone = Arc::clone(&counter);
global_dispatcher().on::<SyncDispatchTestEvent, _, _>(move |event| {
let counter = Arc::clone(&counter_clone);
async move {
counter.fetch_add(event.value, Ordering::SeqCst);
Ok(())
}
});
let event = SyncDispatchTestEvent { value: 99 };
event.dispatch_sync();
sleep(Duration::from_millis(50)).await;
assert_eq!(counter.load(Ordering::SeqCst), 99);
}
}