Skip to content

Commit

Permalink
Add a wait() operator for an actor (#304)
Browse files Browse the repository at this point in the history
This allows someone to wait for the actor's exit without waiting on the JoinHandle
  • Loading branch information
slawlor authored Dec 20, 2024
1 parent 6842be7 commit 3c94f0f
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 3 deletions.
2 changes: 1 addition & 1 deletion ractor/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ractor"
version = "0.14.1"
version = "0.14.2"
authors = ["Sean Lawlor", "Evan Au", "Dillon George"]
description = "A actor framework for Rust"
documentation = "https://docs.rs/ractor"
Expand Down
19 changes: 19 additions & 0 deletions ractor/src/actor/actor_cell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,25 @@ impl ActorCell {
}
}

/// Wait for the actor to exit, optionally within a timeout
///
/// * `timeout`: If supplied, the amount of time to wait before
/// returning an error and cancelling the wait future.
///
/// IMPORTANT: If the timeout is hit, the actor is still running.
/// You should wait again for its exit.
pub async fn wait(
&self,
timeout: Option<crate::concurrency::Duration>,
) -> Result<(), crate::concurrency::Timeout> {
if let Some(to) = timeout {
crate::concurrency::timeout(to, self.inner.wait()).await
} else {
self.inner.wait().await;
Ok(())
}
}

/// Send a supervisor event to the supervisory port
///
/// * `message` - The [SupervisionEvent] to send to the supervisory port
Expand Down
10 changes: 10 additions & 0 deletions ractor/src/actor/actor_properties.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,12 @@ impl ActorProperties {
Ok(())
}

/// Wait for the actor to exit
pub(crate) async fn wait(&self) {
let rx = self.wait_handler.notified();
rx.await;
}

/// Send the kill signal, threading in a OneShot sender which notifies when the shutdown is completed
pub(crate) async fn send_signal_and_wait(
&self,
Expand All @@ -239,5 +245,9 @@ impl ActorProperties {

pub(crate) fn notify_stop_listener(&self) {
self.wait_handler.notify_waiters();
// make sure that any future caller immediately returns by pre-storing
// a notify permit (i.e. the actor stops, but you are only start waiting
// after the actor has already notified it's dead.)
self.wait_handler.notify_one();
}
}
41 changes: 41 additions & 0 deletions ractor/src/actor/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1156,3 +1156,44 @@ async fn runtime_message_typing() {
actor.stop(None);
handle.await.unwrap();
}

#[crate::concurrency::test]
#[tracing_test::traced_test]
async fn wait_for_death() {
struct TestActor;

#[cfg_attr(feature = "async-trait", crate::async_trait)]
impl Actor for TestActor {
type Msg = EmptyMessage;
type Arguments = ();
type State = ();

async fn pre_start(
&self,
_this_actor: crate::ActorRef<Self::Msg>,
_: (),
) -> Result<Self::State, ActorProcessingErr> {
Ok(())
}

async fn post_stop(
&self,
_myself: ActorRef<Self::Msg>,
_: &mut Self::State,
) -> Result<(), ActorProcessingErr> {
crate::concurrency::sleep(Duration::from_millis(10)).await;
Ok(())
}
}

let (actor, handle) = Actor::spawn(None, TestActor, ())
.await
.expect("Failed to start test actor");

actor.stop(None);
assert!(actor.wait(Some(Duration::from_millis(100))).await.is_ok());

// cleanup
actor.stop(None);
handle.await.unwrap();
}
2 changes: 1 addition & 1 deletion ractor_cluster/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ractor_cluster"
version = "0.14.1"
version = "0.14.2"
authors = ["Sean Lawlor <slawlor>"]
description = "Distributed cluster environment of Ractor actors"
documentation = "https://docs.rs/ractor"
Expand Down
2 changes: 1 addition & 1 deletion ractor_cluster_derive/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ractor_cluster_derive"
version = "0.14.1"
version = "0.14.2"
authors = ["Sean Lawlor <slawlor>"]
description = "Derives for ractor_cluster"
license = "MIT"
Expand Down

0 comments on commit 3c94f0f

Please sign in to comment.