2023-08-27 00:07:56 +02:00
|
|
|
use std::sync::Arc;
|
|
|
|
|
|
|
|
use axum::async_trait;
|
|
|
|
|
2023-08-27 19:57:16 +02:00
|
|
|
use churn_domain::LogEvent;
|
2023-08-27 18:15:25 +02:00
|
|
|
use itertools::Itertools;
|
2023-08-27 19:42:33 +02:00
|
|
|
|
2023-08-27 16:49:53 +02:00
|
|
|
use churn_capnp::CapnpPackExt;
|
|
|
|
|
|
|
|
use crate::db::Db;
|
|
|
|
|
2023-08-27 00:07:56 +02:00
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct EventService(Arc<dyn EventServiceTrait + Send + Sync + 'static>);
|
|
|
|
|
2023-08-27 16:49:53 +02:00
|
|
|
impl EventService {
|
|
|
|
pub fn new(db: Db) -> Self {
|
|
|
|
Self(Arc::new(DefaultEventService::new(db)))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-27 00:07:56 +02:00
|
|
|
impl std::ops::Deref for EventService {
|
|
|
|
type Target = Arc<dyn EventServiceTrait + Send + Sync + 'static>;
|
|
|
|
|
|
|
|
fn deref(&self) -> &Self::Target {
|
|
|
|
&self.0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
struct DefaultEventService {
|
2023-08-27 16:49:53 +02:00
|
|
|
db: Db,
|
2023-08-27 00:07:56 +02:00
|
|
|
}
|
|
|
|
|
2023-08-27 16:49:53 +02:00
|
|
|
impl DefaultEventService {
|
|
|
|
pub fn new(db: Db) -> Self {
|
|
|
|
Self { db }
|
2023-08-27 00:07:56 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[async_trait]
|
|
|
|
pub trait EventServiceTrait {
|
|
|
|
async fn append(&self, req: LogEvent) -> anyhow::Result<()>;
|
|
|
|
async fn get_from_cursor(&self, cursor: uuid::Uuid) -> anyhow::Result<Vec<LogEvent>>;
|
|
|
|
async fn get_from_beginning(&self) -> anyhow::Result<Vec<LogEvent>>;
|
2023-08-27 19:57:16 +02:00
|
|
|
async fn get_latest_cursor(&self) -> anyhow::Result<uuid::Uuid>;
|
2023-08-27 00:07:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[async_trait]
|
|
|
|
impl EventServiceTrait for DefaultEventService {
|
|
|
|
async fn append(&self, req: LogEvent) -> anyhow::Result<()> {
|
2023-08-27 16:49:53 +02:00
|
|
|
self.db
|
|
|
|
.insert("events_log", &req.id.to_string(), &req.serialize_capnp())
|
2023-08-27 18:15:25 +02:00
|
|
|
.await?;
|
2023-08-27 16:49:53 +02:00
|
|
|
|
2023-08-27 00:07:56 +02:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
async fn get_from_cursor(&self, cursor: uuid::Uuid) -> anyhow::Result<Vec<LogEvent>> {
|
2023-08-27 16:49:53 +02:00
|
|
|
let events = self.db.get_all("events_log").await?;
|
|
|
|
|
|
|
|
let events = events
|
2023-08-27 00:07:56 +02:00
|
|
|
.iter()
|
2023-08-27 19:42:33 +02:00
|
|
|
.flat_map(|e| match LogEvent::deserialize_capnp(e) {
|
2023-08-27 18:15:25 +02:00
|
|
|
Ok(o) => Ok(o),
|
|
|
|
Err(e) => {
|
|
|
|
tracing::error!("failed to deserialize capnp: {e}");
|
|
|
|
Err(e)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.sorted_by_key(|i| i.timestamp)
|
2023-08-27 00:07:56 +02:00
|
|
|
.skip_while(|item| item.id != cursor)
|
|
|
|
.skip(1)
|
2023-08-27 16:49:53 +02:00
|
|
|
.collect();
|
|
|
|
|
|
|
|
Ok(events)
|
2023-08-27 00:07:56 +02:00
|
|
|
}
|
|
|
|
async fn get_from_beginning(&self) -> anyhow::Result<Vec<LogEvent>> {
|
2023-08-27 16:49:53 +02:00
|
|
|
let events = self.db.get_all("events_log").await?;
|
|
|
|
|
|
|
|
let events = events
|
|
|
|
.iter()
|
2023-08-27 20:16:27 +02:00
|
|
|
.map(|x| x.as_slice())
|
2023-08-27 19:42:33 +02:00
|
|
|
.flat_map(LogEvent::deserialize_capnp)
|
2023-08-27 18:15:25 +02:00
|
|
|
.sorted_by_key(|i| i.timestamp)
|
2023-08-27 16:49:53 +02:00
|
|
|
.collect();
|
|
|
|
|
|
|
|
Ok(events)
|
2023-08-27 00:07:56 +02:00
|
|
|
}
|
2023-08-27 19:57:16 +02:00
|
|
|
|
|
|
|
async fn get_latest_cursor(&self) -> anyhow::Result<uuid::Uuid> {
|
|
|
|
let events = self.db.get_all("events_log").await?;
|
|
|
|
|
|
|
|
let event = events
|
|
|
|
.iter()
|
|
|
|
.flat_map(|e| match LogEvent::deserialize_capnp(e) {
|
|
|
|
Ok(o) => Ok(o),
|
|
|
|
Err(e) => {
|
|
|
|
tracing::error!("failed to deserialize capnp: {e}");
|
|
|
|
Err(e)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
.sorted_by_key(|i| i.timestamp)
|
|
|
|
.last();
|
|
|
|
|
|
|
|
match event {
|
|
|
|
Some(x) => Ok(x.id),
|
|
|
|
None => anyhow::bail!("no events found"),
|
|
|
|
}
|
|
|
|
}
|
2023-08-27 00:07:56 +02:00
|
|
|
}
|