1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{ItemFn, parse_macro_input};
4
5#[proc_macro_attribute]
17pub fn workflow(_attr: TokenStream, item: TokenStream) -> TokenStream {
18 let input_fn = parse_macro_input!(item as ItemFn);
19 let fn_name = &input_fn.sig.ident;
20 let fn_name_str = fn_name.to_string();
21 let vis = &input_fn.vis;
22 let sig = &input_fn.sig;
23 let body = &input_fn.block;
24 let attrs = &input_fn.attrs;
25
26 let expanded = quote! {
27 #(#attrs)*
28 #vis #sig {
29 let _workflow_name = #fn_name_str;
30 tracing::info!(workflow = _workflow_name, "workflow started");
31 let _result: Result<_, _> = async { #body }.await;
32 match &_result {
33 Ok(_) => tracing::info!(workflow = _workflow_name, "workflow completed"),
34 Err(e) => tracing::error!(workflow = _workflow_name, error = %e, "workflow failed"),
35 }
36 _result
37 }
38 };
39
40 TokenStream::from(expanded)
41}
42
43#[proc_macro_attribute]
55pub fn step(_attr: TokenStream, item: TokenStream) -> TokenStream {
56 let input_fn = parse_macro_input!(item as ItemFn);
57 let fn_name = &input_fn.sig.ident;
58 let fn_name_str = fn_name.to_string();
59 let vis = &input_fn.vis;
60 let sig = &input_fn.sig;
61 let body = &input_fn.block;
62 let attrs = &input_fn.attrs;
63
64 let expanded = quote! {
65 #(#attrs)*
66 #vis #sig {
67 let _step_name = #fn_name_str;
68 tracing::debug!(step = _step_name, "step executing");
69 let _result: Result<_, _> = async { #body }.await;
70 match &_result {
71 Ok(_) => tracing::debug!(step = _step_name, "step completed"),
72 Err(e) => tracing::warn!(step = _step_name, error = %e, "step failed"),
73 }
74 _result
75 }
76 };
77
78 TokenStream::from(expanded)
79}