use arc_swap::ArcSwap;
use bytes::Bytes;
use http::HeaderValue;
use once_cell::sync::Lazy;
use std::sync::Arc;
use std::time::Duration;
mod date_service_decorator;
pub use date_service_decorator::DateServiceDecorator;
#[derive(Debug)]
pub struct DateService {
current: Arc<ArcSwap<Bytes>>,
handle: tokio::task::JoinHandle<()>,
}
static DATE_SERVICE: Lazy<DateService> = Lazy::new(|| DateService::new_with_update_interval(Duration::from_millis(800)));
impl DateService {
pub fn get_global_instance() -> &'static DateService {
&DATE_SERVICE
}
fn new_with_update_interval(update_interval: Duration) -> Self {
let mut buf = faf_http_date::get_date_buff_no_key();
faf_http_date::get_date_no_key(&mut buf);
let bytes = Bytes::from_owner(buf);
let current = Arc::new(ArcSwap::from_pointee(bytes));
let current_arc = Arc::clone(¤t);
let handle = tokio::spawn(async move {
loop {
tokio::time::sleep(update_interval).await;
let mut buf = faf_http_date::get_date_buff_no_key();
faf_http_date::get_date_no_key(&mut buf);
let bytes = Bytes::from_owner(buf);
current_arc.store(Arc::new(bytes));
}
});
DateService { current, handle }
}
pub(crate) fn with_http_date<F>(&self, mut f: F)
where
F: FnMut(HeaderValue),
{
let date = self.current.load().as_ref().clone();
let header_value = unsafe { HeaderValue::from_maybe_shared_unchecked(date) };
f(header_value)
}
}
impl Drop for DateService {
fn drop(&mut self) {
self.handle.abort();
}
}