Last active
June 1, 2022 03:22
-
-
Save ddoronin/e733b4e6d146bef63db69c1dfc3ff1f9 to your computer and use it in GitHub Desktop.
Actor System implementation in Rust
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::fmt::Debug; | |
use std::future::Future; | |
use tokio::sync::mpsc; | |
use tokio::sync::{oneshot}; | |
use tokio::sync::mpsc::{Sender, Receiver}; | |
pub enum ActorMessage<State, Action> { | |
Message(Action), | |
Reply(oneshot::Sender<State>), | |
} | |
pub struct Actor<State, Action, Reducer, Effects> where State: Clone + Sized + Debug, | |
Action: Clone + Sized, | |
Reducer: Fn(State, Action) -> State, | |
Effects: Fn(State, Action) -> () { | |
pub state: State, | |
pub reducer: Reducer, | |
pub effects: Effects, | |
pub receiver: Receiver<ActorMessage<State, Action>>, | |
} | |
impl <State, Action, Reducer, Effects> Actor<State, Action, Reducer, Effects> | |
where State: Clone + Sized + Debug, | |
Action: Clone + Sized, | |
Reducer: Fn(State, Action) -> State, | |
Effects: Fn(State, Action) -> () { | |
fn handle_message(&mut self, msg: ActorMessage<State, Action>) { | |
match msg { | |
ActorMessage::Message(action) => { | |
self.state = (self.reducer)(self.state.clone(), action.clone()); | |
(self.effects)(self.state.clone(), action.clone()); | |
}, | |
ActorMessage::Reply(sender) => { | |
sender.send(self.state.clone()); | |
} | |
} | |
} | |
} | |
pub fn create_pure_actor<State, Action, Reducer>(state: State, | |
reducer: Reducer) -> (impl Future<Output=()>, Sender<ActorMessage<State, Action>>) | |
where State: Clone + Sized + Debug, | |
Action: Clone + Sized, | |
Reducer: Fn(State, Action) -> State + Send { | |
create_actor(state, reducer, |_, _| {}, 256) | |
} | |
pub fn create_actor<State, Action, Reducer, Effects>( | |
state: State, | |
reducer: Reducer, | |
effects: Effects, | |
message_box_buffer: usize) -> (impl Future<Output=()>, Sender<ActorMessage<State, Action>>) | |
where State: Clone + Sized + Debug, | |
Action: Clone + Sized, | |
Reducer: Fn(State, Action) -> State + Send, | |
Effects: Fn(State, Action) -> () { | |
let (sender, receiver) = mpsc::channel::<ActorMessage<State, Action>>(message_box_buffer); | |
let mut actor = Actor { | |
state, | |
reducer, | |
effects, | |
receiver | |
}; | |
return (run_actor(actor), sender); | |
} | |
pub async fn request_actor_state<State, Action>(sender: &Sender<ActorMessage<State, Action>>) -> State | |
where State: Clone + Sized + Debug { | |
let (reply_tx, mut reply_rx) = oneshot::channel::<State>(); | |
sender.send(ActorMessage::Reply(reply_tx)).await; | |
reply_rx.await.unwrap() | |
} | |
pub async fn run_actor<State, Action, Reducer, Effects>(mut actor: Actor<State, Action, Reducer, Effects>) | |
where State: Clone + Sized + Debug, | |
Action: Clone + Sized, | |
Reducer: Fn(State, Action) -> State + Send, | |
Effects: Fn(State, Action) -> () { | |
while let Some(msg) = actor.receiver.recv().await { | |
actor.handle_message(msg); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment