use crate::{clock::ClockHandle, db};
use super::{AtomicOperation, hooks};
pub trait AtomicOperationWithTime: AtomicOperation {
fn now(&self) -> chrono::DateTime<chrono::Utc>;
}
pub struct OpWithTime<'a, Op: AtomicOperation + ?Sized> {
inner: &'a mut Op,
now: chrono::DateTime<chrono::Utc>,
}
impl<'a, Op: AtomicOperation + ?Sized> AtomicOperationWithTime for OpWithTime<'a, Op> {
fn now(&self) -> chrono::DateTime<chrono::Utc> {
self.now
}
}
impl<'a, Op: AtomicOperation + ?Sized> OpWithTime<'a, Op> {
pub async fn cached_or_db_time(op: &'a mut Op) -> Result<Self, sqlx::Error> {
let now = if let Some(time) = op.maybe_now() {
time
} else if let Some(manual_time) = op.clock().manual_now() {
manual_time
} else {
db::database_now(op.as_executor()).await?
};
Ok(Self { inner: op, now })
}
pub fn cached_or_time(op: &'a mut Op, time: chrono::DateTime<chrono::Utc>) -> Self {
let now = op.maybe_now().unwrap_or(time);
Self { inner: op, now }
}
pub fn cached_or_clock_time(op: &'a mut Op) -> Self {
let now = op.maybe_now().unwrap_or_else(|| op.clock().now());
Self { inner: op, now }
}
pub fn now(&self) -> chrono::DateTime<chrono::Utc> {
self.now
}
}
impl<'a, Op: AtomicOperation + ?Sized> AtomicOperation for OpWithTime<'a, Op> {
fn maybe_now(&self) -> Option<chrono::DateTime<chrono::Utc>> {
Some(self.now)
}
fn clock(&self) -> &ClockHandle {
self.inner.clock()
}
fn as_executor(&mut self) -> &mut db::Connection {
self.inner.as_executor()
}
fn add_commit_hook<H: hooks::CommitHook>(&mut self, hook: H) -> Result<(), H> {
self.inner.add_commit_hook(hook)
}
}