Since we have two methods, we will add a struct to perform remote calls of these methods from a worker thread. Add the Action enumeration to the code:
enum Action {
StartRollCall,
MarkItself,
}
It has two variants: StartRollCall to perform the remote start_roll_call method call, and the MarkItself variant to call the remote mark_itself method.
Now we can add a function to spawn a worker in a separate thread. If we will perform outgoing calls immediately in incoming method handlers, we can block the execution, because we have a ring of microservices and blocking one microservice will block the whole ring's interaction.
Look at the spawn_worker function:
fn spawn_worker() -> Result<Sender<Action>, Error> {
let (tx, rx) = channel();
let next: SocketAddr = env::var("NEXT")?.parse()?;
thread::spawn(move || {
let remote = Remote::new(next);
let mut in_roll_call = false;
for action in rx.iter() {
match action {
Action::StartRollCall => {
if !in_roll_call {
if remote.start_roll_call().is_ok() {
debug!("ON");
in_roll_call = true;
}
} else {
if remote.mark_itself().is_ok() {
debug!("OFF");
in_roll_call = false;
}
}
}
Action::MarkItself => {
if in_roll_call {
if remote.mark_itself().is_ok() {
debug!("OFF");
in_roll_call = false;
}
} else {
debug!("SKIP");
}
}
}
}
});
Ok(tx)
}
This function creates a channel and spawns a new thread with a routine that processes all received messages from a channel. We create the Remote instance with the address extracted from the NEXT environment variable.
There is a flag that shows that the start_roll_call method has been called. We set it to true when the StartRollCall message is received and the start_roll_call method of the remote server is called. If the flag is already set to true and the routine received the StartRollCall message, the thread will call the mark_itself remote method. In other words, we will call the start_roll_call methods of all running service instances. When all services set the flag to true, we will call the mark_itself methods of all services.
Let's start a server and run a ring of services.