|
|
|
@ -1,6 +1,7 @@ |
|
|
|
|
use crate::domain::{self, acme, checker, config}; |
|
|
|
|
use crate::error::unexpected::{self, Mappable}; |
|
|
|
|
use crate::origin; |
|
|
|
|
use crate::util; |
|
|
|
|
|
|
|
|
|
use std::{future, pin, sync}; |
|
|
|
|
use tokio_util::sync::CancellationToken; |
|
|
|
@ -144,70 +145,56 @@ pub trait Manager: Sync + Send { |
|
|
|
|
fn all_domains(&self) -> Result<Vec<domain::Name>, unexpected::Error>; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub struct ManagerImpl { |
|
|
|
|
struct ManagerImpl { |
|
|
|
|
origin_store: sync::Arc<dyn origin::store::Store>, |
|
|
|
|
domain_config_store: sync::Arc<dyn config::Store>, |
|
|
|
|
domain_checker: checker::DNSChecker, |
|
|
|
|
acme_manager: Option<sync::Arc<dyn acme::manager::Manager>>, |
|
|
|
|
|
|
|
|
|
canceller: CancellationToken, |
|
|
|
|
origin_sync_handler: tokio::task::JoinHandle<()>, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn sync_origins(origin_store: &dyn origin::store::Store) { |
|
|
|
|
match origin_store.all_descrs() { |
|
|
|
|
Ok(iter) => iter.into_iter(), |
|
|
|
|
Err(err) => { |
|
|
|
|
log::error!("Error fetching origin descriptors: {err}"); |
|
|
|
|
return; |
|
|
|
|
async fn sync_origins(origin_store: &dyn origin::store::Store, canceller: CancellationToken) { |
|
|
|
|
let mut interval = tokio::time::interval(tokio::time::Duration::from_secs(20 * 60)); |
|
|
|
|
loop { |
|
|
|
|
tokio::select! { |
|
|
|
|
_ = interval.tick() => { |
|
|
|
|
|
|
|
|
|
match origin_store.all_descrs() { |
|
|
|
|
Ok(iter) => iter.into_iter(), |
|
|
|
|
Err(err) => { |
|
|
|
|
log::error!("Error fetching origin descriptors: {err}"); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
.for_each(|descr| { |
|
|
|
|
if let Err(err) = origin_store.sync(descr.clone(), origin::store::Limits {}) { |
|
|
|
|
log::error!("Failed to sync store for {:?}: {err}", descr); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
}, |
|
|
|
|
_ = canceller.cancelled() => return, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
.for_each(|descr| { |
|
|
|
|
if let Err(err) = origin_store.sync(descr.clone(), origin::store::Limits {}) { |
|
|
|
|
log::error!("Failed to sync store for {:?}: {err}", descr); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub fn new( |
|
|
|
|
task_stack: &mut util::TaskStack<unexpected::Error>, |
|
|
|
|
origin_store: sync::Arc<dyn origin::store::Store>, |
|
|
|
|
domain_config_store: sync::Arc<dyn config::Store>, |
|
|
|
|
domain_checker: checker::DNSChecker, |
|
|
|
|
acme_manager: Option<sync::Arc<dyn acme::manager::Manager>>, |
|
|
|
|
) -> ManagerImpl { |
|
|
|
|
let canceller = CancellationToken::new(); |
|
|
|
|
|
|
|
|
|
let origin_sync_handler = { |
|
|
|
|
) -> sync::Arc<dyn Manager> { |
|
|
|
|
task_stack.spawn(|canceller| { |
|
|
|
|
let origin_store = origin_store.clone(); |
|
|
|
|
let canceller = canceller.clone(); |
|
|
|
|
tokio::spawn(async move { |
|
|
|
|
let mut interval = tokio::time::interval(tokio::time::Duration::from_secs(20 * 60)); |
|
|
|
|
|
|
|
|
|
loop { |
|
|
|
|
tokio::select! { |
|
|
|
|
_ = interval.tick() => sync_origins(origin_store.as_ref()), |
|
|
|
|
_ = canceller.cancelled() => return, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
}; |
|
|
|
|
async move { Ok(sync_origins(origin_store.as_ref(), canceller).await) } |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
ManagerImpl { |
|
|
|
|
sync::Arc::new(ManagerImpl { |
|
|
|
|
origin_store, |
|
|
|
|
domain_config_store, |
|
|
|
|
domain_checker, |
|
|
|
|
acme_manager, |
|
|
|
|
canceller, |
|
|
|
|
origin_sync_handler, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl ManagerImpl { |
|
|
|
|
pub fn stop(self) -> tokio::task::JoinHandle<()> { |
|
|
|
|
self.canceller.cancel(); |
|
|
|
|
self.origin_sync_handler |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl Manager for ManagerImpl { |
|
|
|
|