Eliminate need for awkward boot_fn transmission subprotocol

This commit is contained in:
Tony Garnock-Jones 2022-01-26 22:30:47 +01:00
parent cc11120f23
commit 1111776754
1 changed files with 19 additions and 54 deletions

View File

@ -5,6 +5,7 @@ use preserves::value::NestedValue;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::sync::Arc; use std::sync::Arc;
use std::sync::Mutex;
use std::time::Duration; use std::time::Duration;
use tokio::time::Instant; use tokio::time::Instant;
@ -12,11 +13,11 @@ use tokio::time::Instant;
use crate::actor::*; use crate::actor::*;
use crate::schemas::service::State; use crate::schemas::service::State;
pub type Boot = Box<dyn Send + FnMut(&mut Activation) -> ActorResult>; pub type Boot = Arc<Mutex<Box<dyn Send + FnMut(&mut Activation) -> ActorResult>>>;
#[derive(Debug)]
enum Protocol { enum Protocol {
SuperviseeStarted, // assertion SuperviseeStarted, // assertion
BootFunction(Boot), // message
Retry, // message Retry, // message
} }
@ -40,22 +41,12 @@ pub struct Supervisor {
my_name: Name, my_name: Name,
child_name: Name, child_name: Name,
config: SupervisorConfiguration, config: SupervisorConfiguration,
boot_fn: Option<Boot>, boot_fn: Boot,
restarts: VecDeque<Instant>, restarts: VecDeque<Instant>,
state: Arc<Field<State>>, state: Arc<Field<State>>,
ac_ref: Option<ActorRef>, ac_ref: Option<ActorRef>,
} }
impl std::fmt::Debug for Protocol {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Protocol::SuperviseeStarted => write!(f, "Protocol::SuperviseeStarted"),
Protocol::BootFunction(_) => write!(f, "Protocol::BootFunction(_)"),
Protocol::Retry => write!(f, "Protocol::Retry"),
}
}
}
impl Default for SupervisorConfiguration { impl Default for SupervisorConfiguration {
fn default() -> Self { fn default() -> Self {
Self { Self {
@ -133,12 +124,8 @@ impl Entity<Protocol> for Supervisor
fn message(&mut self, t: &mut Activation, m: Protocol) -> ActorResult { fn message(&mut self, t: &mut Activation, m: Protocol) -> ActorResult {
match m { match m {
Protocol::BootFunction(b) => {
self.boot_fn = Some(b);
Ok(())
}
Protocol::Retry => { Protocol::Retry => {
self.ensure_started(t) self.start_now(t)
} }
_ => Ok(()) _ => Ok(())
} }
@ -172,13 +159,13 @@ impl Supervisor {
my_name: my_name.clone(), my_name: my_name.clone(),
child_name: name, child_name: name,
config, config,
boot_fn: Some(Box::new(boot_fn)), boot_fn: Arc::new(Mutex::new(Box::new(boot_fn))),
restarts: VecDeque::new(), restarts: VecDeque::new(),
state: Arc::clone(&state_field), state: Arc::clone(&state_field),
ac_ref: None, ac_ref: None,
}; };
tracing::info!(self_ref = ?supervisor.self_ref, "Supervisor starting"); tracing::info!(self_ref = ?supervisor.self_ref, "Supervisor starting");
supervisor.ensure_started(t)?; supervisor.start_now(t)?;
t.dataflow(move |t| { t.dataflow(move |t| {
let state = t.get(&state_field).clone(); let state = t.get(&state_field).clone();
tracing::debug!(name = ?my_name, ?state); tracing::debug!(name = ?my_name, ?state);
@ -189,40 +176,18 @@ impl Supervisor {
Ok(()) Ok(())
} }
fn ensure_started(&mut self, t: &mut Activation) -> ActorResult { fn start_now(&mut self, t: &mut Activation) -> ActorResult {
match self.boot_fn.take() { let boot_cell = Arc::clone(&self.boot_fn);
None => { t.facet(|t: &mut Activation| {
t.set(&self.state, State::Failed); t.assert(&self.self_ref, Protocol::SuperviseeStarted);
tracing::error!(name = ?self.my_name, self.ac_ref = Some(t.spawn_link(
"Cannot restart supervisee, because it panicked at startup") self.child_name.clone(),
} move |t| boot_cell.lock().expect("Unpoisoned boot_fn mutex")(t)));
Some(mut boot_fn) => { tracing::debug!(self_ref = ?self.self_ref,
let self_ref = Arc::clone(&self.self_ref); supervisee = ?self.ac_ref,
t.facet(|t: &mut Activation| { "Supervisee started");
t.assert(&self.self_ref, Protocol::SuperviseeStarted); Ok(())
self.ac_ref = Some(t.spawn_link( })?;
self.child_name.clone(),
move |t| {
match boot_fn(t) {
Ok(()) => {
t.message(&self_ref, Protocol::BootFunction(boot_fn));
Ok(())
}
Err(e) => {
t.clear();
t.message(&self_ref, Protocol::BootFunction(boot_fn));
t.deliver();
Err(e)
}
}
}));
tracing::debug!(self_ref = ?self.self_ref,
supervisee = ?self.ac_ref,
"Supervisee started");
Ok(())
})?;
}
}
Ok(()) Ok(())
} }
} }