use crate::error::AtmError;
use crate::graft::AdvisoryStreamRequest;
use crate::protocol::{FramePayload, RequestEnvelope, RequestId, ResponseEnvelope};
pub use crate::protocol::{
NotificationEvent, ReconcileRequest, ReconcileResult, RuntimeStatusSnapshot, WatchEventBatch,
WatchSubscriptionRequest,
};
use serde::{Deserialize, Serialize};
use std::fmt;
use std::str::FromStr;
#[doc(hidden)]
pub mod sealed {
pub trait Sealed {}
}
mod mail;
mod store;
pub use mail::*;
pub use store::*;
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[serde(transparent)]
pub struct MessageKey(String);
impl MessageKey {
pub fn new(value: impl Into<String>) -> Result<Self, AtmError> {
let value = value.into();
if value.trim().is_empty() {
return Err(
AtmError::validation("message key must not be blank").with_recovery(
"Populate a stable ATM message key before calling the Phase R boundary.",
),
);
}
Ok(Self(value))
}
}
impl AsRef<str> for MessageKey {
fn as_ref(&self) -> &str {
&self.0
}
}
impl fmt::Display for MessageKey {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_ref())
}
}
impl FromStr for MessageKey {
type Err = AtmError;
fn from_str(value: &str) -> Result<Self, Self::Err> {
Self::new(value)
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[serde(transparent)]
pub struct TaskState(String);
impl TaskState {
pub fn new(value: impl Into<String>) -> Result<Self, AtmError> {
let value = value.into();
if value.trim().is_empty() {
return Err(
AtmError::validation("task state must not be blank").with_recovery(
"Populate a non-empty task state before calling the Phase R boundary.",
),
);
}
Ok(Self(value))
}
}
impl AsRef<str> for TaskState {
fn as_ref(&self) -> &str {
&self.0
}
}
impl fmt::Display for TaskState {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_ref())
}
}
impl FromStr for TaskState {
type Err = AtmError;
fn from_str(value: &str) -> Result<Self, Self::Err> {
Self::new(value)
}
}
impl PartialEq<&str> for TaskState {
fn eq(&self, other: &&str) -> bool {
self.as_ref() == *other
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[serde(transparent)]
pub struct AckTransition(String);
impl AckTransition {
pub fn new(value: impl Into<String>) -> Result<Self, AtmError> {
let value = value.into();
if value.trim().is_empty() {
return Err(
AtmError::validation("ack transition must not be blank").with_recovery(
"Populate a non-empty ack transition before calling the Phase R boundary.",
),
);
}
Ok(Self(value))
}
}
impl AsRef<str> for AckTransition {
fn as_ref(&self) -> &str {
&self.0
}
}
impl fmt::Display for AckTransition {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_ref())
}
}
impl FromStr for AckTransition {
type Err = AtmError;
fn from_str(value: &str) -> Result<Self, Self::Err> {
Self::new(value)
}
}
pub trait AtmProtocol: sealed::Sealed {
fn request_to_frame(
&self,
request_id: RequestId,
request: RequestEnvelope,
) -> Result<FramePayload, AtmError>;
fn request_from_frame(
&self,
frame: FramePayload,
) -> Result<(RequestId, RequestEnvelope), AtmError>;
fn response_to_frame(
&self,
request_id: RequestId,
response: ResponseEnvelope,
) -> Result<FramePayload, AtmError>;
fn response_from_frame(
&self,
frame: FramePayload,
) -> Result<(RequestId, ResponseEnvelope), AtmError>;
}
pub trait ClientTransport: sealed::Sealed + Send + Sync {
fn send(&self, request: RequestEnvelope) -> Result<ResponseEnvelope, AtmError>;
}
pub trait ServerTransport: sealed::Sealed {
fn serve(
&self,
dispatcher: std::sync::Arc<dyn RequestDispatcher + Send + Sync>,
) -> Result<(), AtmError>;
}
pub trait RequestDispatcher: sealed::Sealed + Send + Sync {
fn dispatch(&self, request: RequestEnvelope) -> Result<ResponseEnvelope, AtmError>;
fn dispatch_advisory_stream(
&self,
request: AdvisoryStreamRequest,
sink: &mut dyn AdvisoryStreamSink,
) -> Result<(), AtmError>;
}
pub trait AdvisoryStreamSink {
fn emit(&mut self, response: ResponseEnvelope) -> Result<(), AtmError>;
fn stop_requested(&self) -> bool {
false
}
}
pub trait NotificationSink: sealed::Sealed {
fn deliver(&self, event: NotificationEvent) -> Result<(), AtmError>;
}
pub trait StatusSource: sealed::Sealed {
fn snapshot(&self) -> Result<RuntimeStatusSnapshot, AtmError>;
}
pub trait WatchEventSource: sealed::Sealed {
fn poll(&self, request: WatchSubscriptionRequest) -> Result<WatchEventBatch, AtmError>;
}
pub trait ReconcileCoordinator: sealed::Sealed {
fn reconcile(&self, request: ReconcileRequest) -> Result<ReconcileResult, AtmError>;
}