1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
//! This example demonstrates how actors can be linked with one another.
//!
//! If actors are linked, then they will be notified if the other dies.

use futures::future::join;
use simpl_actor::*;

pub struct MyActor;

#[actor]
impl MyActor {
    #[message]
    pub fn force_panic(&self) {
        panic!("something went wrong");
    }
}

impl Actor for MyActor {
    type Ref = MyActorRef;

    async fn on_start(&mut self) -> Result<(), BoxError> {
        let id = self.actor_ref().id();
        println!("starting actor {id}");
        Ok(())
    }

    async fn on_stop(self, reason: ActorStopReason) -> Result<(), BoxError> {
        let id = self.actor_ref().id();
        println!("stopping actor {id} because {reason}");
        Ok(())
    }

    async fn on_link_died(
        &mut self,
        id: u64,
        reason: ActorStopReason,
    ) -> Result<Option<ActorStopReason>, BoxError> {
        match &reason {
            ActorStopReason::Normal => {
                println!("linked actor {id} stopped normally");
                Ok(None)
            }
            ActorStopReason::Killed
            | ActorStopReason::Panicked(_)
            | ActorStopReason::LinkDied { .. } => {
                println!("linked actor {id} stopped with error, stopping");
                Ok(Some(reason))
            }
        }
    }
}

#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<(), SendError> {
    let parent = MyActor.spawn();
    let child_a = MyActor.spawn();
    let child_b = MyActor.spawn();
    parent.link_child(&child_b).await;

    let _ = child_a.force_panic().await;
    assert!(parent.is_alive());
    assert!(child_b.is_alive());

    let _ = parent.force_panic().await;
    assert!(!parent.is_alive());
    assert!(!child_b.is_alive());

    join(parent.wait_for_stop(), child_b.wait_for_stop()).await;

    Ok(())
}