Host: fixes from the review, with regression tests
- one live instance per actor: check after the lock; dropping an instance kills it - state snapshots keep target/ and .git/; only source copies skip them - one shutdown deadline; output during shutdown is still routed - deliveries route stdout meanwhile; a stuck stdin kills the instance (no partial lines) and the sender gets undeliverable; control requests are not blocked by a stuck delivery - Host::stop aborts running broker and cargo requests first - compile a version before installing it; roll back if it does not start - unique archive names; a failed archive keeps the actor manageable - commit on close: truncate without create; directory renames - candidates see SAUSAGE_VERSION and the existing state of a new actor - the host publishes PROTOCOL.md at /actor/broker/public/
This commit is contained in:
+20
-7
@@ -20,10 +20,15 @@ use tokio::sync::mpsc;
|
||||
pub use broker::{Broker, Envelope};
|
||||
pub use world::World;
|
||||
|
||||
/// The contract between the host and the actors. The host publishes it at
|
||||
/// `/actor/broker/public/PROTOCOL.md`, so that every actor can read it.
|
||||
const PROTOCOL: &str = include_str!("../../PROTOCOL.md");
|
||||
|
||||
/// A running world.
|
||||
pub struct Host {
|
||||
pub world: World,
|
||||
pub broker: Arc<Broker>,
|
||||
native: Vec<tokio::task::JoinHandle<()>>,
|
||||
_lock: std::fs::File,
|
||||
}
|
||||
|
||||
@@ -40,16 +45,17 @@ impl Host {
|
||||
bail!("another sausage process runs {}", root.display());
|
||||
}
|
||||
let broker = Broker::new(world.clone(), runtime::Runtime::new()?)?;
|
||||
world::write_atomic(&world.public_dir("broker").join("PROTOCOL.md"), PROTOCOL.as_bytes())?;
|
||||
|
||||
let rx = broker.open_mailbox("broker");
|
||||
tokio::spawn(broker.clone().run_actor(rx));
|
||||
let rx = broker.open_mailbox(cargo_actor::ID);
|
||||
tokio::spawn(Arc::new(cargo_actor::Cargo::new(world.clone())?).run_actor(broker.clone(), rx));
|
||||
|
||||
let cargo = cargo_actor::Cargo::new(world.clone())?;
|
||||
let native = vec![
|
||||
tokio::spawn(broker.clone().run_actor(broker.open_mailbox("broker"))),
|
||||
tokio::spawn(cargo.run_actor(broker.clone(), broker.open_mailbox(cargo_actor::ID))),
|
||||
];
|
||||
for change in broker.scan().await {
|
||||
eprintln!("sausage: {change}");
|
||||
}
|
||||
Ok(Host { world, broker, _lock: lock })
|
||||
Ok(Host { world, broker, native, _lock: lock })
|
||||
}
|
||||
|
||||
/// Register a native actor with the ID `id` and return its mailbox.
|
||||
@@ -57,8 +63,15 @@ impl Host {
|
||||
self.broker.open_mailbox(id)
|
||||
}
|
||||
|
||||
/// Stop every actor gracefully.
|
||||
/// Stop the broker and `cargo` (with the requests they still run), then
|
||||
/// every actor, gracefully.
|
||||
pub async fn stop(self) {
|
||||
for task in &self.native {
|
||||
task.abort();
|
||||
}
|
||||
for task in self.native {
|
||||
let _ = task.await;
|
||||
}
|
||||
self.broker.shutdown_all().await;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user