Rust: Establishes core organ communication framework
Introduces `OrganFactory` to manage the creation and spawning of organs, running each in its own thread. `OrganSocket` provides the Brain's interface for sending timestamped commands to specific organs. Configures new MPSC channels within the Brain to handle bidirectional communication with its organs, enabling command dispatch and feedback reception. The Heart is integrated as the first example organ within this architecture.
This commit is contained in:
parent
33e7de18cf
commit
7633985535
5 changed files with 137 additions and 6 deletions
|
|
@ -1,24 +1,41 @@
|
|||
use tracing::{debug, info};
|
||||
use std::sync::mpsc::{Receiver, Sender};
|
||||
use std::thread::JoinHandle;
|
||||
use crate::lifecycle::{LifeState, LifecycleCommand, LifecycleCommandResponse, LifecycleReceipt};
|
||||
use crate::lifecycle::LifeState::{Dying, Buried, Genisys};
|
||||
use crate::organs::organ_factory::OrganFactory;
|
||||
use crate::organs::organ_socket::OrganSocket;
|
||||
use crate::protocols::{BrainMessage, OrganCommand, OrganCommandEnvelope};
|
||||
|
||||
pub struct Brain {
|
||||
state:LifeState,
|
||||
divine_rx : Receiver<LifecycleCommand>,
|
||||
divine_tx: Sender<LifecycleReceipt>
|
||||
divine_tx: Sender<LifecycleReceipt>,
|
||||
organ_rx: Receiver<BrainMessage>,
|
||||
organ_tx: Sender<BrainMessage>,
|
||||
organ_sockets: Vec<OrganSocket>,
|
||||
}
|
||||
|
||||
impl Brain {
|
||||
pub fn new(divine_rx: Receiver<LifecycleCommand>, divine_tx: Sender<LifecycleReceipt>) -> Self {
|
||||
let (organ_tx, organ_rx) = std::sync::mpsc::channel::<BrainMessage>();
|
||||
|
||||
Self {
|
||||
state: LifeState::Dead,
|
||||
divine_rx,
|
||||
divine_tx,
|
||||
organ_rx,
|
||||
organ_tx,
|
||||
organ_sockets: Vec::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run(&mut self) {
|
||||
self.execute_brain_loop();
|
||||
self.build_organs();
|
||||
}
|
||||
|
||||
fn execute_brain_loop(&mut self) {
|
||||
loop {
|
||||
while let Ok(command) = self.divine_rx.try_recv() {
|
||||
self.handle_divine_command(command)
|
||||
|
|
@ -92,5 +109,12 @@ impl Brain {
|
|||
let _ = self.divine_tx.send(receipt);
|
||||
}
|
||||
|
||||
fn build_organs(& mut self) {
|
||||
info!("Building organs...");
|
||||
|
||||
let factory = OrganFactory::new(self.organ_tx.clone());
|
||||
|
||||
info!("{} organs have been built and wired in.", self.organ_sockets.len());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,2 +1,4 @@
|
|||
pub mod heart;
|
||||
pub mod organ;
|
||||
pub mod organ;
|
||||
pub mod organ_socket;
|
||||
pub mod organ_factory;
|
||||
|
|
@ -1,12 +1,29 @@
|
|||
use std::sync::mpsc;
|
||||
use std::sync::mpsc::{Receiver, Sender};
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
use tracing::{info, instrument};
|
||||
use crate::protocols::{BrainMessage, OrganCommandEnvelope, OrganResponse};
|
||||
|
||||
pub struct Heart {
|
||||
id: u32,
|
||||
rx: mpsc::Receiver<OrganCommandEnvelope>,
|
||||
tx: mpsc::Sender<BrainMessage>,
|
||||
brain_command_rx: mpsc::Receiver<OrganCommandEnvelope>,
|
||||
feedback_to_brain_tx: mpsc::Sender<BrainMessage>,
|
||||
}
|
||||
|
||||
impl Heart {
|
||||
pub(crate) fn run_loop(&mut self) {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl Heart {
|
||||
pub(crate) fn new(id: u32, rx: Receiver<OrganCommandEnvelope>, tx: Sender<BrainMessage>) -> Self {
|
||||
Self {
|
||||
id,
|
||||
brain_command_rx: rx,
|
||||
feedback_to_brain_tx: tx,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Heart {
|
||||
|
|
@ -14,7 +31,7 @@ impl Heart {
|
|||
pub fn start(self) {
|
||||
info!("Heart listener active");
|
||||
|
||||
while let Ok(envelope) = self.rx.recv() {
|
||||
while let Ok(envelope) = self.brain_command_rx.recv() {
|
||||
// 1. Process the command (Logic goes here later)
|
||||
let response = OrganResponse::Ok;
|
||||
|
||||
|
|
@ -33,7 +50,7 @@ impl Heart {
|
|||
|
||||
// 4. Trace the reply and send
|
||||
info!(?reply, "Sending response to Brain");
|
||||
let _ = self.tx.send(reply);
|
||||
let _ = self.feedback_to_brain_tx.send(reply);
|
||||
}
|
||||
}
|
||||
}
|
||||
56
src/rustylee/src/organs/organ_factory.rs
Normal file
56
src/rustylee/src/organs/organ_factory.rs
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
use std::sync::mpsc::{self, Receiver, Sender};
|
||||
use std::thread;
|
||||
use crate::organs::organ_socket::OrganSocket;
|
||||
use crate::organs::heart::Heart; // Assuming Heart is our first organ
|
||||
use crate::protocols::{OrganCommandEnvelope, BrainMessage};
|
||||
|
||||
pub struct OrganFactory {
|
||||
brain_tx: Sender<BrainMessage>,
|
||||
}
|
||||
|
||||
impl OrganFactory {
|
||||
pub(crate) fn new(brain_sender: Sender<BrainMessage>) -> Self {
|
||||
Self {
|
||||
brain_tx: brain_sender,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl OrganFactory {
|
||||
pub fn build_organs(
|
||||
// The Brain's "Inbox" mouth - we'll clone this for each organ
|
||||
brain_tx: Sender<BrainMessage>
|
||||
) -> Vec<OrganSocket> {
|
||||
let mut sockets = Vec::new();
|
||||
|
||||
// Let's spawn a Heart as an example (ID: 1)
|
||||
// In a real factory, you might loop through a config list here
|
||||
let heart_socket = Self::spawn_heart(1, brain_tx.clone());
|
||||
sockets.push(heart_socket);
|
||||
|
||||
// Add more organs here...
|
||||
// let lung_socket = Self::spawn_lung(2, brain_tx.clone());
|
||||
|
||||
tracing::info!(count = sockets.len(), "Organ collection built and threads spawned");
|
||||
|
||||
sockets
|
||||
}
|
||||
|
||||
fn spawn_heart(id: u32, feedback_to_brain_tx: Sender<BrainMessage>) -> OrganSocket {
|
||||
let (brain_command_to_organ_tx, brain_command_to_organ_rx) =
|
||||
Self::get_organ_channels();
|
||||
|
||||
let socket = OrganSocket::new(id, brain_command_to_organ_tx);
|
||||
|
||||
thread::spawn(move || {
|
||||
let mut heart = Heart::new(id, brain_command_to_organ_rx, feedback_to_brain_tx);
|
||||
heart.run_loop();
|
||||
});
|
||||
|
||||
socket
|
||||
}
|
||||
|
||||
fn get_organ_channels() -> (Sender<OrganCommandEnvelope>, Receiver<OrganCommandEnvelope>) {
|
||||
mpsc::channel::<OrganCommandEnvelope>()
|
||||
}
|
||||
}
|
||||
32
src/rustylee/src/organs/organ_socket.rs
Normal file
32
src/rustylee/src/organs/organ_socket.rs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
use std::sync::mpsc::Sender;
|
||||
use crate::protocols::{OrganCommand, OrganCommandEnvelope};
|
||||
|
||||
pub struct OrganSocket {
|
||||
pub id: u32,
|
||||
tx: Sender<OrganCommandEnvelope>,
|
||||
}
|
||||
|
||||
impl OrganSocket {
|
||||
pub fn new(id: u32, tx: Sender<OrganCommandEnvelope>) -> Self {
|
||||
Self { id, tx }
|
||||
}
|
||||
|
||||
pub fn send(&self, command: OrganCommand) {
|
||||
// Here's the "Stamping" logic.
|
||||
// The Brain just says "Beat", the Socket adds the "Metadata".
|
||||
let now = SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.unwrap_or_default()
|
||||
.as_millis() as u64;
|
||||
|
||||
let envelope = OrganCommandEnvelope {
|
||||
command,
|
||||
issued_at: now,
|
||||
};
|
||||
|
||||
if let Err(e) = self.tx.send(envelope) {
|
||||
tracing::error!(organ_id = self.id, error = %e, "Socket delivery failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue