Files
k-tv/k-tv-backend/api/src/main.rs

118 lines
3.4 KiB
Rust

//! API Server Entry Point
//!
//! Configures and starts the HTTP server with JWT-based authentication.
use std::sync::Arc;
use tracing::info;
use domain::{ChannelService, IProviderRegistry, ScheduleEngineService, UserService};
use infra::factory::{build_activity_log_repository, build_channel_repository, build_provider_config_repository, build_schedule_repository, build_user_repository};
#[cfg(feature = "local-files")]
use infra::factory::build_transcode_settings_repository;
mod config;
mod database;
mod provider_registry;
mod dto;
mod error;
mod events;
mod extractors;
mod log_layer;
mod poller;
mod routes;
mod scheduler;
mod server;
mod startup;
mod state;
mod telemetry;
mod webhook;
use crate::config::Config;
use crate::state::AppState;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let handles = telemetry::init_tracing();
let config = Config::from_env();
info!("Starting server on {}:{}", config.host, config.port);
// Setup database
let db_pool = database::init_database(&config).await?;
let user_repo = build_user_repository(&db_pool).await?;
let channel_repo = build_channel_repository(&db_pool).await?;
let schedule_repo = build_schedule_repository(&db_pool).await?;
let activity_log_repo = build_activity_log_repository(&db_pool).await?;
let user_service = UserService::new(user_repo);
let channel_service = ChannelService::new(channel_repo.clone());
// Build provider registry — all configured providers are registered simultaneously.
let provider_config_repo = build_provider_config_repository(&db_pool).await?;
let bundle = provider_registry::build_provider_registry(
&config, &db_pool, &provider_config_repo,
).await?;
let registry_arc = bundle.registry;
let provider_registry: Arc<tokio::sync::RwLock<Arc<infra::ProviderRegistry>>> =
Arc::new(tokio::sync::RwLock::new(Arc::clone(&registry_arc)));
let (event_tx, event_rx) = tokio::sync::broadcast::channel::<domain::DomainEvent>(64);
let bg_channel_repo = channel_repo.clone();
let webhook_channel_repo = channel_repo.clone();
tokio::spawn(webhook::run_webhook_consumer(
event_rx,
webhook_channel_repo,
reqwest::Client::new(),
));
let schedule_engine = ScheduleEngineService::new(
Arc::clone(&registry_arc) as Arc<dyn IProviderRegistry>,
channel_repo,
schedule_repo,
);
#[cfg(feature = "local-files")]
let transcode_settings_repo = build_transcode_settings_repository(&db_pool).await.ok();
#[allow(unused_mut)]
let mut state = AppState::new(
user_service,
channel_service,
schedule_engine,
provider_registry,
provider_config_repo,
config.clone(),
event_tx.clone(),
handles.log_tx,
handles.log_history,
activity_log_repo,
db_pool,
#[cfg(feature = "local-files")]
transcode_settings_repo,
)
.await?;
#[cfg(feature = "local-files")]
if let Some(idx) = bundle.local_index {
*state.local_index.write().await = Some(idx);
}
#[cfg(feature = "local-files")]
if let Some(tm) = bundle.transcode_manager {
*state.transcode_manager.write().await = Some(tm);
}
startup::spawn_background_tasks(
Arc::clone(&state.schedule_engine),
bg_channel_repo,
event_tx,
);
server::build_and_serve(state, &config).await
}