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:
+62
-7
@@ -142,6 +142,28 @@ pub async fn receive_reply(
|
||||
.unwrap_or_else(|_| panic!("timed out waiting for reply to {id}"))
|
||||
}
|
||||
|
||||
pub async fn receive_replies(
|
||||
mailbox: &mut mpsc::Receiver<Envelope>,
|
||||
ids: &[String],
|
||||
timeout: Duration,
|
||||
) -> Vec<Envelope> {
|
||||
let mut replies = Vec::with_capacity(ids.len());
|
||||
tokio::time::timeout(timeout, async {
|
||||
while replies.len() < ids.len() {
|
||||
let message = mailbox.recv().await.expect("console mailbox closed");
|
||||
assert!(
|
||||
ids.iter()
|
||||
.any(|id| message.reply_to.as_deref() == Some(id.as_str())),
|
||||
"unexpected message while waiting for replies: {message:?}"
|
||||
);
|
||||
replies.push(message);
|
||||
}
|
||||
})
|
||||
.await
|
||||
.expect("timed out waiting for replies");
|
||||
replies
|
||||
}
|
||||
|
||||
pub async fn ask(
|
||||
host: &Host,
|
||||
mailbox: &mut mpsc::Receiver<Envelope>,
|
||||
@@ -152,16 +174,24 @@ pub async fn ask(
|
||||
receive_reply(mailbox, &id, REPLY_TIMEOUT).await
|
||||
}
|
||||
|
||||
pub async fn spawn_actor(
|
||||
pub async fn ask_type(
|
||||
host: &Host,
|
||||
mailbox: &mut mpsc::Receiver<Envelope>,
|
||||
actor: &str,
|
||||
wasm: &Path,
|
||||
source: &Path,
|
||||
body: Value,
|
||||
expected: &str,
|
||||
) -> Envelope {
|
||||
request(
|
||||
host,
|
||||
mailbox,
|
||||
let reply = ask(host, mailbox, actor, body).await;
|
||||
assert_eq!(reply.body["type"], expected, "unexpected reply: {reply:?}");
|
||||
reply
|
||||
}
|
||||
|
||||
pub fn spawn_request(host: &Host, actor: &str, wasm: &Path, source: &Path) -> String {
|
||||
host.broker.send(
|
||||
"console",
|
||||
Some("broker"),
|
||||
None,
|
||||
None,
|
||||
json!({
|
||||
"type": "spawn",
|
||||
"actor": actor,
|
||||
@@ -169,7 +199,32 @@ pub async fn spawn_actor(
|
||||
"source": source.display().to_string()
|
||||
}),
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn spawn_actor(
|
||||
host: &Host,
|
||||
mailbox: &mut mpsc::Receiver<Envelope>,
|
||||
actor: &str,
|
||||
wasm: &Path,
|
||||
source: &Path,
|
||||
) -> Envelope {
|
||||
let id = spawn_request(host, actor, wasm, source);
|
||||
receive_reply(mailbox, &id, REPLY_TIMEOUT).await
|
||||
}
|
||||
|
||||
pub async fn spawn_type(
|
||||
host: &Host,
|
||||
mailbox: &mut mpsc::Receiver<Envelope>,
|
||||
actor: &str,
|
||||
wasm: &Path,
|
||||
source: &Path,
|
||||
) -> Envelope {
|
||||
let reply = spawn_actor(host, mailbox, actor, wasm, source).await;
|
||||
assert_eq!(
|
||||
reply.body["type"], "spawned",
|
||||
"unexpected spawn reply: {reply:?}"
|
||||
);
|
||||
reply
|
||||
}
|
||||
|
||||
pub async fn upgrade_actor(
|
||||
|
||||
Reference in New Issue
Block a user