Przeglądaj źródła

Code cleanup and documentation.

Cleaned up the code in `btlib::model` and added additional
documenation comments.
Matthew Carr 1 rok temu
rodzic
commit
e1ceff6c5d

+ 10 - 9
crates/btrun/src/kernel.rs

@@ -121,7 +121,8 @@ mod tests {
 
     use crate::{
         tests::{EchoMsg, ASYNC_RT, RUNTIME},
-        ActorError, ActorErrorCommon, ActorName, ActorResult, Envelope, Mailbox, Named, TransKind,
+        ActorError, ActorErrorPayload, ActorName, ActorResult, Envelope, Mailbox, Named,
+        TransKind,
     };
 
     #[derive(Debug)]
@@ -181,7 +182,7 @@ mod tests {
             let test_result = timeout(Duration::from_millis(500), receiver).await.unwrap().unwrap();
 
             assert_eq!(test_result.expected_name, test_result.actual_name);
-            let expected_id = test_result.expected_name.act_id();
+            let expected_id = test_result.expected_name.actor_id();
             assert!(matches!(test_result.actual_exit, ActorExit::Ok(actor_id) if actor_id == expected_id));
         });
     }
@@ -202,7 +203,7 @@ mod tests {
                 move |_: Mailbox<EchoMsg>, actor_id, _| async move {
                     ActorResult::Err(ActorError::new(
                         bterr!(EXPECTED_ERR),
-                        ActorErrorCommon {
+                        ActorErrorPayload {
                             actor_id,
                             actor_impl: expected_actor_impl,
                             state: expected_state,
@@ -221,7 +222,7 @@ mod tests {
                 .unwrap();
 
             assert_eq!(test_result.expected_name, test_result.actual_name);
-            let expected_id = test_result.expected_name.act_id();
+            let expected_id = test_result.expected_name.actor_id();
             if let ActorExit::Error(actual_error) = test_result.actual_exit {
                 assert_eq!(expected_id, actual_error.actor_id());
                 assert_eq!(EXPECTED_ERR, actual_error.err().as_ref());
@@ -251,7 +252,7 @@ mod tests {
                 .unwrap();
 
             assert_eq!(test_result.expected_name, test_result.actual_name);
-            let expected_id = test_result.expected_name.act_id();
+            let expected_id = test_result.expected_name.actor_id();
             if let ActorExit::Panic(actual_panic) = test_result.actual_exit {
                 assert_eq!(expected_id, actual_panic.actor_id());
                 assert_eq!(EXPECTED_ERR, actual_panic.err().unwrap());
@@ -303,7 +304,7 @@ mod tests {
                 .await
                 .unwrap()
                 .unwrap();
-            let expected_id = expected_name.act_id();
+            let expected_id = expected_name.actor_id();
             assert!(matches!(actual, ActorExit::Ok(actual_id) if actual_id == expected_id));
         });
     }
@@ -327,7 +328,7 @@ mod tests {
                     spawn_owned_exit_server(runtime, owner_name, sender).await;
                     ActorResult::Err(ActorError::new(
                         bterr!(EXPECTED_ERR),
-                        ActorErrorCommon {
+                        ActorErrorPayload {
                             actor_id: owner_id,
                             actor_impl: expected_actor_impl,
                             state: expected_state,
@@ -345,7 +346,7 @@ mod tests {
                 .unwrap()
                 .unwrap();
             if let ActorExit::Error(actual_error) = actual {
-                assert_eq!(expected_name.act_id(), actual_error.actor_id());
+                assert_eq!(expected_name.actor_id(), actual_error.actor_id());
                 assert_eq!(EXPECTED_ERR, actual_error.err().as_ref());
                 assert_eq!(&expected_actor_impl, actual_error.actor_impl());
                 assert_eq!(&expected_state, actual_error.state());
@@ -375,7 +376,7 @@ mod tests {
                 .unwrap()
                 .unwrap();
             if let ActorExit::Panic(panic) = actual {
-                assert_eq!(expected_name.act_id(), panic.actor_id());
+                assert_eq!(expected_name.actor_id(), panic.actor_id());
                 assert_eq!(EXPECTED_ERR, panic.err().unwrap());
             } else {
                 panic!("Actor exit wasn't the right variant.");

+ 20 - 82
crates/btrun/src/lib.rs

@@ -6,14 +6,13 @@ use std::{
     future::{ready, Future, Ready},
     marker::PhantomData,
     net::IpAddr,
-    ops::DerefMut,
     panic::AssertUnwindSafe,
     pin::Pin,
     sync::Arc,
 };
 
 use btlib::{bterr, crypto::Creds, error::StringError, BlockPath, Result};
-use btserde::{from_slice, to_vec, write_to};
+use btserde::{from_slice, to_vec};
 use bttp::{DeserCallback, MsgCallback, Replier, Transmitter};
 use futures::FutureExt;
 use serde::{Deserialize, Serialize};
@@ -113,7 +112,7 @@ impl Runtime {
     pub(crate) async fn send_control(&self, to: ActorName, msg: ControlMsg) -> Result<()> {
         if to.path().as_ref() == self.path.as_ref() {
             let handles = self.handles.read().await;
-            if let Some(handle) = handles.get(&to.act_id()) {
+            if let Some(handle) = handles.get(&to.actor_id()) {
                 handle.send_control(msg).await
             } else {
                 Err(RuntimeError::BadActorName(to).into())
@@ -132,7 +131,7 @@ impl Runtime {
     ) -> Result<()> {
         if to.path().as_ref() == self.path.as_ref() {
             let guard = self.handles.read().await;
-            if let Some(handle) = guard.get(&to.act_id()) {
+            if let Some(handle) = guard.get(&to.actor_id()) {
                 handle.send(from, msg).await
             } else {
                 Err(RuntimeError::BadActorName(to).into())
@@ -187,7 +186,7 @@ impl Runtime {
     ) -> Result<T::Reply> {
         if to.path().as_ref() == self.path.as_ref() {
             let guard = self.handles.read().await;
-            if let Some(handle) = guard.get(&to.act_id()) {
+            if let Some(handle) = guard.get(&to.actor_id()) {
                 handle.call_through(msg).await
             } else {
                 Err(bterr!("invalid actor name"))
@@ -254,7 +253,7 @@ impl Runtime {
                 if record.actor_ids.is_empty() {
                     let spawner = record.spawner.as_ref();
                     let actor_name = spawner(self).await?;
-                    let actor_id = actor_name.act_id();
+                    let actor_id = actor_name.actor_id();
                     record.actor_ids.push(actor_id);
                     actor_id
                 } else {
@@ -284,96 +283,35 @@ impl Runtime {
         let mut handles = self.handles.write().await;
 
         if let Some(owner_ref) = owner.as_ref() {
-            if !handles.contains_key(&owner_ref.act_id()) {
+            if !handles.contains_key(&owner_ref.actor_id()) {
                 let owner = owner.take().unwrap();
                 return Err(RuntimeError::BadOwnerName(owner).into());
             }
         }
 
-        let act_id = {
-            let mut act_id = ActorId::new();
-            while handles.contains_key(&act_id) {
-                act_id = ActorId::new();
-            }
-            act_id
-        };
-
-        let act_name = self.actor_name(act_id);
-        let (tx, rx) = mpsc::channel::<Envelope<Msg>>(MAILBOX_LIMIT);
-        // The deliverer closure is responsible for deserializing messages received over the wire
-        // and delivering them to the actor's mailbox, as well as sending replies to call messages.
-        let deliverer = {
-            let buffer = Arc::new(Mutex::new(Vec::<u8>::new()));
-            let tx = tx.clone();
-            let act_name = act_name.clone();
-            move |envelope: WireEnvelope| {
-                let (wire_msg, replier) = envelope.into_parts();
-                let result = from_slice(wire_msg.payload);
-                let buffer = buffer.clone();
-                let tx = tx.clone();
-                let act_name = act_name.clone();
-                let fut: FutureResult = Box::pin(async move {
-                    let msg = result?;
-                    if let Some(mut replier) = replier {
-                        let (envelope, rx) = Envelope::new_call(msg);
-                        tx.send(envelope).await.map_err(|_| {
-                            bterr!("failed to deliver message. Recipient may have halted.")
-                        })?;
-                        match rx.await {
-                            Ok(reply) => {
-                                let mut guard = buffer.lock().await;
-                                guard.clear();
-                                write_to(&reply, guard.deref_mut())?;
-                                let wire_reply = WireReply::Ok(&guard);
-                                replier.reply(wire_reply).await
-                            }
-                            Err(err) => replier.reply_err(err.to_string(), None).await,
-                        }
-                    } else {
-                        tx.send(Envelope::new_send(act_name, msg))
-                            .await
-                            .map_err(|_| {
-                                bterr!("failed to deliver message. Recipient may have halted.")
-                            })
-                    }
-                });
-                fut
+        let actor_id = {
+            let mut actor_id = ActorId::new();
+            while handles.contains_key(&actor_id) {
+                actor_id = ActorId::new();
             }
+            actor_id
         };
 
-        // ctrl_deliverer is responsible for delivering ControlMsgs to the actor.
-        let ctrl_deliverer = {
-            let tx = tx.clone();
-            move |control: ControlMsg| {
-                let tx = tx.clone();
-                let fut: FutureResult = Box::pin(async move {
-                    tx.send(Envelope::Control(control))
-                        .await
-                        .map_err(|err| bterr!("{err}"))
-                });
-                fut
-            }
-        };
+        let act_name = self.actor_name(actor_id);
+        let (sender, receiver) = mpsc::channel::<Envelope<Msg>>(MAILBOX_LIMIT);
 
         if let Some(owner) = owner.as_ref() {
-            let owner_handle = handles.get_mut(&owner.act_id()).unwrap();
+            let owner_handle = handles.get_mut(&owner.actor_id()).unwrap();
             owner_handle.owns_mut().push(act_name.clone());
         }
 
-        let task = Self::catch_unwind(act_id, actor(rx, act_id, self));
+        let task = Self::catch_unwind(actor_id, actor(receiver, actor_id, self));
         let handle = {
             let mut tasks = self.tasks.lock().await;
             tasks.spawn(task)
         };
-        let actor_handle = ActorHandle::new(
-            act_name.clone(),
-            handle,
-            tx,
-            deliverer,
-            ctrl_deliverer,
-            owner,
-        );
-        handles.insert(act_id, actor_handle);
+        let actor_handle = ActorHandle::new(act_name.clone(), handle, sender, owner);
+        handles.insert(actor_id, actor_handle);
 
         Ok(act_name)
     }
@@ -459,7 +397,7 @@ impl Runtime {
     pub async fn take(&self, name: &ActorName) -> Result<ActorHandle> {
         if name.path().as_ref() == self.path.as_ref() {
             let mut guard = self.handles.write().await;
-            if let Some(handle) = guard.remove(&name.act_id()) {
+            if let Some(handle) = guard.remove(&name.actor_id()) {
                 Ok(handle)
             } else {
                 Err(RuntimeError::BadActorName(name.clone()).into())
@@ -601,7 +539,7 @@ impl RuntimeCallback {
 
     async fn deliver_local(&self, msg: WireMsg<'_>, replier: Option<Replier>) -> Result<()> {
         let guard = self.rt.handles.read().await;
-        if let Some(handle) = guard.get(&msg.to.act_id()) {
+        if let Some(handle) = guard.get(&msg.to.actor_id()) {
             let envelope = if let Some(replier) = replier {
                 WireEnvelope::Call { msg, replier }
             } else {
@@ -787,7 +725,7 @@ pub(crate) mod tests {
                 _ => {
                     return Err(ActorError::new(
                         bterr!("Expected EchoMsg to be a Call Message."),
-                        ActorErrorCommon {
+                        ActorErrorPayload {
                             actor_id,
                             actor_impl: ACTOR_IMPL.clone(),
                             state: STATE_NAME.clone(),

+ 124 - 43
crates/btrun/src/model.rs

@@ -3,15 +3,15 @@
 use std::{any::Any, fmt::Display, future::Future, pin::Pin, sync::Arc};
 
 use btlib::{bterr, BlockPath, Result};
-use btserde::field_helpers::smart_ptr;
+use btserde::{field_helpers::smart_ptr, from_slice, write_to};
 use serde::{de::DeserializeOwned, Deserialize, Serialize};
 use tokio::{
-    sync::{mpsc, oneshot},
+    sync::{mpsc, oneshot, Mutex},
     task::AbortHandle,
 };
 use uuid::Uuid;
 
-use crate::WireEnvelope;
+use crate::{WireEnvelope, WireReply};
 
 pub use once_cell::sync::Lazy;
 
@@ -59,7 +59,7 @@ impl Copy for TransKind {}
 
 #[derive(Debug, Clone, Serialize, Deserialize)]
 /// A struct which conveys information about where an actor error occurred to the kernel.
-pub struct ActorErrorCommon {
+pub struct ActorErrorPayload {
     /// The ID of the actor which experienced the error.
     pub actor_id: ActorId,
     /// The name of the actor implementation which erred.
@@ -76,7 +76,7 @@ pub struct ActorErrorCommon {
     pub kind: TransKind,
 }
 
-impl Display for ActorErrorCommon {
+impl Display for ActorErrorPayload {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         write!(
             f,
@@ -90,34 +90,35 @@ impl Display for ActorErrorCommon {
     }
 }
 
+/// An actor error which holds a [btlib::Error] to describe the error which occurred.
 pub struct ActorError {
-    common: ActorErrorCommon,
+    payload: ActorErrorPayload,
     err: btlib::Error,
 }
 
 impl ActorError {
-    pub fn new(err: btlib::Error, common: ActorErrorCommon) -> Self {
-        Self { common, err }
+    pub fn new(err: btlib::Error, payload: ActorErrorPayload) -> Self {
+        Self { payload, err }
     }
 
     pub fn actor_id(&self) -> ActorId {
-        self.common.actor_id
+        self.payload.actor_id
     }
 
     pub fn actor_impl(&self) -> &Arc<String> {
-        &self.common.actor_impl
+        &self.payload.actor_impl
     }
 
     pub fn state(&self) -> &Arc<String> {
-        &self.common.state
+        &self.payload.state
     }
 
     pub fn message(&self) -> &Arc<String> {
-        &self.common.message
+        &self.payload.message
     }
 
     pub fn kind(&self) -> TransKind {
-        self.common.kind
+        self.payload.kind
     }
 
     pub fn err(&self) -> &btlib::Error {
@@ -127,36 +128,40 @@ impl ActorError {
 
 impl Display for ActorError {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        write!(f, "{}: {}", self.common, self.err)
+        write!(f, "{}: {}", self.payload, self.err)
     }
 }
 
+/// An actor error which holds a [String] to describe the error which occurred.
 #[derive(Debug, Clone, Serialize, Deserialize)]
 pub struct ActorErrorStr {
-    common: ActorErrorCommon,
+    payload: ActorErrorPayload,
+    // Note that the reason why a generic err field couldn't be added to ActorErrorPayload is
+    // because we need to use the smart_ptr helper only in the case where the error is an
+    // Arc<String>.
     #[serde(with = "smart_ptr")]
     err: Arc<String>,
 }
 
 impl ActorErrorStr {
     pub fn actor_id(&self) -> ActorId {
-        self.common.actor_id
+        self.payload.actor_id
     }
 
     pub fn actor_impl(&self) -> &Arc<String> {
-        &self.common.actor_impl
+        &self.payload.actor_impl
     }
 
     pub fn state(&self) -> &Arc<String> {
-        &self.common.state
+        &self.payload.state
     }
 
     pub fn message(&self) -> &Arc<String> {
-        &self.common.message
+        &self.payload.message
     }
 
     pub fn kind(&self) -> TransKind {
-        self.common.kind
+        self.payload.kind
     }
 
     pub fn err(&self) -> &Arc<String> {
@@ -166,7 +171,7 @@ impl ActorErrorStr {
 
 impl Display for ActorErrorStr {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        write!(f, "{}: {}", self.common, self.err)
+        write!(f, "{}: {}", self.payload, self.err)
     }
 }
 
@@ -174,14 +179,16 @@ impl From<ActorError> for ActorErrorStr {
     fn from(value: ActorError) -> Self {
         let err = Arc::new(value.err.to_string());
         Self {
-            common: value.common,
+            payload: value.payload,
             err,
         }
     }
 }
 
+/// Indicates the type of panic which occurred. Either a panic with a string object, or some other
+/// type that we can't currently handle.
 #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Serialize, Deserialize)]
-pub enum PanicKind {
+pub(crate) enum PanicKind {
     String(#[serde(with = "smart_ptr")] Arc<String>),
     Unknown,
 }
@@ -189,8 +196,7 @@ pub enum PanicKind {
 impl PanicKind {
     fn new(err: Box<dyn Any>) -> Self {
         if let Ok(err) = err.downcast::<String>() {
-            let string = *err;
-            Self::String(Arc::new(string))
+            Self::String(Arc::new(*err))
         } else {
             Self::Unknown
         }
@@ -206,6 +212,7 @@ impl Display for PanicKind {
     }
 }
 
+/// Conveys information about an actor which panicked.
 #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Serialize, Deserialize)]
 pub struct ActorPanic {
     actor_id: ActorId,
@@ -416,7 +423,7 @@ impl ActorName {
         &self.path
     }
 
-    pub fn act_id(&self) -> ActorId {
+    pub fn actor_id(&self) -> ActorId {
         self.act_id
     }
 }
@@ -436,6 +443,7 @@ pub trait CallMsg: Serialize + DeserializeOwned + Send + Sync {
 /// Trait for messages which expect exactly zero replies.
 pub trait SendMsg: CallMsg {}
 
+/// Trait for enums which wrap individual message types.
 pub trait MsgEnum: CallMsg + Named {}
 
 impl<T: CallMsg + Named> MsgEnum for T {}
@@ -461,8 +469,7 @@ impl Named for ControlMsg {
     }
 }
 
-/// Wrapper around a message type `T` which indicates who the message is from and, if the message
-/// was dispatched with `call`, provides a channel to reply to it.
+/// Wrapper around a message enum `T`.
 pub enum Envelope<T: MsgEnum> {
     Call {
         msg: T,
@@ -476,12 +483,13 @@ pub enum Envelope<T: MsgEnum> {
 }
 
 impl<T: MsgEnum> Envelope<T> {
-    /// Creates a new envelope containing the given message which does not expect a reply.
+    /// Creates a new envelope of the `Send` variant containing the given message.
     pub(super) fn new_send(from: ActorName, msg: T) -> Self {
         Self::Send { from, msg }
     }
 
     /// Creates a new envelope containing the given message which expects exactly one reply.
+    /// The receiver end of the reply channel is also returned.
     pub(super) fn new_call(msg: T) -> (Self, oneshot::Receiver<T::Reply>) {
         let (tx, rx) = oneshot::channel::<T::Reply>();
         let envelope = Self::Call {
@@ -491,7 +499,8 @@ impl<T: MsgEnum> Envelope<T> {
         (envelope, rx)
     }
 
-    /// Returns the name of the actor which sent this message.
+    /// Returns the name of the actor which sent this message, or [None] if this instance isn't the
+    /// `Send` variant.
     pub fn from(&self) -> Option<&ActorName> {
         match self {
             Self::Send { from, .. } => Some(from),
@@ -499,7 +508,8 @@ impl<T: MsgEnum> Envelope<T> {
         }
     }
 
-    /// Returns a reference to the message in this envelope.
+    /// Returns a reference to the message in this envelope, or [None] if this instance is the
+    /// `Control` variant.
     pub fn msg(&self) -> Option<&T> {
         match self {
             Self::Call { msg, .. } | Self::Send { msg, .. } => Some(msg),
@@ -507,6 +517,7 @@ impl<T: MsgEnum> Envelope<T> {
         }
     }
 
+    /// Returns the name of the envelope variant this instance is.
     pub const fn name(&self) -> &'static str {
         match self {
             Self::Call { .. } => "Call",
@@ -515,6 +526,7 @@ impl<T: MsgEnum> Envelope<T> {
         }
     }
 
+    /// Returns the name of the message contained in this envelope.
     pub fn msg_name(&self) -> Arc<String> {
         match self {
             Self::Call { msg, .. } | Self::Send { msg, .. } => msg.name(),
@@ -547,41 +559,104 @@ impl<T: MsgEnum> Envelope<T> {
 
 pub(super) type FutureResult = Pin<Box<dyn Send + Future<Output = Result<()>>>>;
 
+/// An owned handle to a running actor. The actor will continue to run until this handle is dropped.
 pub struct ActorHandle {
     name: ActorName,
     handle: AbortHandle,
+    /// A boxed trait object of type `Sender<T>`, where `T` is the message enum for this actor.
     sender: Box<dyn Send + Sync + Any>,
-    deliverer: Box<dyn Send + Sync + Fn(WireEnvelope<'_>) -> FutureResult>,
+    /// A closure used to deliver messages received over the wire to the actor.
+    wire_deliverer: Box<dyn Send + Sync + Fn(WireEnvelope<'_>) -> FutureResult>,
+    /// A closure used to deliver control messages to the actor.
     ctrl_deliverer: Box<dyn Send + Sync + Fn(ControlMsg) -> FutureResult>,
     owner: Option<ActorName>,
     owns: Vec<ActorName>,
 }
 
 impl ActorHandle {
-    pub(super) fn new<T, F, G>(
+    pub(super) fn new<T>(
         name: ActorName,
         handle: AbortHandle,
         sender: mpsc::Sender<Envelope<T>>,
-        deliverer: F,
-        ctrl_deliverer: G,
         owner: Option<ActorName>,
     ) -> Self
     where
         T: 'static + MsgEnum,
-        F: 'static + Send + Sync + Fn(WireEnvelope<'_>) -> FutureResult,
-        G: 'static + Send + Sync + Fn(ControlMsg) -> FutureResult,
     {
         Self {
-            name,
             handle,
+            wire_deliverer: Self::wire_deliverer(sender.clone(), name.clone()),
+            ctrl_deliverer: Self::control_deliverer(sender.clone()),
+            name,
             sender: Box::new(sender),
-            deliverer: Box::new(deliverer),
-            ctrl_deliverer: Box::new(ctrl_deliverer),
             owner,
             owns: Vec::new(),
         }
     }
 
+    // Makes the `wire_deliverer` field, which is responsible for deserializing messages received
+    // over the wire and delivering them to the actor's mailbox, as well as sending replies to call
+    // messages.
+    fn wire_deliverer<T: 'static + MsgEnum>(
+        sender: mpsc::Sender<Envelope<T>>,
+        name: ActorName,
+    ) -> Box<dyn Send + Sync + Fn(WireEnvelope<'_>) -> FutureResult> {
+        let buffer = Arc::new(Mutex::new(Vec::<u8>::new()));
+        let closure = move |envelope: WireEnvelope| {
+            let (wire_msg, replier) = envelope.into_parts();
+            let result = from_slice(wire_msg.payload);
+            let buffer = buffer.clone();
+            let sender = sender.clone();
+            let act_name = name.clone();
+            let fut: FutureResult = Box::pin(async move {
+                let msg = result?;
+                if let Some(mut replier) = replier {
+                    let (envelope, rx) = Envelope::new_call(msg);
+                    sender.send(envelope).await.map_err(|_| {
+                        bterr!("failed to deliver message. Recipient may have halted.")
+                    })?;
+                    match rx.await {
+                        Ok(reply) => {
+                            let mut guard = buffer.lock().await;
+                            guard.clear();
+                            write_to(&reply, &mut *guard)?;
+                            let wire_reply = WireReply::Ok(&guard);
+                            replier.reply(wire_reply).await
+                        }
+                        Err(err) => replier.reply_err(err.to_string(), None).await,
+                    }
+                } else {
+                    sender
+                        .send(Envelope::new_send(act_name, msg))
+                        .await
+                        .map_err(|_| {
+                            bterr!("failed to deliver message. Recipient may have halted.")
+                        })
+                }
+            });
+            fut
+        };
+        Box::new(closure)
+    }
+
+    /// Makes the `ctrl_deliverer` field, which is responsible for delivering [ControlMsg]s to the
+    /// actor.
+    fn control_deliverer<T: 'static + MsgEnum>(
+        sender: mpsc::Sender<Envelope<T>>,
+    ) -> Box<dyn Send + Sync + Fn(ControlMsg) -> FutureResult> {
+        let closure = move |control: ControlMsg| {
+            let sender = sender.clone();
+            let fut: FutureResult = Box::pin(async move {
+                sender
+                    .send(Envelope::Control(control))
+                    .await
+                    .map_err(|err| bterr!("{err}"))
+            });
+            fut
+        };
+        Box::new(closure)
+    }
+
     fn sender<T: 'static + MsgEnum>(&self) -> Result<&mpsc::Sender<Envelope<T>>> {
         self.sender
             .downcast_ref::<mpsc::Sender<Envelope<T>>>()
@@ -592,7 +667,7 @@ impl ActorHandle {
         &self.name
     }
 
-    /// Sends a message to the actor represented by this handle.
+    /// Sends a message to this actor.
     pub async fn send<T: 'static + MsgEnum>(&self, from: ActorName, msg: T) -> Result<()> {
         let sender = self.sender()?;
         sender
@@ -602,6 +677,7 @@ impl ActorHandle {
         Ok(())
     }
 
+    /// Sends a call message to this actor and awaits the reply.
     pub async fn call_through<T: 'static + MsgEnum>(&self, msg: T) -> Result<T::Reply> {
         let sender = self.sender()?;
         let (envelope, rx) = Envelope::new_call(msg);
@@ -613,22 +689,27 @@ impl ActorHandle {
         Ok(reply)
     }
 
+    /// Sends a [ControlMsg] to this actor.
     pub(crate) async fn send_control(&self, msg: ControlMsg) -> Result<()> {
         (self.ctrl_deliverer)(msg).await
     }
 
+    /// Aborts this actor.
     pub fn abort(&self) {
         self.handle.abort();
     }
 
+    /// Delivers a message received over the wire to this actor.
     pub(super) async fn deliver(&self, envelope: WireEnvelope<'_>) -> Result<()> {
-        (self.deliverer)(envelope).await
+        (self.wire_deliverer)(envelope).await
     }
 
+    /// Takes the owner name out of this handle.
     pub(crate) fn take_owner(&mut self) -> Option<ActorName> {
         self.owner.take()
     }
 
+    /// Returns a mutable reference to the vector of actor names which this actor owns.
     pub(crate) fn owns_mut(&mut self) -> &mut Vec<ActorName> {
         &mut self.owns
     }
@@ -646,8 +727,8 @@ impl Drop for ActorHandle {
 macro_rules! actor_name {
     ($name:literal) => {
         fn actor_impl() -> ::std::sync::Arc<String> {
-            use ::once_cell::sync::Lazy;
             use ::std::sync::Arc;
+            use $crate::model::Lazy;
             static NAME: Lazy<Arc<String>> = Lazy::new(|| Arc::new($name.into()));
             NAME.clone()
         }

+ 9 - 9
crates/btrun/tests/runtime_tests.rs

@@ -159,7 +159,7 @@ mod ping_pong {
                                     {
                                         return Err(ActorError::new(
                                             bterr!("Failed to send Ping reply."),
-                                            ActorErrorCommon {
+                                            ActorErrorPayload {
                                                 actor_id,
                                                 actor_impl: Init::actor_impl(),
                                                 state: Init::state_name(),
@@ -177,7 +177,7 @@ mod ping_pong {
                                 TransResult::Fatal { err } => {
                                     return Err(ActorError::new(
                                         err,
-                                        ActorErrorCommon {
+                                        ActorErrorPayload {
                                             actor_id,
                                             actor_impl: Init::actor_impl(),
                                             state: Init::state_name(),
@@ -193,7 +193,7 @@ mod ping_pong {
                     envelope => {
                         return Err(ActorError::new(
                             bterr!("Unexpected envelope type: {}", envelope.name()),
-                            ActorErrorCommon {
+                            ActorErrorPayload {
                                 actor_id,
                                 actor_impl: Init::actor_impl(),
                                 state: state.name(),
@@ -533,7 +533,7 @@ mod client_callback {
                                         TransResult::Fatal { err } => {
                                             panic_any(ActorError::new(
                                                 err,
-                                                ActorErrorCommon {
+                                                ActorErrorPayload {
                                                 actor_id,
                                                 actor_impl: Init::actor_impl(),
                                                 state: Init::OnSendRegisterRegistered::state_name(),
@@ -551,7 +551,7 @@ mod client_callback {
                         }
                         envelope => return Err(ActorError::new(
                             bterr!("Unexpected envelope type: {}", envelope.name()),
-                            ActorErrorCommon {
+                            ActorErrorPayload {
                             actor_id,
                             actor_impl: Init::actor_impl(),
                             state: state.name(),
@@ -621,7 +621,7 @@ mod client_callback {
                                 TransResult::Fatal { err } => {
                                     let err = ActorError::new(
                                         err,
-                                        ActorErrorCommon {
+                                        ActorErrorPayload {
                                             actor_id,
                                             actor_impl: Init::actor_impl(),
                                             state: Init::state_name(),
@@ -645,7 +645,7 @@ mod client_callback {
                     envelope => {
                         return Err(ActorError::new(
                             bterr!("Unexpected envelope type: {}", envelope.name()),
-                            ActorErrorCommon {
+                            ActorErrorPayload {
                                 actor_id,
                                 actor_impl: Init::actor_impl(),
                                 state: state.name(),
@@ -697,7 +697,7 @@ mod client_callback {
                     TransResult::Abort { err, .. } | TransResult::Fatal { err } => {
                         let err = ActorError::new(
                             err,
-                            ActorErrorCommon {
+                            ActorErrorPayload {
                                 actor_id,
                                 actor_impl: Init::actor_impl(),
                                 state: Init::state_name(),
@@ -713,7 +713,7 @@ mod client_callback {
                 runtime.send(owned, from, msg).await.unwrap_or_else(|err| {
                     let err = ActorError::new(
                         err,
-                        ActorErrorCommon {
+                        ActorErrorPayload {
                             actor_id,
                             actor_impl: Init::actor_impl(),
                             state: Init::state_name(),