RustyLee: Adds organ heartbeat and system time module
Introduces a dedicated `system::time` module to provide consistent millisecond timestamps throughout the application. Refactors the `Heart` organ to process `Beat` commands, incorporating a cooldown mechanism to regulate its rhythm. Updates the `Brain` to periodically request a heartbeat from its organs when in an active lifecycle state, utilizing the new time utilities. Ensures organs are initialized before the brain begins its operational loop.
This commit is contained in:
parent
dbb52ccbb2
commit
793c8eda8d
8 changed files with 92 additions and 30 deletions
|
|
@ -1 +1 @@
|
||||||
146
|
150
|
||||||
|
|
@ -6,6 +6,7 @@ use crate::lifecycle::LifeState::{Dying, Buried, Genisys};
|
||||||
use crate::organs::organ_factory::OrganFactory;
|
use crate::organs::organ_factory::OrganFactory;
|
||||||
use crate::organs::organ_socket::OrganSocket;
|
use crate::organs::organ_socket::OrganSocket;
|
||||||
use crate::protocols::{BrainMessage, OrganCommand, OrganCommandEnvelope};
|
use crate::protocols::{BrainMessage, OrganCommand, OrganCommandEnvelope};
|
||||||
|
use crate::system::time::Time;
|
||||||
|
|
||||||
pub struct Brain {
|
pub struct Brain {
|
||||||
state:LifeState,
|
state:LifeState,
|
||||||
|
|
@ -31,8 +32,8 @@ impl Brain {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&mut self) {
|
pub fn run(&mut self) {
|
||||||
self.execute_brain_loop();
|
|
||||||
self.build_organs();
|
self.build_organs();
|
||||||
|
self.execute_brain_loop();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn execute_brain_loop(&mut self) {
|
fn execute_brain_loop(&mut self) {
|
||||||
|
|
@ -41,12 +42,13 @@ impl Brain {
|
||||||
self.handle_divine_command(command)
|
self.handle_divine_command(command)
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.state == LifeState::Buried {
|
if self.state == Buried {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Drain the Organ Feedback Mailbox
|
if self.is_ready() {
|
||||||
// (We will add this once we define the Organ channels)
|
self.request_heart_beat();
|
||||||
|
}
|
||||||
|
|
||||||
Self::rest()
|
Self::rest()
|
||||||
}
|
}
|
||||||
|
|
@ -95,6 +97,7 @@ impl Brain {
|
||||||
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_lifecycle_state(&mut self, command: &LifecycleCommand, new_state: LifeState) {
|
fn set_lifecycle_state(&mut self, command: &LifecycleCommand, new_state: LifeState) {
|
||||||
self.state = new_state;
|
self.state = new_state;
|
||||||
self.report_to_god(LifecycleReceipt{
|
self.report_to_god(LifecycleReceipt{
|
||||||
|
|
@ -112,9 +115,26 @@ impl Brain {
|
||||||
fn build_organs(& mut self) {
|
fn build_organs(& mut self) {
|
||||||
info!("Building organs...");
|
info!("Building organs...");
|
||||||
|
|
||||||
let factory = OrganFactory::new(self.organ_tx.clone());
|
self.organ_sockets = OrganFactory::build_organs(self.organ_tx.clone());
|
||||||
|
|
||||||
info!("{} organs have been built and wired in.", self.organ_sockets.len());
|
info!("{} organs have been built and wired in.", self.organ_sockets.len());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn request_heart_beat(&self) {
|
||||||
|
if let Some(socket) = self.organ_sockets.first() {
|
||||||
|
let envelope = OrganCommandEnvelope {
|
||||||
|
command: OrganCommand::Beat(0),
|
||||||
|
issued_at: Time::time_stamp_millis(),
|
||||||
|
};
|
||||||
|
|
||||||
|
_ = socket.tx.send(envelope);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_ready(&self) -> bool {
|
||||||
|
self.state != LifeState::Dead &&
|
||||||
|
self.state != Genisys &&
|
||||||
|
self.state != Buried
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,10 @@ pub mod brain;
|
||||||
pub mod organs;
|
pub mod organs;
|
||||||
pub mod coordinates;
|
pub mod coordinates;
|
||||||
pub mod protocols;
|
pub mod protocols;
|
||||||
|
pub mod system;
|
||||||
|
|
||||||
use std::fmt::Alignment::Left;
|
use std::fmt::Alignment::Left;
|
||||||
use tracing::{info, debug};
|
use tracing::{debug, info};
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,15 @@
|
||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
use std::sync::mpsc::{Receiver, Sender};
|
use std::sync::mpsc::{Receiver, Sender};
|
||||||
use std::time::{SystemTime, UNIX_EPOCH};
|
use tracing::{debug, info, instrument};
|
||||||
use tracing::{info, instrument};
|
use crate::protocols::{BrainMessage, OrganCommand, OrganCommandEnvelope, OrganResponse};
|
||||||
use crate::protocols::{BrainMessage, OrganCommandEnvelope, OrganResponse};
|
use crate::system::time::Time;
|
||||||
|
|
||||||
pub struct Heart {
|
pub struct Heart {
|
||||||
id: u32,
|
id: u32,
|
||||||
brain_command_rx: mpsc::Receiver<OrganCommandEnvelope>,
|
brain_command_rx: mpsc::Receiver<OrganCommandEnvelope>,
|
||||||
feedback_to_brain_tx: mpsc::Sender<BrainMessage>,
|
feedback_to_brain_tx: mpsc::Sender<BrainMessage>,
|
||||||
|
last_beat_time: u64,
|
||||||
|
timestamp: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Heart {
|
impl Heart {
|
||||||
|
|
@ -16,6 +18,8 @@ impl Heart {
|
||||||
id,
|
id,
|
||||||
brain_command_rx: rx,
|
brain_command_rx: rx,
|
||||||
feedback_to_brain_tx: tx,
|
feedback_to_brain_tx: tx,
|
||||||
|
last_beat_time: 0,
|
||||||
|
timestamp: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -24,25 +28,46 @@ impl Heart {
|
||||||
info!("Heart listener active");
|
info!("Heart listener active");
|
||||||
|
|
||||||
while let Ok(envelope) = self.brain_command_rx.recv() {
|
while let Ok(envelope) = self.brain_command_rx.recv() {
|
||||||
// 1. Process the command (Logic goes here later)
|
self.timestamp = Time::time_stamp_millis();
|
||||||
|
debug!("Received brain command: {:?}", envelope);
|
||||||
|
|
||||||
|
match envelope.command {
|
||||||
|
OrganCommand::Beat(_) => {
|
||||||
|
if (self.ready_to_beat()) {
|
||||||
|
self.beat();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let response = OrganResponse::Ok;
|
let response = OrganResponse::Ok;
|
||||||
|
|
||||||
// 2. Capture the "now" timestamp
|
self.send_response_brain(envelope, response);
|
||||||
let now = SystemTime::now()
|
}
|
||||||
.duration_since(UNIX_EPOCH)
|
}
|
||||||
.unwrap_or_default()
|
|
||||||
.as_millis() as u64;
|
fn ready_to_beat(&self) -> bool {
|
||||||
|
self.timestamp >= self.last_beat_time + 500
|
||||||
|
}
|
||||||
|
|
||||||
|
fn beat(&mut self) {
|
||||||
|
self.last_beat_time = self.timestamp;
|
||||||
|
info!("Beat time: {}", self.last_beat_time);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send_response_brain(&self, envelope: OrganCommandEnvelope, response: OrganResponse) {
|
||||||
|
|
||||||
// 3. Package the reply
|
|
||||||
let reply = BrainMessage {
|
let reply = BrainMessage {
|
||||||
organ_command: envelope, // Move the original envelope back
|
organ_command: envelope,
|
||||||
responded_at: now,
|
responded_at: self.timestamp,
|
||||||
response,
|
response,
|
||||||
};
|
};
|
||||||
|
|
||||||
// 4. Trace the reply and send
|
|
||||||
info!(?reply, "Sending response to Brain");
|
info!(?reply, "Sending response to Brain");
|
||||||
let _ = self.feedback_to_brain_tx.send(reply);
|
let _ = self.feedback_to_brain_tx.send(reply);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use crate::protocols::{OrganCommand, OrganCommandEnvelope};
|
||||||
|
|
||||||
pub struct OrganSocket {
|
pub struct OrganSocket {
|
||||||
pub id: u32,
|
pub id: u32,
|
||||||
tx: Sender<OrganCommandEnvelope>,
|
pub tx: Sender<OrganCommandEnvelope>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OrganSocket {
|
impl OrganSocket {
|
||||||
|
|
|
||||||
1
src/rustylee/src/system.rs
Normal file
1
src/rustylee/src/system.rs
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
pub mod time;
|
||||||
15
src/rustylee/src/system/time.rs
Normal file
15
src/rustylee/src/system/time.rs
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
|
|
||||||
|
pub struct Time {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Time {
|
||||||
|
|
||||||
|
pub fn time_stamp_millis() -> u64 {
|
||||||
|
SystemTime::now()
|
||||||
|
.duration_since(UNIX_EPOCH)
|
||||||
|
.unwrap_or_default()
|
||||||
|
.as_millis() as u64
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue