Skip to content

Commit

Permalink
add actor watching unit test
Browse files Browse the repository at this point in the history
  • Loading branch information
LeonHartley committed Sep 10, 2023
1 parent 5c2f23b commit be9442d
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 4 deletions.
14 changes: 10 additions & 4 deletions coerce/src/actor/watch/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,21 @@ pub mod watchers;

#[async_trait]
pub trait ActorWatch {
fn watch<A: Actor>(&self, actor: LocalActorRef<A>, ctx: &ActorContext);
fn watch<A: Actor>(&self, actor: &LocalActorRef<A>, ctx: &ActorContext);

fn unwatch<A: Actor>(&self, actor: LocalActorRef<A>, ctx: &ActorContext);
fn unwatch<A: Actor>(&self, actor: &LocalActorRef<A>, ctx: &ActorContext);
}

impl<A: Actor> ActorWatch for A
where
A: Handler<ActorTerminated>,
{
fn watch<W: Actor>(&self, actor: LocalActorRef<W>, ctx: &ActorContext) {
fn watch<W: Actor>(&self, actor: &LocalActorRef<W>, ctx: &ActorContext) {
let terminated_receiver = Receiver::<ActorTerminated>::from(self.actor_ref(ctx));
let _ = actor.notify(Watch::from(terminated_receiver));
}

fn unwatch<W: Actor>(&self, actor: LocalActorRef<W>, ctx: &ActorContext) {
fn unwatch<W: Actor>(&self, actor: &LocalActorRef<W>, ctx: &ActorContext) {
let _ = actor.notify(Unwatch::from(ctx.id().clone()));
}
}
Expand Down Expand Up @@ -76,6 +76,12 @@ pub struct ActorTerminated {
actor_ref: BoxedActorRef,
}

impl ActorTerminated {
pub fn actor_ref(&self) -> &BoxedActorRef {
&self.actor_ref
}
}

impl From<BoxedActorRef> for ActorTerminated {
fn from(value: BoxedActorRef) -> Self {
Self { actor_ref: value }
Expand Down
55 changes: 55 additions & 0 deletions coerce/tests/test_actor_watching.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
use crate::util::TestActor;
use async_trait::async_trait;
use coerce::actor::context::ActorContext;
use coerce::actor::message::Handler;
use coerce::actor::system::ActorSystem;
use coerce::actor::watch::{ActorTerminated, ActorWatch};
use coerce::actor::{Actor, ActorId, CoreActorRef, IntoActor, LocalActorRef};
use tokio::sync::oneshot;
use tokio::sync::oneshot::Sender;

pub mod util;



pub struct Watchdog {
target: LocalActorRef<TestActor>,
on_actor_terminated: Option<Sender<ActorTerminated>>,
}

#[async_trait]
impl Actor for Watchdog {
async fn started(&mut self, ctx: &mut ActorContext) {
self.watch(&self.target, ctx);
}
}

#[async_trait]
impl Handler<ActorTerminated> for Watchdog {
async fn handle(&mut self, message: ActorTerminated, _ctx: &mut ActorContext) {
if let Some(on_actor_terminated) = self.on_actor_terminated.take() {
let _ = on_actor_terminated.send(message);
}
}
}

#[tokio::test]
pub async fn test_actor_watch_notifications() {
let system = ActorSystem::new();
let actor = TestActor::new().into_actor(Option::<ActorId>::None, &system).await.unwrap();
let (tx, rx) = oneshot::channel();
let _watchdog = Watchdog {
target: actor.clone(),
on_actor_terminated: Some(tx),
}
.into_actor(Option::<ActorId>::None, &system)
.await
.unwrap();

let _ = actor.notify_stop();
let actor_terminated = rx.await.unwrap();
let terminated_actor = actor_terminated.actor_ref();

assert_eq!(terminated_actor.actor_id(), actor.actor_id());
assert_eq!(terminated_actor.is_valid(), false);
}

0 comments on commit be9442d

Please sign in to comment.