feat: with subscription

Signed-off-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
2023-09-23 22:38:12 +02:00
parent 05fb5c0722
commit 7b08b16cdb
10 changed files with 167 additions and 21 deletions

View File

@@ -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 {

View File

@@ -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(())
}
}
}

View File

@@ -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)?;