site_log/
lib.rs

1#![cfg_attr(docsrs, feature(doc_cfg))]
2#![feature(type_alias_impl_trait)]
3
4use std::{ops::Deref, sync::Arc};
5
6use anyhow::Result;
7use kvid::KvId;
8pub use site_log_derive::linkme;
9use tosql::ToSqlTrait;
10mod ctx;
11pub use ctx::Ctx;
12pub use tokio::spawn;
13
14pub static SITE_LOG_ID: KvId = KvId::const_new("siteLog");
15
16pub struct Site {
17  pub ctx: Arc<ctx::Ctx>,
18}
19
20#[derive(Clone)]
21pub struct Arg<T: Sized> {
22  pub ctx: Arc<ctx::Ctx>,
23  pub inner: Arc<T>,
24}
25
26impl<T> Deref for Arg<T> {
27  type Target = T;
28  fn deref(&self) -> &Self::Target {
29    self.inner.as_ref()
30  }
31}
32
33pub type ArcArg<T> = Arc<Arg<T>>;
34pub type JoinHandle = tokio::task::JoinHandle<Result<()>>;
35pub type Hook<T> = fn(ArcArg<T>) -> JoinHandle;
36pub type HookLi<T> = [Hook<T>];
37pub type HookSlice<T> = &'static linkme::DistributedSlice<HookLi<T>>;
38
39pub trait TypeHook
40where
41  Self: 'static + Sized,
42{
43  const ID: u64;
44  const HOOK: HookSlice<Self>;
45}
46
47impl Site {
48  pub async fn log<T: Send + Sync + TypeHook + ToSqlTrait>(
49    &self,
50    row: impl Into<Arc<T>>,
51  ) -> Result<()> {
52    let row = row.into();
53    let ctx = self.ctx.clone();
54    let (log_result, task_result) = tokio::join!(
55      tokio::spawn({
56        let dump = row.dump();
57        let ctx = ctx.clone();
58        async move {
59          use fred::types::streams::XID;
60          use xkv::fred::interfaces::StreamsInterface;
61          ctx
62            .xadd::<(), _, _, _, _>(
63              &ctx.site_key[..],
64              false,
65              None,
66              XID::Auto,
67              (&ctx.ipbin[..], xbin::concat!(ctx.bin, dump)),
68            )
69            .await
70        }
71      }),
72      tokio::spawn({
73        let arg = Arc::new(Arg { ctx, inner: row });
74        async move {
75          for i in T::HOOK.iter().map(|f| f(arg.clone())) {
76            let _ = i.await?;
77          }
78          Ok::<_, anyhow::Error>(())
79        }
80      })
81    );
82    let _ = task_result?;
83    let _ = log_result?;
84    Ok(())
85  }
86}