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 async fn get_subscriber_cursor(&self, key: String) -> anyhow::Result<Option<Value>>;
141
142 async fn is_subscriber_running(&self, key: String, worker_id: Ulid) -> anyhow::Result<bool>;
144
145 async fn upsert_subscriber(&self, key: String, worker_id: Ulid) -> anyhow::Result<()>;
147
148 async fn acknowledge(&self, key: String, cursor: Value, lag: u64) -> anyhow::Result<()>;
150
151 async fn read(
153 &self,
154 aggregators: Option<Vec<EventFilter>>,
155 routing_key: Option<RoutingKey>,
156 args: Args,
157 ) -> anyhow::Result<ReadResult<Event>>;
158
159 async fn latest_timestamp(
164 &self,
165 aggregators: Option<Vec<EventFilter>>,
166 routing_key: Option<RoutingKey>,
167 ) -> anyhow::Result<u64>;
168
169 async fn get_snapshot(
174 &self,
175 aggregate_type: String,
176 aggregate_revision: String,
177 id: String,
178 ) -> anyhow::Result<Option<(Vec<u8>, Value)>>;
179
180 async fn save_snapshot(
185 &self,
186 aggregate_type: String,
187 aggregate_revision: String,
188 id: String,
189 data: Vec<u8>,
190 cursor: Value,
191 ) -> anyhow::Result<()>;
192
193 async fn delete_snapshot(&self, aggregate_type: String, id: String) -> anyhow::Result<()>;
199}
200
201pub struct Evento {
216 inner: Arc<Box<dyn Executor>>,
217 default_routing_key: Option<String>,
218}
219
220impl Clone for Evento {
221 fn clone(&self) -> Self {
222 Self {
223 inner: self.inner.clone(),
224 default_routing_key: self.default_routing_key.clone(),
225 }
226 }
227}
228
229#[async_trait::async_trait]
230impl Executor for Evento {
231 fn default_routing_key(&self) -> Option<&str> {
232 self.default_routing_key.as_deref()
233 }
234
235 async fn write(&self, mut events: Vec<Event>) -> Result<(), WriteError> {
236 if let Some(default) = self.default_routing_key.as_deref() {
237 for event in &mut events {
238 if event.routing_key.is_none() {
239 event.routing_key = Some(default.to_owned());
240 }
241 }
242 }
243 self.inner.write(events).await
244 }
245
246 async fn read(
247 &self,
248 aggregators: Option<Vec<EventFilter>>,
249 routing_key: Option<RoutingKey>,
250 args: Args,
251 ) -> anyhow::Result<ReadResult<Event>> {
252 self.inner.read(aggregators, routing_key, args).await
253 }
254
255 async fn latest_timestamp(
256 &self,
257 aggregators: Option<Vec<EventFilter>>,
258 routing_key: Option<RoutingKey>,
259 ) -> anyhow::Result<u64> {
260 self.inner.latest_timestamp(aggregators, routing_key).await
261 }
262
263 async fn get_subscriber_cursor(&self, key: String) -> anyhow::Result<Option<Value>> {
264 self.inner.get_subscriber_cursor(key).await
265 }
266
267 async fn is_subscriber_running(&self, key: String, worker_id: Ulid) -> anyhow::Result<bool> {
268 self.inner.is_subscriber_running(key, worker_id).await
269 }
270
271 async fn upsert_subscriber(&self, key: String, worker_id: Ulid) -> anyhow::Result<()> {
272 self.inner.upsert_subscriber(key, worker_id).await
273 }
274
275 async fn acknowledge(&self, key: String, cursor: Value, lag: u64) -> anyhow::Result<()> {
276 self.inner.acknowledge(key, cursor, lag).await
277 }
278
279 async fn get_snapshot(
280 &self,
281 aggregate_type: String,
282 aggregate_revision: String,
283 id: String,
284 ) -> anyhow::Result<Option<(Vec<u8>, Value)>> {
285 self.inner
286 .get_snapshot(aggregate_type, aggregate_revision, id)
287 .await
288 }
289
290 async fn save_snapshot(
291 &self,
292 aggregate_type: String,
293 aggregate_revision: String,
294 id: String,
295 data: Vec<u8>,
296 cursor: Value,
297 ) -> anyhow::Result<()> {
298 self.inner
299 .save_snapshot(aggregate_type, aggregate_revision, id, data, cursor)
300 .await
301 }
302
303 async fn delete_snapshot(&self, aggregate_type: String, id: String) -> anyhow::Result<()> {
304 self.inner.delete_snapshot(aggregate_type, id).await
305 }
306}
307
308impl Evento {
309 pub fn new<E: Executor>(executor: E) -> Self {
311 Self {
312 inner: Arc::new(Box::new(executor)),
313 default_routing_key: None,
314 }
315 }
316
317 pub fn default_routing_key(mut self, key: impl Into<String>) -> Self {
324 self.default_routing_key = Some(key.into());
325 self
326 }
327}
328
329#[cfg(feature = "group")]
336#[derive(Clone, Default)]
337pub struct EventoGroup {
338 executors: Vec<Evento>,
339}
340
341#[cfg(feature = "group")]
342impl EventoGroup {
343 pub fn executor(mut self, executor: impl Into<Evento>) -> Self {
347 self.executors.push(executor.into());
348
349 self
350 }
351
352 pub fn first(&self) -> &Evento {
358 self.executors
359 .first()
360 .expect("EventoGroup must have at least one executor")
361 }
362}
363
364#[cfg(feature = "group")]
365#[async_trait::async_trait]
366impl Executor for EventoGroup {
367 fn default_routing_key(&self) -> Option<&str> {
368 self.first().default_routing_key()
369 }
370
371 async fn write(&self, events: Vec<Event>) -> Result<(), WriteError> {
372 self.first().write(events).await
373 }
374
375 async fn read(
376 &self,
377 aggregators: Option<Vec<EventFilter>>,
378 routing_key: Option<RoutingKey>,
379 args: Args,
380 ) -> anyhow::Result<ReadResult<Event>> {
381 use crate::cursor;
382 let futures = self
383 .executors
384 .iter()
385 .map(|e| e.read(aggregators.to_owned(), routing_key.to_owned(), args.clone()));
386
387 let results = futures_util::future::join_all(futures).await;
388 let mut events = vec![];
389 for res in results {
390 for edge in res?.edges {
391 events.push(edge.node);
392 }
393 }
394
395 Ok(cursor::Reader::new(events).args(args).execute()?)
396 }
397
398 async fn latest_timestamp(
399 &self,
400 aggregators: Option<Vec<EventFilter>>,
401 routing_key: Option<RoutingKey>,
402 ) -> anyhow::Result<u64> {
403 let futures = self
404 .executors
405 .iter()
406 .map(|e| e.latest_timestamp(aggregators.to_owned(), routing_key.to_owned()));
407
408 let results = futures_util::future::join_all(futures).await;
409 let mut max = 0u64;
410 for res in results {
411 let ts = res?;
412 if ts > max {
413 max = ts;
414 }
415 }
416
417 Ok(max)
418 }
419
420 async fn get_subscriber_cursor(&self, key: String) -> anyhow::Result<Option<Value>> {
421 self.first().get_subscriber_cursor(key).await
422 }
423
424 async fn is_subscriber_running(&self, key: String, worker_id: Ulid) -> anyhow::Result<bool> {
425 self.first().is_subscriber_running(key, worker_id).await
426 }
427
428 async fn upsert_subscriber(&self, key: String, worker_id: Ulid) -> anyhow::Result<()> {
429 self.first().upsert_subscriber(key, worker_id).await
430 }
431
432 async fn acknowledge(&self, key: String, cursor: Value, lag: u64) -> anyhow::Result<()> {
433 self.first().acknowledge(key, cursor, lag).await
434 }
435
436 async fn get_snapshot(
437 &self,
438 aggregate_type: String,
439 aggregate_revision: String,
440 id: String,
441 ) -> anyhow::Result<Option<(Vec<u8>, Value)>> {
442 self.first()
443 .get_snapshot(aggregate_type, aggregate_revision, id)
444 .await
445 }
446
447 async fn save_snapshot(
448 &self,
449 aggregate_type: String,
450 aggregate_revision: String,
451 id: String,
452 data: Vec<u8>,
453 cursor: Value,
454 ) -> anyhow::Result<()> {
455 self.first()
456 .save_snapshot(aggregate_type, aggregate_revision, id, data, cursor)
457 .await
458 }
459
460 async fn delete_snapshot(&self, aggregate_type: String, id: String) -> anyhow::Result<()> {
461 self.first().delete_snapshot(aggregate_type, id).await
462 }
463}
464
465#[cfg(feature = "rw")]
476pub struct Rw<R: Executor, W: Executor> {
477 r: R,
478 w: W,
479}
480
481#[cfg(feature = "rw")]
482impl<R: Executor + Clone, W: Executor + Clone> Clone for Rw<R, W> {
483 fn clone(&self) -> Self {
484 Self {
485 r: self.r.clone(),
486 w: self.w.clone(),
487 }
488 }
489}
490
491#[cfg(feature = "rw")]
492#[async_trait::async_trait]
493impl<R: Executor, W: Executor> Executor for Rw<R, W> {
494 fn default_routing_key(&self) -> Option<&str> {
495 self.w.default_routing_key()
496 }
497
498 async fn write(&self, events: Vec<Event>) -> Result<(), WriteError> {
499 self.w.write(events).await
500 }
501
502 async fn read(
503 &self,
504 aggregators: Option<Vec<EventFilter>>,
505 routing_key: Option<RoutingKey>,
506 args: Args,
507 ) -> anyhow::Result<ReadResult<Event>> {
508 self.r.read(aggregators, routing_key, args).await
509 }
510
511 async fn latest_timestamp(
512 &self,
513 aggregators: Option<Vec<EventFilter>>,
514 routing_key: Option<RoutingKey>,
515 ) -> anyhow::Result<u64> {
516 self.r.latest_timestamp(aggregators, routing_key).await
517 }
518
519 async fn get_subscriber_cursor(&self, key: String) -> anyhow::Result<Option<Value>> {
520 self.r.get_subscriber_cursor(key).await
521 }
522
523 async fn is_subscriber_running(&self, key: String, worker_id: Ulid) -> anyhow::Result<bool> {
524 self.r.is_subscriber_running(key, worker_id).await
525 }
526
527 async fn upsert_subscriber(&self, key: String, worker_id: Ulid) -> anyhow::Result<()> {
528 self.w.upsert_subscriber(key, worker_id).await
529 }
530
531 async fn acknowledge(&self, key: String, cursor: Value, lag: u64) -> anyhow::Result<()> {
532 self.w.acknowledge(key, cursor, lag).await
533 }
534
535 async fn get_snapshot(
536 &self,
537 aggregate_type: String,
538 aggregate_revision: String,
539 id: String,
540 ) -> anyhow::Result<Option<(Vec<u8>, Value)>> {
541 self.r
542 .get_snapshot(aggregate_type, aggregate_revision, id)
543 .await
544 }
545
546 async fn save_snapshot(
547 &self,
548 aggregate_type: String,
549 aggregate_revision: String,
550 id: String,
551 data: Vec<u8>,
552 cursor: Value,
553 ) -> anyhow::Result<()> {
554 self.w
555 .save_snapshot(aggregate_type, aggregate_revision, id, data, cursor)
556 .await
557 }
558
559 async fn delete_snapshot(&self, aggregate_type: String, id: String) -> anyhow::Result<()> {
560 self.w.delete_snapshot(aggregate_type, id).await
561 }
562}
563
564#[cfg(feature = "rw")]
565impl<R: Executor, W: Executor> From<(R, W)> for Rw<R, W> {
566 fn from((r, w): (R, W)) -> Self {
567 Self { r, w }
568 }
569}