mirror of
https://github.com/CloudNebulaProject/webfingerd.git
synced 2026-04-10 13:10:41 +00:00
feat: finalize main.rs with graceful shutdown and full wiring
This commit is contained in:
parent
244397274c
commit
1ca65df43d
2 changed files with 92 additions and 0 deletions
|
|
@ -35,6 +35,7 @@ base64 = "0.22"
|
||||||
thiserror = "2"
|
thiserror = "2"
|
||||||
urlencoding = "2"
|
urlencoding = "2"
|
||||||
async-trait = "0.1"
|
async-trait = "0.1"
|
||||||
|
migration = { path = "migration" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
axum-test = "20"
|
axum-test = "20"
|
||||||
|
|
|
||||||
91
src/main.rs
91
src/main.rs
|
|
@ -1,13 +1,104 @@
|
||||||
|
use axum_extra::extract::cookie::Key;
|
||||||
|
use metrics_exporter_prometheus::PrometheusBuilder;
|
||||||
|
use sea_orm::{ConnectOptions, ConnectionTrait, Database, Statement};
|
||||||
|
use sea_orm_migration::MigratorTrait;
|
||||||
|
use std::sync::Arc;
|
||||||
use tracing_subscriber::{fmt, EnvFilter};
|
use tracing_subscriber::{fmt, EnvFilter};
|
||||||
|
|
||||||
|
use webfingerd::cache::Cache;
|
||||||
|
use webfingerd::challenge::RealChallengeVerifier;
|
||||||
use webfingerd::config::Settings;
|
use webfingerd::config::Settings;
|
||||||
|
use webfingerd::handler;
|
||||||
|
use webfingerd::reaper;
|
||||||
|
use webfingerd::state::AppState;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
|
// Structured JSON logging with env filter
|
||||||
fmt()
|
fmt()
|
||||||
.with_env_filter(EnvFilter::from_default_env())
|
.with_env_filter(EnvFilter::from_default_env())
|
||||||
.json()
|
.json()
|
||||||
.init();
|
.init();
|
||||||
|
|
||||||
|
// Load configuration
|
||||||
let settings = Settings::load().expect("failed to load configuration");
|
let settings = Settings::load().expect("failed to load configuration");
|
||||||
tracing::info!(listen = %settings.server.listen, "starting webfingerd");
|
tracing::info!(listen = %settings.server.listen, "starting webfingerd");
|
||||||
|
|
||||||
|
// Connect to database
|
||||||
|
let db_url = format!("sqlite://{}?mode=rwc", settings.database.path);
|
||||||
|
let opt = ConnectOptions::new(&db_url);
|
||||||
|
let db = Database::connect(opt)
|
||||||
|
.await
|
||||||
|
.expect("failed to connect to database");
|
||||||
|
|
||||||
|
// Enable WAL mode for better concurrent read performance
|
||||||
|
if settings.database.wal_mode {
|
||||||
|
db.execute(Statement::from_string(
|
||||||
|
sea_orm::DatabaseBackend::Sqlite,
|
||||||
|
"PRAGMA journal_mode=WAL".to_string(),
|
||||||
|
))
|
||||||
|
.await
|
||||||
|
.expect("failed to set WAL mode");
|
||||||
|
tracing::info!("SQLite WAL mode enabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run migrations
|
||||||
|
migration::Migrator::up(&db, None)
|
||||||
|
.await
|
||||||
|
.expect("failed to run migrations");
|
||||||
|
tracing::info!("database migrations applied");
|
||||||
|
|
||||||
|
// Hydrate cache from database
|
||||||
|
let cache = Cache::new();
|
||||||
|
cache
|
||||||
|
.hydrate(&db)
|
||||||
|
.await
|
||||||
|
.expect("failed to hydrate cache");
|
||||||
|
tracing::info!("cache hydrated");
|
||||||
|
|
||||||
|
// Install Prometheus metrics recorder
|
||||||
|
let metrics_handle = PrometheusBuilder::new()
|
||||||
|
.install_recorder()
|
||||||
|
.expect("failed to install metrics recorder");
|
||||||
|
|
||||||
|
// Derive cookie signing key from session secret
|
||||||
|
let cookie_key = Key::from(settings.ui.session_secret.as_bytes());
|
||||||
|
|
||||||
|
// Spawn background reaper for expired links
|
||||||
|
reaper::spawn_reaper(
|
||||||
|
db.clone(),
|
||||||
|
cache.clone(),
|
||||||
|
settings.cache.reaper_interval_secs,
|
||||||
|
);
|
||||||
|
tracing::info!(
|
||||||
|
interval_secs = settings.cache.reaper_interval_secs,
|
||||||
|
"reaper task spawned"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Build application state
|
||||||
|
let state = AppState {
|
||||||
|
db,
|
||||||
|
cache,
|
||||||
|
settings: Arc::new(settings.clone()),
|
||||||
|
challenge_verifier: Arc::new(RealChallengeVerifier),
|
||||||
|
metrics_handle,
|
||||||
|
cookie_key,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Build router
|
||||||
|
let app = handler::router(state);
|
||||||
|
|
||||||
|
// Bind and serve with graceful shutdown
|
||||||
|
let listener = tokio::net::TcpListener::bind(&settings.server.listen)
|
||||||
|
.await
|
||||||
|
.expect("failed to bind");
|
||||||
|
tracing::info!(listen = %settings.server.listen, "webfingerd started");
|
||||||
|
|
||||||
|
axum::serve(listener, app)
|
||||||
|
.with_graceful_shutdown(async {
|
||||||
|
tokio::signal::ctrl_c().await.ok();
|
||||||
|
tracing::info!("shutting down");
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.expect("server error");
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue