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.connection()).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 connection(&mut self) -> &mut db::Connection {
self.inner.connection()
}
fn add_commit_hook_dyn(
&mut self,
type_id: std::any::TypeId,
hook: Box<dyn hooks::DynHook>,
) -> Result<(), Box<dyn hooks::DynHook>> {
self.inner.add_commit_hook_dyn(type_id, hook)
}
fn commit_hook_dyn(&self, type_id: std::any::TypeId) -> Option<&dyn hooks::DynHook> {
self.inner.commit_hook_dyn(type_id)
}
fn supports_hooks(&self) -> bool {
self.inner.supports_hooks()
}
fn savepoint_parts(&mut self) -> (&mut db::Connection, super::savepoint::HookSlot<'_>) {
self.inner.savepoint_parts()
}
}