use serde_json::Value;
use crate::Result;
use crate::future::BoxedFuture;
use crate::lock::Lock;
use crate::opts::{QueueOpts, ScheduleOpts};
use crate::outbox::Outbox;
use crate::queue::Queue;
use crate::schedule::Schedule;
use crate::stop_token::StopToken;
use crate::stream_handle::StreamHandle;
use crate::tx::TxHandle;
use crate::wake_receiver::WakeReceiver;
pub type WithTxClosure<'a> =
Box<dyn FnOnce(&mut dyn TxHandle) -> BoxedFuture<'_, Result<()>> + Send + 'a>;
pub trait Store: Send + Sync {
fn begin_tx(&self) -> BoxedFuture<'_, Result<Box<dyn TxHandle + Send>>>;
fn notify<'a>(&'a self, channel: &str, payload: Value) -> BoxedFuture<'a, Result<()>>;
fn listen<'a>(&'a self, channel: &str) -> BoxedFuture<'a, Result<Box<dyn WakeReceiver>>>;
fn stream<'a>(&'a self, name: &str) -> BoxedFuture<'a, Result<Box<dyn StreamHandle>>>;
fn queue<'a>(&'a self, name: &str, opts: QueueOpts) -> BoxedFuture<'a, Result<Box<dyn Queue>>>;
fn outbox<'a>(&'a self, name: &str) -> BoxedFuture<'a, Result<Box<dyn Outbox>>>;
fn try_lock<'a>(
&'a self,
name: &str,
owner: &str,
ttl: i64,
) -> BoxedFuture<'a, Result<Option<Box<dyn Lock>>>>;
fn schedule<'a>(
&'a self,
name: &str,
spec: &str,
queue: &str,
payload: Value,
opts: ScheduleOpts,
) -> BoxedFuture<'a, Result<Schedule>>;
fn unschedule<'a>(&'a self, name: &str) -> BoxedFuture<'a, Result<bool>>;
fn run_schedules<'a>(&'a self, stop: StopToken) -> BoxedFuture<'a, Result<()>>;
fn with_tx<'a>(&'a self, f: WithTxClosure<'a>) -> BoxedFuture<'a, Result<()>> {
Box::pin(async move {
let mut handle = self.begin_tx().await?;
match Box::pin(f(&mut *handle)).await {
Ok(()) => handle.commit().await,
Err(e) => {
drop(handle);
Err(e)
}
}
})
}
}