Entity::stop, Activation::on_stop
This commit is contained in:
parent
6757d0d4b5
commit
5861f91971
|
@ -165,6 +165,16 @@ pub trait Entity<M>: Send {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Optional callback for running actions when the entity's owning [Facet] terminates
|
||||||
|
/// cleanly. Will not be called in case of abnormal shutdown (crash) of an actor.
|
||||||
|
///
|
||||||
|
/// Programs register an entity's stop hook with [Activation::on_stop].
|
||||||
|
///
|
||||||
|
/// The default implementation does nothing.
|
||||||
|
fn stop(&mut self, turn: &mut Activation) -> ActorResult {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Optional callback for running cleanup actions when the
|
/// Optional callback for running cleanup actions when the
|
||||||
/// entity's animating [Actor] terminates.
|
/// entity's animating [Actor] terminates.
|
||||||
///
|
///
|
||||||
|
@ -510,16 +520,16 @@ impl FacetRef {
|
||||||
let mut t = Activation::make(&self.actor.facet_ref(state.root),
|
let mut t = Activation::make(&self.actor.facet_ref(state.root),
|
||||||
Account::new(crate::name!("shutdown")),
|
Account::new(crate::name!("shutdown")),
|
||||||
state);
|
state);
|
||||||
|
if let Err(err) = t._terminate_facet(t.state.root, exit_status.is_ok()) {
|
||||||
|
// This can only occur as the result of an internal error in this file's code.
|
||||||
|
tracing::error!(?err, "unexpected error from terminate_facet");
|
||||||
|
panic!("Unexpected error result from terminate_facet");
|
||||||
|
}
|
||||||
for action in std::mem::take(&mut t.state.exit_hooks) {
|
for action in std::mem::take(&mut t.state.exit_hooks) {
|
||||||
if let Err(err) = action(&mut t, &exit_status) {
|
if let Err(err) = action(&mut t, &exit_status) {
|
||||||
tracing::error!(?err, "error in exit hook");
|
tracing::error!(?err, "error in exit hook");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Err(err) = t._terminate_facet(t.state.root, false) {
|
|
||||||
// This can only occur as the result of an internal error in this file's code.
|
|
||||||
tracing::error!(?err, "unexpected error from disorderly terminate_facet");
|
|
||||||
panic!("Unexpected error result from disorderly terminate_facet");
|
|
||||||
}
|
|
||||||
*g = ActorState::Terminated {
|
*g = ActorState::Terminated {
|
||||||
exit_status: Arc::clone(&exit_status),
|
exit_status: Arc::clone(&exit_status),
|
||||||
};
|
};
|
||||||
|
@ -684,6 +694,21 @@ impl<'activation> Activation<'activation> {
|
||||||
move |t| t.with_entity(&r, |t, e| e.sync(t, peer))))
|
move |t| t.with_entity(&r, |t, e| e.sync(t, peer))))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Registers the entity `r` in the list of stop actions for the active facet. If the facet
|
||||||
|
/// terminates cleanly, `r`'s [`stop`][Entity::stop] will be called.
|
||||||
|
///
|
||||||
|
/// **Note.** If the actor crashes, the stop actions will *not* be called.
|
||||||
|
///
|
||||||
|
/// Use [`RunningActor::add_exit_hook`] to install a callback that will be called at the
|
||||||
|
/// end of the lifetime of the *actor* rather than the facet. (Also, exit hooks are called
|
||||||
|
/// no matter whether actor termination was normal or abnormal.)
|
||||||
|
pub fn on_stop<M: 'static + Send>(&mut self, r: &Arc<Ref<M>>) {
|
||||||
|
if let Some(f) = self.active_facet() {
|
||||||
|
let r = Arc::clone(r);
|
||||||
|
f.stop_actions.push(Box::new(move |t| r.internal_with_entity(|e| e.stop(t))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Retrieve the [`Account`] against which actions are recorded.
|
/// Retrieve the [`Account`] against which actions are recorded.
|
||||||
pub fn account(&self) -> &Arc<Account> {
|
pub fn account(&self) -> &Arc<Account> {
|
||||||
&self.pending.account
|
&self.pending.account
|
||||||
|
@ -1558,6 +1583,9 @@ where
|
||||||
fn sync(&mut self, t: &mut Activation, peer: Arc<Ref<Synced>>) -> ActorResult {
|
fn sync(&mut self, t: &mut Activation, peer: Arc<Ref<Synced>>) -> ActorResult {
|
||||||
t.with_entity(&self.underlying, |t, e| e.sync(t, peer))
|
t.with_entity(&self.underlying, |t, e| e.sync(t, peer))
|
||||||
}
|
}
|
||||||
|
fn stop(&mut self, t: &mut Activation) -> ActorResult {
|
||||||
|
t.with_entity(&self.underlying, |t, e| e.stop(t))
|
||||||
|
}
|
||||||
fn exit_hook(&mut self, t: &mut Activation, exit_status: &Arc<ActorResult>) -> ActorResult {
|
fn exit_hook(&mut self, t: &mut Activation, exit_status: &Arc<ActorResult>) -> ActorResult {
|
||||||
self.underlying.internal_with_entity(|e| e.exit_hook(t, exit_status))
|
self.underlying.internal_with_entity(|e| e.exit_hook(t, exit_status))
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,17 +10,19 @@ pub struct During<T>(Map<Handle, DuringRetractionHandler<T>>);
|
||||||
pub type DuringRetractionHandler<T> = Box<dyn Send + FnOnce(&mut T, &mut Activation) -> ActorResult>;
|
pub type DuringRetractionHandler<T> = Box<dyn Send + FnOnce(&mut T, &mut Activation) -> ActorResult>;
|
||||||
pub type DuringResult<E> = Result<Option<DuringRetractionHandler<E>>, Error>;
|
pub type DuringResult<E> = Result<Option<DuringRetractionHandler<E>>, Error>;
|
||||||
|
|
||||||
pub struct DuringEntity<M, E, Fa, Fm, Fx>
|
pub struct DuringEntity<M, E, Fa, Fm, Fs, Fx>
|
||||||
where
|
where
|
||||||
M: 'static + Send,
|
M: 'static + Send,
|
||||||
E: 'static + Send,
|
E: 'static + Send,
|
||||||
Fa: 'static + Send + FnMut(&mut E, &mut Activation, M) -> DuringResult<E>,
|
Fa: 'static + Send + FnMut(&mut E, &mut Activation, M) -> DuringResult<E>,
|
||||||
Fm: 'static + Send + FnMut(&mut E, &mut Activation, M) -> ActorResult,
|
Fm: 'static + Send + FnMut(&mut E, &mut Activation, M) -> ActorResult,
|
||||||
|
Fs: 'static + Send + FnMut(&mut E, &mut Activation) -> ActorResult,
|
||||||
Fx: 'static + Send + FnMut(&mut E, &mut Activation, &Arc<ActorResult>) -> ActorResult,
|
Fx: 'static + Send + FnMut(&mut E, &mut Activation, &Arc<ActorResult>) -> ActorResult,
|
||||||
{
|
{
|
||||||
state: E,
|
state: E,
|
||||||
assertion_handler: Option<Fa>,
|
assertion_handler: Option<Fa>,
|
||||||
message_handler: Option<Fm>,
|
message_handler: Option<Fm>,
|
||||||
|
stop_handler: Option<Fs>,
|
||||||
exit_handler: Option<Fx>,
|
exit_handler: Option<Fx>,
|
||||||
during: During<E>,
|
during: During<E>,
|
||||||
phantom: PhantomData<M>,
|
phantom: PhantomData<M>,
|
||||||
|
@ -51,38 +53,42 @@ pub fn entity<M: 'static + Send, E>(
|
||||||
E,
|
E,
|
||||||
fn (&mut E, &mut Activation, M) -> DuringResult<E>,
|
fn (&mut E, &mut Activation, M) -> DuringResult<E>,
|
||||||
fn (&mut E, &mut Activation, M) -> ActorResult,
|
fn (&mut E, &mut Activation, M) -> ActorResult,
|
||||||
|
fn (&mut E, &mut Activation) -> ActorResult,
|
||||||
fn (&mut E, &mut Activation, &Arc<ActorResult>) -> ActorResult>
|
fn (&mut E, &mut Activation, &Arc<ActorResult>) -> ActorResult>
|
||||||
where
|
where
|
||||||
E: 'static + Send,
|
E: 'static + Send,
|
||||||
{
|
{
|
||||||
DuringEntity::new(state, None, None, None)
|
DuringEntity::new(state, None, None, None, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M, E, Fa, Fm, Fx> DuringEntity<M, E, Fa, Fm, Fx>
|
impl<M, E, Fa, Fm, Fs, Fx> DuringEntity<M, E, Fa, Fm, Fs, Fx>
|
||||||
where
|
where
|
||||||
M: 'static + Send,
|
M: 'static + Send,
|
||||||
E: 'static + Send,
|
E: 'static + Send,
|
||||||
Fa: 'static + Send + FnMut(&mut E, &mut Activation, M) -> DuringResult<E>,
|
Fa: 'static + Send + FnMut(&mut E, &mut Activation, M) -> DuringResult<E>,
|
||||||
Fm: 'static + Send + FnMut(&mut E, &mut Activation, M) -> ActorResult,
|
Fm: 'static + Send + FnMut(&mut E, &mut Activation, M) -> ActorResult,
|
||||||
|
Fs: 'static + Send + FnMut(&mut E, &mut Activation) -> ActorResult,
|
||||||
Fx: 'static + Send + FnMut(&mut E, &mut Activation, &Arc<ActorResult>) -> ActorResult,
|
Fx: 'static + Send + FnMut(&mut E, &mut Activation, &Arc<ActorResult>) -> ActorResult,
|
||||||
{
|
{
|
||||||
pub fn new(
|
pub fn new(
|
||||||
state: E,
|
state: E,
|
||||||
assertion_handler: Option<Fa>,
|
assertion_handler: Option<Fa>,
|
||||||
message_handler: Option<Fm>,
|
message_handler: Option<Fm>,
|
||||||
|
stop_handler: Option<Fs>,
|
||||||
exit_handler: Option<Fx>,
|
exit_handler: Option<Fx>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
DuringEntity {
|
DuringEntity {
|
||||||
state,
|
state,
|
||||||
assertion_handler,
|
assertion_handler,
|
||||||
message_handler,
|
message_handler,
|
||||||
|
stop_handler,
|
||||||
exit_handler,
|
exit_handler,
|
||||||
during: During::new(),
|
during: During::new(),
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_asserted<Fa1>(self, assertion_handler: Fa1) -> DuringEntity<M, E, Fa1, Fm, Fx>
|
pub fn on_asserted<Fa1>(self, assertion_handler: Fa1) -> DuringEntity<M, E, Fa1, Fm, Fs, Fx>
|
||||||
where
|
where
|
||||||
Fa1: 'static + Send + FnMut(&mut E, &mut Activation, M) -> DuringResult<E>,
|
Fa1: 'static + Send + FnMut(&mut E, &mut Activation, M) -> DuringResult<E>,
|
||||||
{
|
{
|
||||||
|
@ -90,6 +96,7 @@ where
|
||||||
state: self.state,
|
state: self.state,
|
||||||
assertion_handler: Some(assertion_handler),
|
assertion_handler: Some(assertion_handler),
|
||||||
message_handler: self.message_handler,
|
message_handler: self.message_handler,
|
||||||
|
stop_handler: self.stop_handler,
|
||||||
exit_handler: self.exit_handler,
|
exit_handler: self.exit_handler,
|
||||||
during: self.during,
|
during: self.during,
|
||||||
phantom: self.phantom,
|
phantom: self.phantom,
|
||||||
|
@ -99,7 +106,7 @@ where
|
||||||
pub fn on_asserted_facet<Fa1>(
|
pub fn on_asserted_facet<Fa1>(
|
||||||
self,
|
self,
|
||||||
mut assertion_handler: Fa1,
|
mut assertion_handler: Fa1,
|
||||||
) -> DuringEntity<M, E, Box<dyn 'static + Send + FnMut(&mut E, &mut Activation, M) -> DuringResult<E>>, Fm, Fx>
|
) -> DuringEntity<M, E, Box<dyn 'static + Send + FnMut(&mut E, &mut Activation, M) -> DuringResult<E>>, Fm, Fs, Fx>
|
||||||
where
|
where
|
||||||
Fa1: 'static + Send + FnMut(&mut E, &mut Activation, M) -> ActorResult
|
Fa1: 'static + Send + FnMut(&mut E, &mut Activation, M) -> ActorResult
|
||||||
{
|
{
|
||||||
|
@ -112,7 +119,7 @@ where
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_message<Fm1>(self, message_handler: Fm1) -> DuringEntity<M, E, Fa, Fm1, Fx>
|
pub fn on_message<Fm1>(self, message_handler: Fm1) -> DuringEntity<M, E, Fa, Fm1, Fs, Fx>
|
||||||
where
|
where
|
||||||
Fm1: 'static + Send + FnMut(&mut E, &mut Activation, M) -> ActorResult,
|
Fm1: 'static + Send + FnMut(&mut E, &mut Activation, M) -> ActorResult,
|
||||||
{
|
{
|
||||||
|
@ -120,13 +127,29 @@ where
|
||||||
state: self.state,
|
state: self.state,
|
||||||
assertion_handler: self.assertion_handler,
|
assertion_handler: self.assertion_handler,
|
||||||
message_handler: Some(message_handler),
|
message_handler: Some(message_handler),
|
||||||
|
stop_handler: self.stop_handler,
|
||||||
exit_handler: self.exit_handler,
|
exit_handler: self.exit_handler,
|
||||||
during: self.during,
|
during: self.during,
|
||||||
phantom: self.phantom,
|
phantom: self.phantom,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn on_exit<Fx1>(self, exit_handler: Fx1) -> DuringEntity<M, E, Fa, Fm, Fx1>
|
pub fn on_stop<Fs1>(self, stop_handler: Fs1) -> DuringEntity<M, E, Fa, Fm, Fs1, Fx>
|
||||||
|
where
|
||||||
|
Fs1: 'static + Send + FnMut(&mut E, &mut Activation) -> ActorResult,
|
||||||
|
{
|
||||||
|
DuringEntity {
|
||||||
|
state: self.state,
|
||||||
|
assertion_handler: self.assertion_handler,
|
||||||
|
message_handler: self.message_handler,
|
||||||
|
stop_handler: Some(stop_handler),
|
||||||
|
exit_handler: self.exit_handler,
|
||||||
|
during: self.during,
|
||||||
|
phantom: self.phantom,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn on_exit<Fx1>(self, exit_handler: Fx1) -> DuringEntity<M, E, Fa, Fm, Fs, Fx1>
|
||||||
where
|
where
|
||||||
Fx1: 'static + Send + FnMut(&mut E, &mut Activation, &Arc<ActorResult>) -> ActorResult,
|
Fx1: 'static + Send + FnMut(&mut E, &mut Activation, &Arc<ActorResult>) -> ActorResult,
|
||||||
{
|
{
|
||||||
|
@ -134,6 +157,7 @@ where
|
||||||
state: self.state,
|
state: self.state,
|
||||||
assertion_handler: self.assertion_handler,
|
assertion_handler: self.assertion_handler,
|
||||||
message_handler: self.message_handler,
|
message_handler: self.message_handler,
|
||||||
|
stop_handler: self.stop_handler,
|
||||||
exit_handler: Some(exit_handler),
|
exit_handler: Some(exit_handler),
|
||||||
during: self.during,
|
during: self.during,
|
||||||
phantom: self.phantom,
|
phantom: self.phantom,
|
||||||
|
@ -141,8 +165,12 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create(self, t: &mut Activation) -> Arc<Ref<M>> {
|
pub fn create(self, t: &mut Activation) -> Arc<Ref<M>> {
|
||||||
|
let should_register_stop_action = self.stop_handler.is_some();
|
||||||
let should_register_exit_hook = self.exit_handler.is_some();
|
let should_register_exit_hook = self.exit_handler.is_some();
|
||||||
let r = t.create(self);
|
let r = t.create(self);
|
||||||
|
if should_register_stop_action {
|
||||||
|
t.on_stop(&r);
|
||||||
|
}
|
||||||
if should_register_exit_hook {
|
if should_register_exit_hook {
|
||||||
t.state.add_exit_hook(&r);
|
t.state.add_exit_hook(&r);
|
||||||
}
|
}
|
||||||
|
@ -150,11 +178,12 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E, Fa, Fm, Fx> DuringEntity<AnyValue, E, Fa, Fm, Fx>
|
impl<E, Fa, Fm, Fs, Fx> DuringEntity<AnyValue, E, Fa, Fm, Fs, Fx>
|
||||||
where
|
where
|
||||||
E: 'static + Send,
|
E: 'static + Send,
|
||||||
Fa: 'static + Send + FnMut(&mut E, &mut Activation, AnyValue) -> DuringResult<E>,
|
Fa: 'static + Send + FnMut(&mut E, &mut Activation, AnyValue) -> DuringResult<E>,
|
||||||
Fm: 'static + Send + FnMut(&mut E, &mut Activation, AnyValue) -> ActorResult,
|
Fm: 'static + Send + FnMut(&mut E, &mut Activation, AnyValue) -> ActorResult,
|
||||||
|
Fs: 'static + Send + FnMut(&mut E, &mut Activation) -> ActorResult,
|
||||||
Fx: 'static + Send + FnMut(&mut E, &mut Activation, &Arc<ActorResult>) -> ActorResult,
|
Fx: 'static + Send + FnMut(&mut E, &mut Activation, &Arc<ActorResult>) -> ActorResult,
|
||||||
{
|
{
|
||||||
pub fn create_cap(self, t: &mut Activation) -> Arc<Cap>
|
pub fn create_cap(self, t: &mut Activation) -> Arc<Cap>
|
||||||
|
@ -163,12 +192,13 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<M, E, Fa, Fm, Fx> Entity<M> for DuringEntity<M, E, Fa, Fm, Fx>
|
impl<M, E, Fa, Fm, Fs, Fx> Entity<M> for DuringEntity<M, E, Fa, Fm, Fs, Fx>
|
||||||
where
|
where
|
||||||
M: Send,
|
M: Send,
|
||||||
E: 'static + Send,
|
E: 'static + Send,
|
||||||
Fa: 'static + Send + FnMut(&mut E, &mut Activation, M) -> DuringResult<E>,
|
Fa: 'static + Send + FnMut(&mut E, &mut Activation, M) -> DuringResult<E>,
|
||||||
Fm: 'static + Send + FnMut(&mut E, &mut Activation, M) -> ActorResult,
|
Fm: 'static + Send + FnMut(&mut E, &mut Activation, M) -> ActorResult,
|
||||||
|
Fs: 'static + Send + FnMut(&mut E, &mut Activation) -> ActorResult,
|
||||||
Fx: 'static + Send + FnMut(&mut E, &mut Activation, &Arc<ActorResult>) -> ActorResult,
|
Fx: 'static + Send + FnMut(&mut E, &mut Activation, &Arc<ActorResult>) -> ActorResult,
|
||||||
{
|
{
|
||||||
fn assert(&mut self, t: &mut Activation, a: M, h: Handle) -> ActorResult {
|
fn assert(&mut self, t: &mut Activation, a: M, h: Handle) -> ActorResult {
|
||||||
|
@ -192,6 +222,13 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn stop(&mut self, t: &mut Activation) -> ActorResult {
|
||||||
|
match &mut self.stop_handler {
|
||||||
|
Some(handler) => handler(&mut self.state, t),
|
||||||
|
None => Ok(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn exit_hook(&mut self, t: &mut Activation, exit_status: &Arc<ActorResult>) -> ActorResult {
|
fn exit_hook(&mut self, t: &mut Activation, exit_status: &Arc<ActorResult>) -> ActorResult {
|
||||||
match &mut self.exit_handler {
|
match &mut self.exit_handler {
|
||||||
Some(handler) => handler(&mut self.state, t, exit_status),
|
Some(handler) => handler(&mut self.state, t, exit_status),
|
||||||
|
|
Loading…
Reference in New Issue