gitdataai/apps/email/src/main.rs
2026-04-15 09:08:09 +08:00

85 lines
2.4 KiB
Rust

use clap::Parser;
use config::AppConfig;
use service::AppService;
use slog::{Drain, OwnedKVList, Record};
#[derive(Parser, Debug)]
#[command(name = "email-worker")]
#[command(version)]
struct Args {
#[arg(long, default_value = "info")]
log_level: String,
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let args = Args::parse();
let cfg = AppConfig::load();
let log = build_logger(&args.log_level);
slog::info!(log, "Starting email worker");
let service = AppService::new(cfg).await?;
let (shutdown_tx, shutdown_rx) = tokio::sync::broadcast::channel::<()>(1);
let log_for_signal = log.clone();
tokio::spawn(async move {
tokio::signal::ctrl_c().await.ok();
slog::info!(log_for_signal, "shutting down email worker");
let _ = shutdown_tx.send(());
});
service.start_email_workers(shutdown_rx).await?;
slog::info!(log, "email worker stopped");
Ok(())
}
fn build_logger(level: &str) -> slog::Logger {
let level_filter = match level {
"trace" => 0usize,
"debug" => 1usize,
"info" => 2usize,
"warn" => 3usize,
"error" => 4usize,
_ => 2usize,
};
struct StderrDrain(usize);
impl Drain for StderrDrain {
type Ok = ();
type Err = ();
#[inline]
fn log(&self, record: &Record, _logger: &OwnedKVList) -> Result<(), ()> {
let slog_level = match record.level() {
slog::Level::Trace => 0,
slog::Level::Debug => 1,
slog::Level::Info => 2,
slog::Level::Warning => 3,
slog::Level::Error => 4,
slog::Level::Critical => 5,
};
if slog_level < self.0 {
return Ok(());
}
let _ = eprintln!(
"{} [{}] {}:{} - {}",
chrono::Utc::now().format("%Y-%m-%dT%H:%M:%S%.3fZ"),
record.level().to_string(),
record
.file()
.rsplit_once('/')
.map(|(_, s)| s)
.unwrap_or(record.file()),
record.line(),
record.msg(),
);
Ok(())
}
}
let drain = StderrDrain(level_filter);
let drain = std::sync::Mutex::new(drain);
let drain = slog::Fuse::new(drain);
slog::Logger::root(drain, slog::o!())
}