kx-utils 0.1.3

Common utils incubator
Documentation
//

/// Called when the actor starts, before it processes any messages.
///
/// Messages sent internally by the actor during `on_start` are prioritized and processed
/// before any externally sent messages, even if external messages are received first.
///
/// This ensures that the actor can properly initialize before handling external messages.
///
/// # Example
///
/// ```rust
/// use kx_utils::on_actor_start;
/// struct ServerActor;
/// impl kameo::Actor for ServerActor {
///     type Mailbox = kameo::mailbox::unbounded::UnboundedMailbox<Self>;
///
///     on_actor_start!(this, actor_ref, {
///         // handle start here
///         Ok(())
///     });
/// }
/// ```
#[macro_export]
macro_rules! on_actor_start {
    ($this:ident, $actor_ref:ident, $body:expr) => {
        #[allow(unused_variables)]
        #[tracing::instrument(skip_all)]
        async fn on_start(
            &mut self,
            actor_ref: kameo::actor::ActorRef<Self>,
        ) -> std::result::Result<(), kameo::error::BoxError> {
            tracing::debug!(?actor_ref, "{}", <Self as kameo::Actor>::name());
            let $this = self;
            let $actor_ref = actor_ref;
            $body
        }
    };
}

#[macro_export]
macro_rules! default_on_actor_start {
    ($this:ident, $actor_ref:ident) => {
        $crate::on_actor_start!($this, $actor_ref, { Ok(()) });
    };
}

/// Called swhen the actor encounters a panic or an error during "tell" message handling.
///
/// This method gives the actor an opportunity to clean up or reset its state and determine
/// whether it should be stopped or continue processing messages.
///
/// # Parameters
/// - `err`: The panic or error that occurred.
///
/// # Returns
/// - `Some(ActorStopReason)`: Stops the actor.
/// - `None`: Allows the actor to continue processing messages.
///
/// # Example
///
/// ```rust
/// use kx_utils::on_actor_panic;
/// struct ServerActor;
/// impl kameo::Actor for ServerActor {
///     type Mailbox = kameo::mailbox::unbounded::UnboundedMailbox<Self>;
///
///     on_actor_panic!(this, actor_ref, err, {
///         // handle panic here
///         Ok(None)
///     });
/// }
/// ```
#[macro_export]
macro_rules! on_actor_panic {
    ($this:ident, $actor_ref:ident, $err:ident, $body:expr) => {
        #[allow(unused_variables)]
        #[tracing::instrument(skip_all)]
        async fn on_panic(
            &mut self,
            actor_ref: kameo::actor::WeakActorRef<Self>,
            err: kameo::error::PanicError,
        ) -> std::result::Result<Option<kameo::error::ActorStopReason>, kameo::error::BoxError> {
            tracing::debug!(?actor_ref, %err, "{}", <Self as kameo::Actor>::name());
            let $this = self;
            let $actor_ref = actor_ref;
            let $err = err;
            $body
        }
    };
}

#[macro_export]
macro_rules! default_on_actor_panic {
    ($this:ident, $actor_ref:ident, $err:ident) => {
        $crate::on_actor_panic!($this, $actor_ref, $err, {
            Ok(Some(kameo::error::ActorStopReason::Panicked($err)))
        });
    };
}

/// Called when a linked actor dies.
///
/// By default, the actor will stop if the reason for the linked actor's death is anything other
/// than `Normal`. You can customize this behavior in the implementation.
///
/// # Returns
/// Whether the actor should stop or continue processing messages.
///
/// # Example
///
/// ```rust
/// use kx_utils::on_actor_link_died;
/// struct ServerActor;
/// impl kameo::Actor for ServerActor {
///     type Mailbox = kameo::mailbox::unbounded::UnboundedMailbox<Self>;
///
///     on_actor_link_died!(this, actor_ref, id, reason, {
///         // handle link death here
///         Ok(None)
///     });
/// }
/// ```
#[macro_export]
macro_rules! on_actor_link_died {
    ($this:ident, $actor_ref:ident, $id:ident, $reason:ident, $body:expr) => {
        #[allow(unused_variables)]
        #[tracing::instrument(skip_all)]
        async fn on_link_died(
            &mut self,
            actor_ref: kameo::actor::WeakActorRef<Self>,
            id: kameo::actor::ActorID,
            reason: kameo::error::ActorStopReason,
        ) -> std::result::Result<Option<kameo::error::ActorStopReason>, kameo::error::BoxError> {
            tracing::debug!(?actor_ref, %id, %reason, "{}", <Self as kameo::Actor>::name());
            let $this = self;
            let $actor_ref = actor_ref;
            let $id = id;
            let $reason = reason;
            $body
        }
    };
}

#[macro_export]
macro_rules! default_on_actor_link_died {
    ($this:ident, $actor_ref:ident, $id:ident, $reason:ident) => {
        $crate::on_actor_link_died!($this, $actor_ref, $id, $reason, {
            match &$reason {
                kameo::error::ActorStopReason::Normal => Ok(None),
                kameo::error::ActorStopReason::Killed
                | kameo::error::ActorStopReason::Panicked(_)
                | kameo::error::ActorStopReason::LinkDied { .. } => {
                    Ok(Some(kameo::error::ActorStopReason::LinkDied {
                        id: $id,
                        reason: Box::new($reason),
                    }))
                }
            }
        });
    };
}

/// Called before the actor stops.
///
/// This allows the actor to perform any necessary cleanup or release resources before being fully stopped.
///
/// # Parameters
/// - `reason`: The reason why the actor is being stopped.
///
/// # Example
///
/// ```rust
/// use kx_utils::on_actor_stop;
/// struct ServerActor;
/// impl kameo::Actor for ServerActor {
///     type Mailbox = kameo::mailbox::unbounded::UnboundedMailbox<Self>;
///
///     on_actor_stop!(this, actor_ref, reason, {
///         // handle stop here
///         Ok(())
///     });
/// }
/// ```
#[macro_export]
macro_rules! on_actor_stop {
    ($this:ident, $actor_ref:ident, $reason:ident, $body:expr) => {
        #[allow(unused_variables)]
        #[tracing::instrument(skip_all)]
        async fn on_stop(
            &mut self,
            actor_ref: kameo::actor::WeakActorRef<Self>,
            reason: kameo::error::ActorStopReason,
        ) -> std::result::Result<(), kameo::error::BoxError> {
            tracing::debug!(?actor_ref, %reason, "{}", <Self as kameo::Actor>::name());
            let $this = self;
            let $actor_ref = actor_ref;
            let $reason = reason;
            $body
        }
    };
}

#[macro_export]
macro_rules! default_on_actor_stop {
    ($this:ident, $actor_ref:ident, $reason:ident) => {
        $crate::on_actor_stop!($this, $actor_ref, $reason, { Ok(()) });
    };
}