use std::fmt::{Display, Formatter};
use std::sync::atomic::{AtomicU64, Ordering};
use std::sync::Arc;
use std::time::Duration;
use tokio::sync::{mpsc, oneshot};
use crate::error::ActorError;
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct ActorId(Arc<str>);
impl ActorId {
pub fn as_str(&self) -> &str {
&self.0
}
}
impl<T> From<T> for ActorId
where
T: Into<String>,
{
fn from(value: T) -> Self {
let owned: String = value.into();
Self(Arc::from(owned.into_boxed_str()))
}
}
impl Display for ActorId {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Debug, Clone, Copy)]
pub enum SchedulePolicy {
Once,
Recurring {
interval: Duration,
miss_policy: MissPolicy,
},
}
#[derive(Debug, Clone, Copy)]
pub enum MissPolicy {
Skip,
CatchUp,
Delay,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct RecurringId(u64);
impl RecurringId {
pub(crate) fn new(id: u64) -> Self {
Self(id)
}
}
#[derive(Default)]
pub(crate) struct RecurringIdGenerator {
next: AtomicU64,
}
impl RecurringIdGenerator {
pub fn next(&self) -> RecurringId {
let id = self.next.fetch_add(1, Ordering::Relaxed);
RecurringId::new(id)
}
pub fn next_stream_id(&self) -> StreamId {
let id = self.next.fetch_add(1, Ordering::Relaxed);
StreamId::new(id)
}
}
#[derive(Debug, Clone)]
pub enum StopReason {
Graceful,
ParentRequest,
Failure(ActorError),
Cancelled,
Kill,
}
impl Display for StopReason {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
StopReason::Graceful => write!(f, "graceful"),
StopReason::ParentRequest => write!(f, "parent requested"),
StopReason::Failure(err) => write!(f, "failure: {err}"),
StopReason::Cancelled => write!(f, "cancelled"),
StopReason::Kill => write!(f, "killed"),
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ActorStatus {
Initializing,
Running,
Stopping,
Stopped,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum StreamEvent<T> {
Data(T),
Finished,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct StreamId(u64);
impl StreamId {
pub(crate) fn new(id: u64) -> Self {
Self(id)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RestartStrategy {
OneForOne,
OneForAll,
RestForOne,
SimpleOneForOne,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RestartType {
Permanent,
Transient,
Temporary,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Shutdown {
Kill,
Timeout(Duration),
Infinity,
}
impl Default for Shutdown {
fn default() -> Self {
Shutdown::Timeout(Duration::from_secs(5))
}
}
#[derive(Debug, Clone)]
pub struct ChildEvent {
pub child_id: ActorId,
pub child_name: Option<String>,
pub reason: StopReason,
pub action: SupervisionAction,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SupervisionAction {
RestartInitiated,
Removed,
NotSupervised,
BudgetExhausted,
}
#[derive(Debug, Clone)]
pub struct ActorStatusInfo {
pub id: ActorId,
pub name: Option<String>,
pub status: ActorStatus,
pub mailbox_len: usize,
pub mailbox_capacity: usize,
pub child_count: usize,
pub timer_count: usize,
pub stream_count: usize,
}
#[derive(Debug, Clone)]
pub struct ChildInfo {
pub id: ActorId,
pub name: Option<String>,
pub restart_type: RestartType,
pub shutdown: Shutdown,
pub is_alive: bool,
pub restart_pending: bool,
}
#[derive(Debug)]
pub(crate) enum SystemMessage {
Stop(StopReason),
GetStatus(oneshot::Sender<ActorStatusInfo>),
ChildStopped(ChildStoppedInternal),
RestartComplete {
seq: u64,
child_id: ActorId,
new_system_tx: mpsc::Sender<SystemMessage>,
new_join: tokio::task::JoinHandle<StopReason>,
},
}
#[derive(Debug, Clone)]
pub(crate) struct ChildStoppedInternal {
pub child_id: ActorId,
pub reason: StopReason,
pub incarnation: u64,
}
#[derive(Debug)]
pub enum Envelope<M, R> {
Message {
payload: M,
responder: Option<oneshot::Sender<Result<R, ActorError>>>,
},
}