use std::sync::Arc;
use std::time::Duration;
use tokio::sync::mpsc;
use crate::download_engine::{ProgressUpdate, WorkerPool, build_job_submission};
use nzb_core::models::NzbJob;
#[async_trait::async_trait]
pub trait DispatchEngine: Send + Sync {
fn start(&self);
fn submit_job(&self, job: &NzbJob, progress_tx: mpsc::Sender<ProgressUpdate>);
fn pause_job(&self, job_id: &str);
fn resume_job(&self, job_id: &str);
fn cancel_job(&self, job_id: &str);
fn abort_job(&self, job_id: &str, reason: String);
fn has_job(&self, job_id: &str) -> bool;
fn reconcile_servers(&self);
fn set_max_worker_idle(&self, d: Duration);
fn eviction_count(&self) -> u64;
fn server_stats_snapshot(&self) -> Vec<(String, ServerAttemptStats)> {
Vec::new()
}
async fn shutdown(&self);
}
#[derive(Debug, Clone, Copy, Default)]
pub struct ServerAttemptStats {
pub attempted: u64,
pub succeeded: u64,
pub not_found: u64,
pub transient_failed: u64,
}
pub struct DispatchHandle(Arc<WorkerPool>);
impl DispatchHandle {
pub fn new(pool: Arc<WorkerPool>) -> Self {
Self(pool)
}
pub fn pool(&self) -> &Arc<WorkerPool> {
&self.0
}
}
#[async_trait::async_trait]
impl DispatchEngine for DispatchHandle {
fn start(&self) {
self.0.start();
}
fn submit_job(&self, job: &NzbJob, progress_tx: mpsc::Sender<ProgressUpdate>) {
let (ctx, items) = build_job_submission(job, progress_tx);
self.0.submit_job(ctx, items);
}
fn pause_job(&self, job_id: &str) {
self.0.pause_job(job_id);
}
fn resume_job(&self, job_id: &str) {
self.0.resume_job(job_id);
}
fn cancel_job(&self, job_id: &str) {
self.0.cancel_job(job_id);
}
fn abort_job(&self, job_id: &str, reason: String) {
self.0.abort_job(job_id, reason);
}
fn has_job(&self, job_id: &str) -> bool {
self.0.has_job(job_id)
}
fn reconcile_servers(&self) {
self.0.reconcile_servers();
}
fn set_max_worker_idle(&self, d: Duration) {
self.0.set_max_worker_idle(d);
}
fn eviction_count(&self) -> u64 {
self.0.eviction_count()
}
async fn shutdown(&self) {
self.0.shutdown().await;
}
}