use std::marker::PhantomData;
use std::sync::Arc;
use crate::ids::CommandId;
pub trait CompletionSink: Send + Sync {
fn complete(&self, cmd_id: CommandId, result_bytes: &[u8]);
fn fail(&self, cmd_id: CommandId, detail: &str);
}
pub struct CompletionHandle<R, E> {
cmd_id: CommandId,
sink: Arc<dyn CompletionSink>,
_marker: PhantomData<fn() -> (R, E)>,
}
impl<R, E> CompletionHandle<R, E> {
pub fn new(cmd_id: CommandId, sink: Arc<dyn CompletionSink>) -> Self {
Self {
cmd_id,
sink,
_marker: PhantomData,
}
}
pub fn cmd_id(&self) -> CommandId {
self.cmd_id
}
}
impl<R, E> CompletionHandle<R, E>
where
R: serde::Serialize,
E: std::fmt::Display,
{
pub fn complete(self, result: Result<R, E>) {
match result {
Ok(value) => {
let bytes = bincode::serialize(&value).unwrap_or_default();
self.sink.complete(self.cmd_id, &bytes);
}
Err(e) => {
let detail = e.to_string();
self.sink.fail(self.cmd_id, &detail);
}
}
}
}
pub enum ContractResponse<R, E> {
Now(Result<R, E>),
Later,
}