main
etc?
ask
pattern
@olanod - did you ever find a way to run a future to completion from within an actor's recv
method? Just using block_on
results in the error
cannot execute
LocalPool
executor from within another executor: EnterError
and trying to use the ctx.run()
method complains about a lifetime issue as the future that I'm trying to execute is a method on an S3 bucket client from rusoto. Thanks!
move
keyword
tokio::runtime::Handle::current()
and then pass this handle around to the actor system whenever an actor needed to be able to block on a future. Hope this helps others! I think this should be added to the docs, and if I get motivated I may submit a PR for this.
Version 0.4.2
is now available. Special thanks to @olexiyb and @nothingismagick for:
Next up we'll be expanding on the migration to GHA to improve cadence with regards to code merges and version releases. Thank you to the team and community.
[dependencies]
riker = "0.4.2"
ask
pattern here: https://riker.rs/patterns/ )
'there is no timer running, must be called from the context of Tokio runtime'
when using Context::run
? riker-rs/riker#150
Context::run
? I would basically like to use self
when running a future using ctx.run(async move { self.data = something().await; })
but of course that doesn't work. Can I use messages?
#[derive(Debug, Clone)]
enum Actor1Command {
Ping,
Pong,
Init { a2: ActorRef<Actor2Command> },
}
struct Actor1 {
a2: Option<ActorRef<Actor2Command>>,
}
impl ActorFactoryArgs<Option<ActorRef<Actor2Command>>> for Actor1 {
fn create_args(args: Option<ActorRef<Actor2Command>>) -> Self {
Actor1 { a2: args }
}
}
impl Actor for Actor1 {
type Msg = Actor1Command;
fn recv(&mut self, _ctx: &Context<Self::Msg>, msg: Self::Msg, _sender: Sender) {
match msg {
Actor1Command::Ping => {
println!("Actor 1 received message");
_ctx.schedule_once(
Duration::from_millis(1000),
_ctx.myself(),
None,
Actor1Command::Pong,
);
}
Actor1Command::Pong => {
self.a2
.as_ref()
.map(|aref| aref.tell(Actor2Command::Ping, None));
}
Actor1Command::Init { a2 } => self.a2 = Some(a2),
}
}
}
struct Actor2 {
a1: ActorRef<Actor1Command>,
}
#[derive(Debug, Clone)]
enum Actor2Command {
Ping,
Pong,
}
impl ActorFactoryArgs<ActorRef<Actor1Command>> for Actor2 {
fn create_args(args: ActorRef<Actor1Command>) -> Self {
Actor2 { a1: args }
}
}
impl Actor for Actor2 {
type Msg = Actor2Command;
fn recv(&mut self, _ctx: &Context<Self::Msg>, msg: Self::Msg, _sender: Sender) {
match msg {
Actor2Command::Ping => {
println!("Actor 2 received message");
_ctx.schedule_once(
Duration::from_millis(1000),
_ctx.myself(),
None,
Actor2Command::Pong,
);
}
Actor2Command::Pong => {
self.a1.tell(Actor1Command::Ping, None);
}
}
}
}
let sys = ActorSystem::new().unwrap();
let actor1: ActorRef<Actor1Command> = sys
.actor_of_props::<Actor1>("actor1", Props::new_args(None))
.expect("blargh");
let actor2: ActorRef<Actor2Command> = sys
.actor_of_props::<Actor2>("actor2", Props::new_args(actor1.clone()))
.expect("blargh");
actor1
.clone()
.tell(Actor1Command::Init { a2: actor2.clone() }, None);
actor1.clone().tell(Actor1Command::Ping, None);
std::thread::sleep(Duration::from_millis(10_000));