@@ -1,4 +1,5 @@
|
||||
use crunch::errors::*;
|
||||
use crunch::traits::Event;
|
||||
|
||||
struct SomeEvent {
|
||||
name: String,
|
||||
@@ -22,7 +23,7 @@ impl crunch::traits::Deserializer for SomeEvent {
|
||||
}
|
||||
|
||||
impl crunch::traits::Event for SomeEvent {
|
||||
fn event_info(&self) -> crunch::traits::EventInfo {
|
||||
fn event_info() -> crunch::traits::EventInfo {
|
||||
crunch::traits::EventInfo {
|
||||
domain: "some-domain",
|
||||
entity_type: "some-entity",
|
||||
@@ -39,6 +40,18 @@ async fn main() -> anyhow::Result<()> {
|
||||
let transport = crunch::Transport::in_memory();
|
||||
crunch::OutboxHandler::new(in_memory.clone(), transport.clone()).spawn();
|
||||
let publisher = crunch::Publisher::new(in_memory);
|
||||
let subscriber = crunch::Subscriber::new(transport);
|
||||
|
||||
subscriber
|
||||
.subscribe(|item: SomeEvent| async move {
|
||||
tracing::info!(
|
||||
"subscription got event: {}, info: {}",
|
||||
item.name,
|
||||
item.int_event_info(),
|
||||
);
|
||||
Ok(())
|
||||
})
|
||||
.await?;
|
||||
|
||||
publisher
|
||||
.publish(SomeEvent {
|
||||
|
@@ -15,4 +15,64 @@ pub mod errors {
|
||||
pub use impls::Persistence;
|
||||
pub use outbox::OutboxHandler;
|
||||
pub use publisher::Publisher;
|
||||
pub use subscriber::Subscriber;
|
||||
pub use transport::Transport;
|
||||
|
||||
mod subscriber {
|
||||
use crunch_traits::{Event, EventInfo};
|
||||
use futures::StreamExt;
|
||||
|
||||
use crate::{errors, Transport};
|
||||
|
||||
pub struct Subscriber {
|
||||
transport: Transport,
|
||||
}
|
||||
|
||||
impl Subscriber {
|
||||
pub fn new(transport: Transport) -> Self {
|
||||
Self { transport }
|
||||
}
|
||||
|
||||
pub async fn subscribe<I, F, Fut>(
|
||||
&self,
|
||||
callback: F,
|
||||
) -> Result<(), errors::SubscriptionError>
|
||||
where
|
||||
F: Fn(I) -> Fut + Send + Sync + 'static,
|
||||
Fut: futures::Future<Output = Result<(), errors::SubscriptionError>> + Send + 'static,
|
||||
I: Event + Send + 'static,
|
||||
{
|
||||
let mut stream = self
|
||||
.transport
|
||||
.subscriber(&I::event_info())
|
||||
.await
|
||||
.map_err(errors::SubscriptionError::ConnectionFailed)?
|
||||
.ok_or(errors::SubscriptionError::FailedToSubscribe(
|
||||
anyhow::anyhow!("failed to find channel to subscribe to"),
|
||||
))?;
|
||||
|
||||
tokio::spawn(async move {
|
||||
while let Some(item) = stream.next().await {
|
||||
let item = match I::deserialize(item)
|
||||
.map_err(errors::SubscriptionError::DeserializationFailed)
|
||||
{
|
||||
Ok(i) => i,
|
||||
Err(e) => {
|
||||
tracing::warn!("deserialization failed: {}", e);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
match callback(item).await {
|
||||
Ok(_) => {}
|
||||
Err(e) => {
|
||||
tracing::error!("subscription callback failed: {}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -19,7 +19,7 @@ impl Publisher {
|
||||
let content = event.serialize().map_err(PublishError::SerializeError)?;
|
||||
|
||||
self.persistence
|
||||
.insert(&event.event_info(), content)
|
||||
.insert(&event.int_event_info(), content)
|
||||
.await
|
||||
.map_err(PublishError::DbError)?;
|
||||
|
||||
|
Reference in New Issue
Block a user