lib.rs (2897B)
1 /* 2 This file is part of TALER 3 Copyright (C) 2024-2025 Taler Systems SA 4 5 TALER is free software; you can redistribute it and/or modify it under the 6 terms of the GNU Affero General Public License as published by the Free Software 7 Foundation; either version 3, or (at your option) any later version. 8 9 TALER is distributed in the hope that it will be useful, but WITHOUT ANY 10 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 11 A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. 12 13 You should have received a copy of the GNU Affero General Public License along with 14 TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/> 15 */ 16 17 use std::{future::Future, path::PathBuf, time::Duration}; 18 19 use config::{Config, parser::ConfigSource}; 20 use tracing::error; 21 use tracing_subscriber::util::SubscriberInitExt; 22 23 use crate::log::taler_logger; 24 25 pub mod api_common; 26 pub mod api_params; 27 pub mod api_revenue; 28 pub mod api_wire; 29 pub mod cli; 30 pub mod config; 31 pub mod db; 32 pub mod error; 33 pub mod error_code; 34 pub mod json_file; 35 pub mod log; 36 pub mod types; 37 38 #[derive(clap::Parser, Debug, Clone)] 39 pub struct CommonArgs { 40 /// Specifies the configuration file 41 #[clap(long, short)] 42 #[arg(global = true)] 43 config: Option<PathBuf>, 44 45 /// Configure logging to use LOGLEVEL 46 #[clap(long, short('L'))] 47 #[arg(global = true)] 48 log: Option<tracing::Level>, 49 } 50 51 pub fn taler_main<F: Future<Output = Result<(), anyhow::Error>>>( 52 src: ConfigSource, 53 args: CommonArgs, 54 app: impl FnOnce(Config) -> F, 55 ) { 56 taler_logger(args.log).init(); 57 let cfg = match Config::from_file(src, args.config) { 58 Ok(cfg) => cfg, 59 Err(err) => { 60 error!(target: "config", "{}", err); 61 std::process::exit(1); 62 } 63 }; 64 65 // Setup async runtime 66 let runtime = tokio::runtime::Builder::new_multi_thread() 67 .enable_all() 68 .build() 69 .unwrap(); 70 71 // Run app 72 let result = runtime.block_on(app(cfg)); 73 if let Err(err) = result { 74 error!(target: "cli", "{}", err); 75 std::process::exit(1); 76 } 77 } 78 79 /// Infinite exponential backoff with decorrelated jitter 80 pub struct ExpoBackoffDecorr { 81 base: u32, 82 max: u32, 83 factor: f32, 84 sleep: u32, 85 } 86 87 impl ExpoBackoffDecorr { 88 pub fn new(base: u32, max: u32, factor: f32) -> Self { 89 Self { 90 base, 91 max, 92 factor, 93 sleep: base, 94 } 95 } 96 97 pub fn backoff(&mut self) -> Duration { 98 self.sleep = 99 fastrand::u32(self.base..(self.sleep as f32 * self.factor) as u32).min(self.max); 100 Duration::from_millis(self.sleep as u64) 101 } 102 103 pub fn reset(&mut self) { 104 self.sleep = self.base 105 } 106 } 107 108 impl Default for ExpoBackoffDecorr { 109 fn default() -> Self { 110 Self::new(200, 15 * 1000, 2.0) 111 } 112 }