use bytes::Bytes;
use crate::{Response, Return};
macro_rules! args_try_into {
($prefix: expr, $name:expr, $args:expr, $($await:tt)*) => {{
use log::{error, info};
let mut prefix = $prefix.into();
prefix += " ";
prefix += $name;
match $args.try_into() {
Ok(args) => {
let start = coarsetime::Instant::now();
let result = Self::call(&args)$($await)*;
let duration = start.elapsed().as_millis();
prefix += &format!(" {duration}ms");
match result {
Return::Err(err) => {
error!("{prefix} {args:?} {err}");
Return::Response(Response {
code: 500,
body: err.to_string().into(),
})
}
Return::Ok(r) => {
info!("{prefix}");
Return::Ok(r)
}
Return::Response(r) => {
info!("{prefix} {}", r.code);
Return::Response(r)
}
}
},
Err(err) => {
error!("{prefix} parse args : {err}");
Return::Response(Response {
code: 500,
body: err.to_string().into(),
})
}
}
}};
}
pub trait Call {
type Args: std::fmt::Debug + TryFrom<Bytes>;
type Result;
fn call(args: &Self::Args) -> Return<Self::Result>;
fn log_call(prefix: impl Into<String>, name: &str, args: Bytes) -> Return<Self::Result>
where
<<Self as Call>::Args as TryFrom<bytes::Bytes>>::Error: std::fmt::Display,
{
args_try_into!(prefix, name, args,)
}
}
pub trait AsyncCall {
type Args: std::fmt::Debug + TryFrom<Bytes>;
type Result;
fn call(args: &Self::Args) -> impl Future<Output = Return<Self::Result>>;
fn log_call(
prefix: impl Into<String>,
name: &'static str,
args: Bytes,
) -> impl std::future::Future<Output = Return<Self::Result>>
where
<<Self as AsyncCall>::Args as TryFrom<bytes::Bytes>>::Error: std::fmt::Display,
{
async move { args_try_into!(prefix, name, args, .await) }
}
}