use std::time::Duration; use async_trait::async_trait; use speare::{req_res, Ctx, Directive, Handle, Node, Process, Request, Supervision}; use tokio::time; struct Foo; struct FooErr(Handle); #[async_trait] impl Process for Foo { type Props = Handle; type Msg = (); type Err = FooErr; async fn init(ctx: &mut Ctx) -> Result { Err(FooErr(ctx.props().clone())) } } struct Bar; struct BarErr(Handle); #[async_trait] impl Process for Bar { type Props = Handle; type Msg = (); type Err = BarErr; async fn init(ctx: &mut Ctx) -> Result { Err(BarErr(ctx.props().clone())) } } struct Parent { msgs: Vec, } enum ParentMsg { Error(String), GetMsgs(Request<(), Vec>), } #[async_trait] impl Process for Parent { type Props = (); type Msg = ParentMsg; type Err = (); async fn init(ctx: &mut Ctx) -> Result { ctx.spawn::(ctx.this().clone()); ctx.spawn::(ctx.this().clone()); Ok(Parent { msgs: vec![] }) } async fn handle(&mut self, msg: Self::Msg, _: &mut Ctx) -> Result<(), Self::Err> { match msg { ParentMsg::Error(err) => self.msgs.push(err), ParentMsg::GetMsgs(req) => req.reply(self.msgs.clone()), } Ok(()) } fn supervision(_: &Self::Props) -> Supervision { Supervision::one_for_one() .max_restarts(2) .when(|e: &FooErr| { e.0.send(ParentMsg::Error("Foo".to_string())); Directive::Resume }) .when(|e: &BarErr| { e.0.send(ParentMsg::Error("Bar".to_string())); Directive::Restart }) } } #[tokio::test] async fn it_processes_different_errors_differently() { // Arrange let mut node = Node::default(); let parent = node.spawn::(()); time::sleep(Duration::from_nanos(1)).await; // Act let (req, res) = req_res(()); parent.send(ParentMsg::GetMsgs(req)); let msgs = res.recv().await.unwrap(); // Assert assert_eq!( msgs, vec![ "Foo".to_string(), "Bar".to_string(), "Bar".to_string(), "Bar".to_string() ] ); }