lazy-settings-macros 0.4.0

Application settings created lazily and in a distributed manner.
Documentation
extern crate proc_macro;
#[macro_use]
extern crate quote;
extern crate syn;

use proc_macro::TokenStream;

use darling::FromMeta;
use syn::parse_macro_input;

#[derive(Debug, FromMeta)]
struct Args {
    key: String,
}

#[proc_macro_attribute]
pub fn settings(metadata: TokenStream, input: TokenStream) -> TokenStream {
    let input_struct = parse_macro_input!(input as syn::ItemStruct);
    let attr_args = parse_macro_input!(metadata as syn::AttributeArgs);
    let args = Args::from_list(&attr_args).unwrap();
    let struct_ident = input_struct.ident.clone();
    let key = args.key.clone();
    let uppercase_key = key.to_uppercase();
    TokenStream::from(quote! {
        #[derive(Debug, Clone, ::lazy_settings::serde::Deserialize, ::lazy_settings::getset_scoped::Getters)]
        #[get]
        #input_struct

        impl #struct_ident {
            pub fn get(instance_name: &str) -> Result<Self, ::lazy_settings::eyre::Report> {
                static SINGLETON: ::lazy_settings::once_cell::sync::Lazy<::lazy_settings::parking_lot::RwLock<::std::collections::HashMap<String, #struct_ident>>> = ::once_cell::sync::Lazy::new(|| ::lazy_settings::parking_lot::RwLock::new(::std::collections::HashMap::default()));
                {
                    let singleton_ro = SINGLETON.read();
                    if let Some(existing_settings) = singleton_ro.get(instance_name) {
                        return Ok(existing_settings.clone())
                    }
                }
                {
                    let new_settings = ::lazy_settings::config::Config::builder()
                        .add_source(::lazy_settings::config::Environment::with_prefix(
                            format!("APP_{}_{}", #uppercase_key, instance_name.to_uppercase()).as_str(),
                        ))
                        .build()?;
                    eprintln!("Initializing {} settings, instance name: {}", #key, instance_name);
                    let new_settings: #struct_ident = ::lazy_settings::eyre::WrapErr::wrap_err(new_settings.try_deserialize(), "Cannot read settings.")?;
                    let mut singleton_rw = SINGLETON.write();
                    singleton_rw.insert(instance_name.to_string(), new_settings.clone());
                    return Ok(new_settings)
                }
            }
        }
    })
}