1use proc_macro::TokenStream;
2use quote::quote;
3use syn::{parse_macro_input, punctuated::Punctuated, Lit, Token, ItemFn};
4use syn::parse::Parser;
5
6#[proc_macro_attribute]
7pub fn cron(attr: TokenStream, item: TokenStream) -> TokenStream {
8 let args = Punctuated::<Lit, Token![,]>::parse_terminated
9 .parse(attr)
10 .expect("Failed to parse attribute args");
11
12 let input = parse_macro_input!(item as ItemFn);
13 let fn_name = &input.sig.ident;
14
15 let pattern = if let Some(Lit::Str(lit_str)) = args.first() {
16 lit_str.value()
17 } else {
18 panic!("Expected a string literal with a cron expression inside #[cron(\"...\")]");
19 };
20
21 croner::Cron::new(&pattern)
22 .with_seconds_optional()
23 .parse()
24 .expect("It doesn't seem to be a valid cron expression");
25
26 let result = quote! {
27 #input
28
29 relayr::inventory::submit! {
30 relayr::Cron { pattern: #pattern, runnable: |job_id| Box::pin(#fn_name(job_id)), name: stringify!(#fn_name) }
31 }
32 };
33
34 result.into()
35}