use crate::actor::{ActorAddress, ActorInterface, ActorTypeMetadata, AnyActor, Message}; use crate::runtime::{Inbox, Runtime, SingleThreadRuntime}; use parking_lot::Mutex; use std::any::Any; use std::sync::Arc; use std::sync::atomic::AtomicUsize; pub type AdminResult = Result; #[derive(Debug, Clone, PartialEq, Eq)] pub enum AdminError { ActorNotFound { actor: ActorAddress, }, AddressMismatch { requested: ActorAddress, snapshot: ActorAddress, }, TypeMismatch { expected_actor_type: &'static str, expected_message_type: &'static str, actual_actor_type: &'static str, actual_message_type: &'static str, }, Timeout, } pub struct RuntimeAdmin<'a> { pub(crate) runtime: &'a Runtime, } pub struct Admin { pub(crate) inbox: Inbox>, } #[derive(Debug, Clone, PartialEq, Eq)] pub struct OperationResult { pub applied: bool, } #[derive(Debug, Clone, PartialEq, Eq)] pub struct ActorStatus { pub started: bool, pub suspended: bool, pub stopping: bool, pub poisoned: bool, } #[derive(Debug, Clone, PartialEq, Eq)] pub struct ActorSummary { pub address: ActorAddress, pub actor_type: &'static str, pub message_type: &'static str, pub worker_id: usize, pub parent: Option, pub mailbox_depth: usize, pub status: ActorStatus, pub last_message_type: Option<&'static str>, pub messages_handled: u64, } #[derive(Debug, Clone, PartialEq, Eq)] pub struct ListActorsResponse { pub actors: Vec, } #[derive(Debug, Clone, PartialEq, Eq)] pub struct InspectActorResponse { pub summary: ActorSummary, } #[derive(Debug, Clone, PartialEq, Eq)] pub struct ActorStateSnapshot { pub actor: ActorAddress, pub actor_type: &'static str, pub message_type: &'static str, pub actor_instance: A, } #[derive(Debug, Clone, PartialEq, Eq)] pub struct GetActorStateResponse { pub state: ActorStateSnapshot, } impl ActorStateSnapshot { pub fn new(actor: ActorAddress, actor_instance: A) -> Self { Self { actor, actor_type: std::any::type_name::(), message_type: std::any::type_name::(), actor_instance, } } } impl Admin { pub(crate) fn new(inbox: Inbox>) -> Self { Self { inbox } } pub fn try_recv(&self) -> Option> { self.inbox.try_recv() } pub fn recv_ticking(&self, host: &mut SingleThreadRuntime, max_ticks: usize) -> AdminResult { for _ in 0..max_ticks { host.try_tick(); if let Some(resp) = self.inbox.try_recv() { return resp; } } Err(AdminError::Timeout) } pub fn reply_addr(&self) -> &ActorAddress { self.inbox.addr() } } pub(crate) type AdminBoxedReply = Box; pub(crate) enum AdminCommand { ListActors { acc: Arc, }, InspectActor { actor: ActorAddress, reply_to: ActorAddress, }, GetActorState { actor: ActorAddress, reply_to: ActorAddress, get: Box< dyn FnOnce(ActorAddress, &dyn AnyActor, ActorTypeMetadata) -> AdminBoxedReply + Send, >, not_found: Box AdminBoxedReply + Send>, }, ReplaceActorState { actor: ActorAddress, reply_to: ActorAddress, replace: Box< dyn FnOnce(&mut dyn AnyActor, ActorTypeMetadata) -> AdminResult + Send, >, }, StopActor { actor: ActorAddress, reply_to: ActorAddress, }, SuspendActor { actor: ActorAddress, reply_to: ActorAddress, }, ResumeActor { actor: ActorAddress, reply_to: ActorAddress, }, } pub(crate) struct ListActorsAccumulator { pub(crate) remaining: AtomicUsize, pub(crate) summaries: Mutex>, pub(crate) reply_to: ActorAddress, }