use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, ItemFn};
pub fn impl_atomic(args: TokenStream, input: TokenStream) -> TokenStream {
let func = parse_macro_input!(input as ItemFn);
let db_arg_name = parse_macro_input!(args as syn::Ident);
let func_vis = &func.vis;
let func_sig = &func.sig;
let func_block = &func.block;
let func_attrs = &func.attrs;
if func.sig.asyncness.is_none() {
return syn::Error::new_spanned(
func.sig.fn_token,
"#[atomic] can only be used on async functions",
)
.to_compile_error()
.into();
}
let expanded = quote! {
#(#func_attrs)*
#func_vis #func_sig {
use sea_orm::TransactionTrait;
let __txn = #db_arg_name.begin().await?;
let __result: Result<_, ormada::error::OrmadaOrmError> = async {
let #db_arg_name = &__txn;
#func_block
}.await;
match __result {
Ok(__value) => {
__txn.commit().await?;
Ok(__value)
}
Err(__err) => {
let _ = __txn.rollback().await;
Err(__err)
}
}
}
};
TokenStream::from(expanded)
}