123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- //! This module contains types used to model the actor system implemented by the runtime.
- use std::{fmt::Display, sync::Arc};
- use btlib::BlockPath;
- use btserde::field_helpers::smart_ptr;
- use serde::{de::DeserializeOwned, Deserialize, Serialize};
- use uuid::Uuid;
- /// Represents the result of an actor state transition, which can be one of the following:
- /// * `Success`: The transition succeeded and the new state is contained in the result.
- /// * `Abort`: The transition failed and the previous state along with an error describing
- /// the failure is in the result.
- /// * `Fatal`: The transition failed and the actor cannot recover from this failure. An error
- /// describing the failure is contained in the result.
- pub enum TransResult<From, To> {
- /// Represents a successful transition.
- Ok(To),
- /// Represents an aborted transition.
- Abort { from: From, err: btlib::Error },
- /// Represents a failed transition which kills the actor which attempted it.
- Fatal { err: btlib::Error },
- }
- /// Specifies a kind of transition, either a `Send` or a `Receive`.
- pub enum TransKind {
- /// A transition which doesn't receive any message, but sends one or more.
- Send,
- /// A transition which receives a message.
- Receive,
- }
- impl TransKind {
- const fn verb(&self) -> &'static str {
- match self {
- Self::Send => "sending",
- Self::Receive => "receiving",
- }
- }
- }
- /// A struct which conveys information about where an actor panic occurred to the kernel.
- pub struct ActorPanic {
- /// The name of the actor implementation which panicked.
- pub actor_impl: String,
- /// The name of the state the actor was in.
- pub state: &'static str,
- /// The name of the message the actor was handling, or the name of the first message it was
- /// trying to send.
- pub message: &'static str,
- /// The kind of transition which was being attempted.
- pub kind: TransKind,
- /// An error describing why the panic occurred.
- pub err: btlib::Error,
- }
- impl Display for ActorPanic {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- write!(
- f,
- "Actor {} panicked in state {} while {} a message of type {}: {}",
- self.actor_impl,
- self.state,
- self.kind.verb(),
- self.message,
- self.err
- )
- }
- }
- /// Represents the terminal state of an actor, where it stops processing messages and halts.
- pub struct End;
- impl End {
- /// Returns the identifier for this type which is expected in protocol definitions.
- pub fn ident() -> &'static str {
- stringify!(End)
- }
- }
- /// A unique identifier for a particular service.
- #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Serialize, Deserialize)]
- pub struct ServiceId(#[serde(with = "smart_ptr")] Arc<String>);
- impl ServiceId {
- pub fn new(value: Arc<String>) -> Self {
- Self(value)
- }
- }
- impl AsRef<str> for ServiceId {
- fn as_ref(&self) -> &str {
- self.0.as_str()
- }
- }
- impl<T: Into<String>> From<T> for ServiceId {
- fn from(value: T) -> Self {
- Self(Arc::new(value.into()))
- }
- }
- impl Display for ServiceId {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- f.write_str(self.as_ref())
- }
- }
- /// A unique identifier for a service.
- ///
- /// A service is a collection of actors in the same directory which provide some functionality.
- #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Serialize, Deserialize)]
- pub struct ServiceName {
- /// The path to the directory containing the service.
- #[serde(with = "smart_ptr")]
- path: Arc<BlockPath>,
- /// The id of the service.
- service_id: ServiceId,
- }
- impl ServiceName {
- pub fn new(path: Arc<BlockPath>, service_id: ServiceId) -> Self {
- Self { path, service_id }
- }
- }
- /// Indicates the set of service providers a message is addressed to.
- ///
- /// The message could be delivered to any of the service providers in this set, at random.
- pub struct ServiceAddr {
- /// The [ServiceName] to address the message to.
- name: ServiceName,
- #[allow(dead_code)]
- /// Indicates if the message should be routed towards the root of the tree or away from it.
- rootward: bool,
- }
- impl ServiceAddr {
- pub fn new(name: ServiceName, rootward: bool) -> Self {
- Self { name, rootward }
- }
- pub fn path(&self) -> &Arc<BlockPath> {
- &self.name.path
- }
- pub fn service_id(&self) -> &ServiceId {
- &self.name.service_id
- }
- }
- /// An identifier for an actor which is unique in a given runtime.
- #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Serialize, Deserialize)]
- pub struct ActorId(Uuid);
- impl ActorId {
- pub fn new() -> Self {
- Self(Uuid::new_v4())
- }
- /// Returns an actor ID that can't have messages delivered to it.
- pub fn undeliverable() -> Self {
- Self(Uuid::from_bytes([0; 16]))
- }
- }
- impl Default for ActorId {
- fn default() -> Self {
- Self::new()
- }
- }
- impl Copy for ActorId {}
- impl Display for ActorId {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- self.0.fmt(f)
- }
- }
- /// A unique identifier for a specific actor activation.
- #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Serialize, Deserialize)]
- pub struct ActorName {
- /// The path to the directory containing this actor.
- #[serde(with = "smart_ptr")]
- path: Arc<BlockPath>,
- /// A unique identifier for an actor activation. Even as an actor transitions to different types
- /// as it handles messages, this value does not change. Thus this value can be used to trace an
- /// actor through a series of state transitions.
- act_id: ActorId,
- }
- impl ActorName {
- pub fn new(path: Arc<BlockPath>, act_id: ActorId) -> Self {
- Self { path, act_id }
- }
- pub fn path(&self) -> &Arc<BlockPath> {
- &self.path
- }
- pub fn act_id(&self) -> ActorId {
- self.act_id
- }
- }
- impl Display for ActorName {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- write!(f, "{}@{}", self.act_id, self.path)
- }
- }
- /// Trait for messages which expect exactly one reply.
- pub trait CallMsg: Serialize + DeserializeOwned + Send + Sync {
- /// The reply type expected for this message.
- type Reply: Serialize + DeserializeOwned + Send + Sync;
- }
- /// Trait for messages which expect exactly zero replies.
- pub trait SendMsg: CallMsg {}
- /// A type used to express when a reply is not expected for a message type.
- #[derive(Serialize, Deserialize)]
- pub enum NoReply {}
|