1use std::{hash::Hash, sync::Arc};
16use ulid::Ulid;
17
18use crate::{
19 cursor::{Args, ReadResult, Value},
20 Event, RoutingKey, WriteError,
21};
22
23#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
40pub struct EventFilter {
41 pub aggregate_type: String,
43 pub aggregate_id: Option<String>,
45 pub name: Option<String>,
47}
48
49impl EventFilter {
50 pub fn exact(
54 aggregate_type: impl Into<String>,
55 id: impl Into<String>,
56 name: impl Into<String>,
57 ) -> Self {
58 Self {
59 aggregate_type: aggregate_type.into(),
60 aggregate_id: Some(id.into()),
61 name: Some(name.into()),
62 }
63 }
64
65 pub fn by_type(value: impl Into<String>) -> Self {
69 Self {
70 aggregate_type: value.into(),
71 aggregate_id: None,
72 name: None,
73 }
74 }
75
76 pub fn by_id(aggregate_type: impl Into<String>, id: impl Into<String>) -> Self {
80 Self {
81 aggregate_type: aggregate_type.into(),
82 aggregate_id: Some(id.into()),
83 name: None,
84 }
85 }
86
87 pub fn by_event(aggregate_type: impl Into<String>, name: impl Into<String>) -> Self {
91 Self {
92 aggregate_type: aggregate_type.into(),
93 aggregate_id: None,
94 name: Some(name.into()),
95 }
96 }
97}
98
99impl Hash for EventFilter {
100 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
101 self.aggregate_type.hash(state);
102 self.aggregate_id.hash(state);
103 self.name.hash(state);
104 }
105}
106
107#[async_trait::async_trait]
122pub trait Executor: Send + Sync + 'static {
123 fn default_routing_key(&self) -> Option<&str> {
131 None
132 }
133
134 async fn write(&self, events: Vec<Event>) -> Result<(), WriteError>;
138
139 fn write_watch(&self) -> Option<tokio::sync::watch::Receiver<u64>> {
150 None
151 }
152
153 fn stable_timestamp(&self) -> Option<u64> {
166 None
167 }
168
169 async fn get_subscriber_cursor(&self, key: String) -> anyhow::Result<Option<Value>>;
171
172 async fn is_subscriber_running(&self, key: String, worker_id: Ulid) -> anyhow::Result<bool>;
174
175 async fn upsert_subscriber(&self, key: String, worker_id: Ulid) -> anyhow::Result<()>;
177
178 async fn acknowledge(&self, key: String, cursor: Value, lag: u64) -> anyhow::Result<()>;
180
181 async fn read(
183 &self,
184 aggregators: Option<Vec<EventFilter>>,
185 routing_key: Option<RoutingKey>,
186 args: Args,
187 ) -> anyhow::Result<ReadResult<Event>>;
188
189 async fn latest_timestamp(
194 &self,
195 aggregators: Option<Vec<EventFilter>>,
196 routing_key: Option<RoutingKey>,
197 ) -> anyhow::Result<u64>;
198
199 async fn get_snapshot(
204 &self,
205 aggregate_type: String,
206 aggregate_revision: String,
207 id: String,
208 ) -> anyhow::Result<Option<(Vec<u8>, Value)>>;
209
210 async fn save_snapshot(
215 &self,
216 aggregate_type: String,
217 aggregate_revision: String,
218 id: String,
219 data: Vec<u8>,
220 cursor: Value,
221 ) -> anyhow::Result<()>;
222
223 async fn delete_snapshot(&self, aggregate_type: String, id: String) -> anyhow::Result<()>;
229}
230
231pub struct Evento {
246 inner: Arc<Box<dyn Executor>>,
247 default_routing_key: Option<String>,
248}
249
250impl Clone for Evento {
251 fn clone(&self) -> Self {
252 Self {
253 inner: self.inner.clone(),
254 default_routing_key: self.default_routing_key.clone(),
255 }
256 }
257}
258
259#[async_trait::async_trait]
260impl Executor for Evento {
261 fn default_routing_key(&self) -> Option<&str> {
262 self.default_routing_key.as_deref()
263 }
264
265 async fn write(&self, mut events: Vec<Event>) -> Result<(), WriteError> {
266 if let Some(default) = self.default_routing_key.as_deref() {
267 for event in &mut events {
268 if event.routing_key.is_none() {
269 event.routing_key = Some(default.to_owned());
270 }
271 }
272 }
273 self.inner.write(events).await
274 }
275
276 fn write_watch(&self) -> Option<tokio::sync::watch::Receiver<u64>> {
277 self.inner.write_watch()
278 }
279
280 fn stable_timestamp(&self) -> Option<u64> {
281 self.inner.stable_timestamp()
282 }
283
284 async fn read(
285 &self,
286 aggregators: Option<Vec<EventFilter>>,
287 routing_key: Option<RoutingKey>,
288 args: Args,
289 ) -> anyhow::Result<ReadResult<Event>> {
290 self.inner.read(aggregators, routing_key, args).await
291 }
292
293 async fn latest_timestamp(
294 &self,
295 aggregators: Option<Vec<EventFilter>>,
296 routing_key: Option<RoutingKey>,
297 ) -> anyhow::Result<u64> {
298 self.inner.latest_timestamp(aggregators, routing_key).await
299 }
300
301 async fn get_subscriber_cursor(&self, key: String) -> anyhow::Result<Option<Value>> {
302 self.inner.get_subscriber_cursor(key).await
303 }
304
305 async fn is_subscriber_running(&self, key: String, worker_id: Ulid) -> anyhow::Result<bool> {
306 self.inner.is_subscriber_running(key, worker_id).await
307 }
308
309 async fn upsert_subscriber(&self, key: String, worker_id: Ulid) -> anyhow::Result<()> {
310 self.inner.upsert_subscriber(key, worker_id).await
311 }
312
313 async fn acknowledge(&self, key: String, cursor: Value, lag: u64) -> anyhow::Result<()> {
314 self.inner.acknowledge(key, cursor, lag).await
315 }
316
317 async fn get_snapshot(
318 &self,
319 aggregate_type: String,
320 aggregate_revision: String,
321 id: String,
322 ) -> anyhow::Result<Option<(Vec<u8>, Value)>> {
323 self.inner
324 .get_snapshot(aggregate_type, aggregate_revision, id)
325 .await
326 }
327
328 async fn save_snapshot(
329 &self,
330 aggregate_type: String,
331 aggregate_revision: String,
332 id: String,
333 data: Vec<u8>,
334 cursor: Value,
335 ) -> anyhow::Result<()> {
336 self.inner
337 .save_snapshot(aggregate_type, aggregate_revision, id, data, cursor)
338 .await
339 }
340
341 async fn delete_snapshot(&self, aggregate_type: String, id: String) -> anyhow::Result<()> {
342 self.inner.delete_snapshot(aggregate_type, id).await
343 }
344}
345
346impl Evento {
347 pub fn new<E: Executor>(executor: E) -> Self {
349 Self {
350 inner: Arc::new(Box::new(executor)),
351 default_routing_key: None,
352 }
353 }
354
355 pub fn default_routing_key(mut self, key: impl Into<String>) -> Self {
362 self.default_routing_key = Some(key.into());
363 self
364 }
365}
366
367#[cfg(feature = "group")]
374#[derive(Clone, Default)]
375pub struct EventoGroup {
376 executors: Vec<Evento>,
377}
378
379#[cfg(feature = "group")]
380impl EventoGroup {
381 pub fn executor(mut self, executor: impl Into<Evento>) -> Self {
385 self.executors.push(executor.into());
386
387 self
388 }
389
390 pub fn first(&self) -> &Evento {
396 self.executors
397 .first()
398 .expect("EventoGroup must have at least one executor")
399 }
400}
401
402#[cfg(feature = "group")]
403#[async_trait::async_trait]
404impl Executor for EventoGroup {
405 fn default_routing_key(&self) -> Option<&str> {
406 self.first().default_routing_key()
407 }
408
409 async fn write(&self, events: Vec<Event>) -> Result<(), WriteError> {
410 self.first().write(events).await
411 }
412
413 fn write_watch(&self) -> Option<tokio::sync::watch::Receiver<u64>> {
414 self.first().write_watch()
415 }
416
417 fn stable_timestamp(&self) -> Option<u64> {
418 self.first().stable_timestamp()
419 }
420
421 async fn read(
422 &self,
423 aggregators: Option<Vec<EventFilter>>,
424 routing_key: Option<RoutingKey>,
425 args: Args,
426 ) -> anyhow::Result<ReadResult<Event>> {
427 use crate::cursor;
428 let futures = self
429 .executors
430 .iter()
431 .map(|e| e.read(aggregators.to_owned(), routing_key.to_owned(), args.clone()));
432
433 let results = futures_util::future::join_all(futures).await;
434 let mut events = vec![];
435 for res in results {
436 for edge in res?.edges {
437 events.push(edge.node);
438 }
439 }
440
441 Ok(cursor::Reader::new(events).args(args).execute()?)
442 }
443
444 async fn latest_timestamp(
445 &self,
446 aggregators: Option<Vec<EventFilter>>,
447 routing_key: Option<RoutingKey>,
448 ) -> anyhow::Result<u64> {
449 let futures = self
450 .executors
451 .iter()
452 .map(|e| e.latest_timestamp(aggregators.to_owned(), routing_key.to_owned()));
453
454 let results = futures_util::future::join_all(futures).await;
455 let mut max = 0u64;
456 for res in results {
457 let ts = res?;
458 if ts > max {
459 max = ts;
460 }
461 }
462
463 Ok(max)
464 }
465
466 async fn get_subscriber_cursor(&self, key: String) -> anyhow::Result<Option<Value>> {
467 self.first().get_subscriber_cursor(key).await
468 }
469
470 async fn is_subscriber_running(&self, key: String, worker_id: Ulid) -> anyhow::Result<bool> {
471 self.first().is_subscriber_running(key, worker_id).await
472 }
473
474 async fn upsert_subscriber(&self, key: String, worker_id: Ulid) -> anyhow::Result<()> {
475 self.first().upsert_subscriber(key, worker_id).await
476 }
477
478 async fn acknowledge(&self, key: String, cursor: Value, lag: u64) -> anyhow::Result<()> {
479 self.first().acknowledge(key, cursor, lag).await
480 }
481
482 async fn get_snapshot(
483 &self,
484 aggregate_type: String,
485 aggregate_revision: String,
486 id: String,
487 ) -> anyhow::Result<Option<(Vec<u8>, Value)>> {
488 self.first()
489 .get_snapshot(aggregate_type, aggregate_revision, id)
490 .await
491 }
492
493 async fn save_snapshot(
494 &self,
495 aggregate_type: String,
496 aggregate_revision: String,
497 id: String,
498 data: Vec<u8>,
499 cursor: Value,
500 ) -> anyhow::Result<()> {
501 self.first()
502 .save_snapshot(aggregate_type, aggregate_revision, id, data, cursor)
503 .await
504 }
505
506 async fn delete_snapshot(&self, aggregate_type: String, id: String) -> anyhow::Result<()> {
507 self.first().delete_snapshot(aggregate_type, id).await
508 }
509}
510
511#[cfg(feature = "rw")]
522pub struct Rw<R: Executor, W: Executor> {
523 r: R,
524 w: W,
525}
526
527#[cfg(feature = "rw")]
528impl<R: Executor + Clone, W: Executor + Clone> Clone for Rw<R, W> {
529 fn clone(&self) -> Self {
530 Self {
531 r: self.r.clone(),
532 w: self.w.clone(),
533 }
534 }
535}
536
537#[cfg(feature = "rw")]
538#[async_trait::async_trait]
539impl<R: Executor, W: Executor> Executor for Rw<R, W> {
540 fn default_routing_key(&self) -> Option<&str> {
541 self.w.default_routing_key()
542 }
543
544 async fn write(&self, events: Vec<Event>) -> Result<(), WriteError> {
545 self.w.write(events).await
546 }
547
548 fn write_watch(&self) -> Option<tokio::sync::watch::Receiver<u64>> {
549 self.r.write_watch()
550 }
551
552 fn stable_timestamp(&self) -> Option<u64> {
553 self.r.stable_timestamp()
554 }
555
556 async fn read(
557 &self,
558 aggregators: Option<Vec<EventFilter>>,
559 routing_key: Option<RoutingKey>,
560 args: Args,
561 ) -> anyhow::Result<ReadResult<Event>> {
562 self.r.read(aggregators, routing_key, args).await
563 }
564
565 async fn latest_timestamp(
566 &self,
567 aggregators: Option<Vec<EventFilter>>,
568 routing_key: Option<RoutingKey>,
569 ) -> anyhow::Result<u64> {
570 self.r.latest_timestamp(aggregators, routing_key).await
571 }
572
573 async fn get_subscriber_cursor(&self, key: String) -> anyhow::Result<Option<Value>> {
574 self.r.get_subscriber_cursor(key).await
575 }
576
577 async fn is_subscriber_running(&self, key: String, worker_id: Ulid) -> anyhow::Result<bool> {
578 self.r.is_subscriber_running(key, worker_id).await
579 }
580
581 async fn upsert_subscriber(&self, key: String, worker_id: Ulid) -> anyhow::Result<()> {
582 self.w.upsert_subscriber(key, worker_id).await
583 }
584
585 async fn acknowledge(&self, key: String, cursor: Value, lag: u64) -> anyhow::Result<()> {
586 self.w.acknowledge(key, cursor, lag).await
587 }
588
589 async fn get_snapshot(
590 &self,
591 aggregate_type: String,
592 aggregate_revision: String,
593 id: String,
594 ) -> anyhow::Result<Option<(Vec<u8>, Value)>> {
595 self.r
596 .get_snapshot(aggregate_type, aggregate_revision, id)
597 .await
598 }
599
600 async fn save_snapshot(
601 &self,
602 aggregate_type: String,
603 aggregate_revision: String,
604 id: String,
605 data: Vec<u8>,
606 cursor: Value,
607 ) -> anyhow::Result<()> {
608 self.w
609 .save_snapshot(aggregate_type, aggregate_revision, id, data, cursor)
610 .await
611 }
612
613 async fn delete_snapshot(&self, aggregate_type: String, id: String) -> anyhow::Result<()> {
614 self.w.delete_snapshot(aggregate_type, id).await
615 }
616}
617
618#[cfg(feature = "rw")]
619impl<R: Executor, W: Executor> From<(R, W)> for Rw<R, W> {
620 fn from((r, w): (R, W)) -> Self {
621 Self { r, w }
622 }
623}