use proc_macro2::TokenStream;
use quote::quote;
use syn::parse::{Parse, ParseStream};
use syn::{Block, Token};
pub(super) struct WatchCfgFileArgs {
title: String,
reload_block: Block,
}
impl Parse for WatchCfgFileArgs {
fn parse(input: ParseStream) -> syn::Result<Self> {
let title = input.parse::<syn::LitStr>()?.value();
let _: Token![,] = input.parse()?;
let reload_block = input.parse()?;
Ok(WatchCfgFileArgs {
title,
reload_block,
})
}
}
pub(super) fn watch_cfg_file_macro(args: WatchCfgFileArgs) -> TokenStream {
let WatchCfgFileArgs {
title,
reload_block,
} = args;
let reload_block = &reload_block.stmts;
let expanded = quote! {
debug!("watch {} cfg file...", #title);
tokio::spawn({
async move {
let (_watcher, receiver) = watch_cfg_file(files).expect(&format!("watch {} cfg file error", #title));
let mut interval = interval(Duration::from_secs(1));
loop {
interval.tick().await;
match receiver.try_recv() {
Ok(event_result) => {
match event_result {
Ok(events) => {
for event in events {
debug!("{} cfg file change event: {:?}", #title, event);
}
debug!("reload from {} cfg file...", #title);
#( #reload_block )*
}
Err(e) => {
warn!("error receiving {} cfg file events: {:?}", #title, e);
}
}
}
Err(mpsc::TryRecvError::Empty) => {
continue;
}
Err(mpsc::TryRecvError::Disconnected) => {
debug!("{} cfg file watcher channel closed, exiting watcher loop", #title);
break;
}
}
}
debug!("{} cfg file watcher task finished", #title);
}
});
};
TokenStream::from(expanded)
}