Enhances lifecycle communication with detailed receipts
Replaces simple string messages sent from the Brain with a structured `LifecycleReceipt` object. This receipt provides comprehensive feedback, including the original command, a specific response status (e.g., `Ok`, `Refused`), and the resulting `LifeState`. This change improves the clarity, type safety, and debuggability of inter-thread communication between the main God thread and the Brain.
This commit is contained in:
parent
b8137feea5
commit
500b26703e
4 changed files with 46 additions and 21 deletions
|
|
@ -1 +1 @@
|
||||||
135
|
136
|
||||||
|
|
@ -1,16 +1,16 @@
|
||||||
use tracing::info;
|
use tracing::info;
|
||||||
use std::sync::mpsc::{Receiver, Sender};
|
use std::sync::mpsc::{Receiver, Sender};
|
||||||
use crate::lifecycle::{LifeState, LifecycleCommand};
|
use crate::lifecycle::{LifeState, LifecycleCommand, LifecycleCommandResponse, LifecycleReceipt};
|
||||||
use crate::lifecycle::LifeState::{Buried, Genisys};
|
use crate::lifecycle::LifeState::{Buried, Genisys};
|
||||||
|
|
||||||
pub struct Brain {
|
pub struct Brain {
|
||||||
state:LifeState,
|
state:LifeState,
|
||||||
divine_rx : Receiver<LifecycleCommand>,
|
divine_rx : Receiver<LifecycleCommand>,
|
||||||
divine_tx: Sender<String>
|
divine_tx: Sender<LifecycleReceipt>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Brain {
|
impl Brain {
|
||||||
pub fn new(divine_rx: Receiver<LifecycleCommand>, divine_tx: Sender<String>) -> Self {
|
pub fn new(divine_rx: Receiver<LifecycleCommand>, divine_tx: Sender<LifecycleReceipt>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
state: LifeState::Dead,
|
state: LifeState::Dead,
|
||||||
divine_rx,
|
divine_rx,
|
||||||
|
|
@ -47,7 +47,14 @@ impl Brain {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.report_to_god("REFUSED")
|
self.refuse_command(command)
|
||||||
|
}
|
||||||
|
fn refuse_command(&mut self, command: LifecycleCommand) {
|
||||||
|
self.report_to_god(LifecycleReceipt{
|
||||||
|
command: command.clone(),
|
||||||
|
response: LifecycleCommandResponse::Refused,
|
||||||
|
new_state: self.state.clone()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn can_transition_lifecycle(&self, command: &LifecycleCommand) -> bool
|
fn can_transition_lifecycle(&self, command: &LifecycleCommand) -> bool
|
||||||
|
|
@ -63,13 +70,17 @@ impl Brain {
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
fn set_lifecycle_state(&mut self, state: &LifecycleCommand) {
|
fn set_lifecycle_state(&mut self, command: &LifecycleCommand) {
|
||||||
self.state = state.required_state;
|
self.state = command.required_state;
|
||||||
self.report_to_god("OK");
|
self.report_to_god(LifecycleReceipt{
|
||||||
|
command: command.clone(),
|
||||||
|
response: LifecycleCommandResponse::Ok,
|
||||||
|
new_state: self.state
|
||||||
|
});
|
||||||
}
|
}
|
||||||
fn report_to_god(&self, msg: &str) {
|
fn report_to_god(&self, receipt: LifecycleReceipt) {
|
||||||
info!("Reporting to God {}", msg);
|
info!("Reporting to God: Status = {:?}, NewState={:?}", receipt.response, receipt.new_state);
|
||||||
let _ = self.divine_tx.send(msg.to_string());
|
let _ = self.divine_tx.send(receipt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,8 +15,22 @@ pub enum LifeState {
|
||||||
Buried
|
Buried
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub enum LifecycleCommandResponse {
|
||||||
|
Ok,
|
||||||
|
Refused,
|
||||||
|
Failed
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
pub struct LifecycleCommand {
|
pub struct LifecycleCommand {
|
||||||
pub required_state: LifeState,
|
pub required_state: LifeState,
|
||||||
pub command_time: Instant
|
pub command_time: Instant
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct LifecycleReceipt {
|
||||||
|
pub command: LifecycleCommand,
|
||||||
|
pub response: LifecycleCommandResponse,
|
||||||
|
pub new_state: LifeState
|
||||||
|
}
|
||||||
|
|
@ -10,7 +10,7 @@ use std::thread;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
use crate::brain::Brain;
|
use crate::brain::Brain;
|
||||||
use crate::lifecycle::{LifeState, LifecycleCommand};
|
use crate::lifecycle::{LifeState, LifecycleCommand, LifecycleReceipt};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let shutdown_requested = Arc::new(AtomicBool::new(false));
|
let shutdown_requested = Arc::new(AtomicBool::new(false));
|
||||||
|
|
@ -26,7 +26,7 @@ fn main() {
|
||||||
info!("God: Brain has been buried. Shutting down.");
|
info!("God: Brain has been buried. Shutting down.");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wait_for_death(tx: Sender<LifecycleCommand>, rx: Receiver<String>) {
|
fn wait_for_death(tx: Sender<LifecycleCommand>, rx: Receiver<LifecycleReceipt>) {
|
||||||
info!("God: Resting for 10 seconds...");
|
info!("God: Resting for 10 seconds...");
|
||||||
thread::sleep(Duration::from_secs(10));
|
thread::sleep(Duration::from_secs(10));
|
||||||
|
|
||||||
|
|
@ -36,12 +36,12 @@ fn wait_for_death(tx: Sender<LifecycleCommand>, rx: Receiver<String>) {
|
||||||
command_time: Instant::now(),
|
command_time: Instant::now(),
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Ok(reply) = rx.recv() {
|
if let Ok(receipt) = rx.recv() {
|
||||||
info!("Brain: {}", reply);
|
info!("Brain: {:?}", receipt.response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn let_there_be_life(tx: &Sender<LifecycleCommand>, rx: &Receiver<String>) {
|
fn let_there_be_life(tx: &Sender<LifecycleCommand>, rx: &Receiver<LifecycleReceipt>) {
|
||||||
// 3. Command: Genisys
|
// 3. Command: Genisys
|
||||||
info!("God: Commanding Genisys...");
|
info!("God: Commanding Genisys...");
|
||||||
let _ = tx.send(LifecycleCommand {
|
let _ = tx.send(LifecycleCommand {
|
||||||
|
|
@ -50,14 +50,14 @@ fn let_there_be_life(tx: &Sender<LifecycleCommand>, rx: &Receiver<String>) {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Wait for Brain's "OK"
|
// Wait for Brain's "OK"
|
||||||
if let Ok(reply) = rx.recv() {
|
if let Ok(receipt) = rx.recv() {
|
||||||
info!("Brain: {}", reply);
|
info!("Brain: {:?}", receipt.response);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spawn_brain() -> (Sender<LifecycleCommand>, Receiver<String>) {
|
fn spawn_brain() -> (Sender<LifecycleCommand>, Receiver<LifecycleReceipt>) {
|
||||||
let (to_brain_tx, to_brain_rx) = mpsc::channel::<LifecycleCommand>();
|
let (to_brain_tx, to_brain_rx) = mpsc::channel::<LifecycleCommand>();
|
||||||
let (from_brain_tx, from_brain_rx) = mpsc::channel::<String>();
|
let (from_brain_tx, from_brain_rx) = mpsc::channel::<LifecycleReceipt>();
|
||||||
|
|
||||||
// The Brain takes one half of each pair
|
// The Brain takes one half of each pair
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue