diff --git a/src/main.rs b/src/main.rs index 064e7de..6f5248a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -40,12 +40,13 @@ use logger::Logger; use notify::{Notification, Notifier}; lazy_static! { - // Tracks whether or not the .env file has been loaded. + // Tracks whether or not the environment variables have been loaded from the .env file. static ref LOADED_ENV_FILE: AtomicBool = AtomicBool::new(false); } -/// Attempts to load the .env file one time at the start of the main process or at the start of the -/// tests. Panics if the .env file cannot be found or parsed. +/// Attempts to load the .env file once at the start of the main process or at the start of the +/// tests. Panics if the .env file cannot be found or if it cannot be parsed (most likely it +/// contains invalid UTF-8 bytes). fn load_env_file() { if !LOADED_ENV_FILE.load(Ordering::Relaxed) { match dotenv::dotenv() { @@ -57,9 +58,9 @@ fn load_env_file() { } /// Sets up ctrl-c to change the value of `poagov_is_running` from `true` to `false`. When -/// `poagov_is_running` changes to `false`, the process of gracefully shutting down begins. The -/// `AtomicBool` returned by this function is used to indicate whether or not the `poagov` binary -/// should continue running. +/// `poagov_is_running` changes to `false`, the `poagov` process begins to gracefully shut down. +/// The `AtomicBool` returned by this function is used to indicate whether or not the `poagov` +/// binary should continue running. fn set_ctrlc_handler(logger: Arc>) -> Result> { let poagov_is_running = Arc::new(AtomicBool::new(true)); let setup_res = { @@ -82,21 +83,25 @@ fn main() -> Result<()> { let cli = parse_cli(); let config = Config::new(&cli)?; let logger = Arc::new(Mutex::new(Logger::new(&config))); + let running = set_ctrlc_handler(logger.clone())?; + let client = RpcClient::new(config.endpoint.clone()); + let blockchain_iter = BlockchainIter::new(&client, &config, running)?; + let mut notifier = Notifier::new(&config, logger.clone())?; // If email notifications have been enabled but there are no email recipients configured, warn // the user. if config.email_notifications && config.email_recipients.is_empty() { logger.lock().unwrap().log_no_email_recipients_configured(); } - - let running = set_ctrlc_handler(logger.clone())?; - let client = RpcClient::new(config.endpoint.clone()); - let mut notifier = Notifier::new(&config, logger.clone())?; logger.lock().unwrap().log_starting_poagov(); - 'main_loop: for iter_res in BlockchainIter::new(&client, &config, running)? { - let (start_block, stop_block) = iter_res?; + 'blockchain_walker: for block_range_res in blockchain_iter { + let (start_block, stop_block) = block_range_res?; let mut notifications = vec![]; + + // For each contract that we are monitoring for governance events, get the ballot-created + // events that fall within the current `BlockchainIter`'s block window, convert those + // ballot-created logs to `Notification`s. for contract in config.contracts.iter() { let ballot_created_logs = client.get_ballot_created_logs( contract, @@ -114,17 +119,22 @@ fn main() -> Result<()> { notifications.push(notification); } } + + // Sort the notifications by ascending block number. notifications.sort_unstable_by(|notif1, notif2| { notif1.log().block_number.cmp(¬if2.log().block_number) }); - for notification in notifications.iter() { - notifier.notify(notification); + + // Notify the governance notifications recipients. + for notification in notifications { + notifier.notify(¬ification); if notifier.reached_limit() { let limit = config.notification_limit.unwrap(); logger.lock().unwrap().log_reached_notification_limit(limit); - break 'main_loop; + break 'blockchain_walker; } } + logger.lock().unwrap().log_finished_block_window(start_block, stop_block); }