Eliminate need for awkward boot_fn transmission subprotocol
This commit is contained in:
parent
cc11120f23
commit
1111776754
|
@ -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(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue