feat(channel): add auto-schedule feature to channels with background scheduler
This commit is contained in:
76
k-tv-backend/api/src/scheduler.rs
Normal file
76
k-tv-backend/api/src/scheduler.rs
Normal file
@@ -0,0 +1,76 @@
|
||||
//! Background auto-scheduler task.
|
||||
//!
|
||||
//! Runs every hour, finds channels with `auto_schedule = true`, and regenerates
|
||||
//! their schedule if it is within 24 hours of expiry (or already expired).
|
||||
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use chrono::Utc;
|
||||
use domain::{ChannelRepository, ScheduleEngineService};
|
||||
|
||||
pub async fn run_auto_scheduler(
|
||||
schedule_engine: Arc<ScheduleEngineService>,
|
||||
channel_repo: Arc<dyn ChannelRepository>,
|
||||
) {
|
||||
loop {
|
||||
tokio::time::sleep(Duration::from_secs(3600)).await;
|
||||
tick(&schedule_engine, &channel_repo).await;
|
||||
}
|
||||
}
|
||||
|
||||
async fn tick(
|
||||
schedule_engine: &Arc<ScheduleEngineService>,
|
||||
channel_repo: &Arc<dyn ChannelRepository>,
|
||||
) {
|
||||
let channels = match channel_repo.find_auto_schedule_enabled().await {
|
||||
Ok(c) => c,
|
||||
Err(e) => {
|
||||
tracing::warn!("auto-scheduler: failed to fetch channels: {}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let now = Utc::now();
|
||||
|
||||
for channel in channels {
|
||||
let from = match schedule_engine.get_latest_schedule(channel.id).await {
|
||||
Ok(Some(s)) => {
|
||||
let remaining = s.valid_until - now;
|
||||
if remaining > chrono::Duration::hours(24) {
|
||||
// Still fresh — skip until it gets close to expiry
|
||||
continue;
|
||||
} else if s.valid_until > now {
|
||||
// Seamless handoff: new schedule starts where the old one ends
|
||||
s.valid_until
|
||||
} else {
|
||||
// Expired: start from now to avoid scheduling in the past
|
||||
now
|
||||
}
|
||||
}
|
||||
Ok(None) => now,
|
||||
Err(e) => {
|
||||
tracing::warn!(
|
||||
"auto-scheduler: failed to fetch latest schedule for channel {}: {}",
|
||||
channel.id,
|
||||
e
|
||||
);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
if let Err(e) = schedule_engine.generate_schedule(channel.id, from).await {
|
||||
tracing::warn!(
|
||||
"auto-scheduler: failed to generate schedule for channel {}: {}",
|
||||
channel.id,
|
||||
e
|
||||
);
|
||||
} else {
|
||||
tracing::info!(
|
||||
"auto-scheduler: generated schedule for channel {} starting at {}",
|
||||
channel.id,
|
||||
from
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user