File operations under /actor/<id>/fs/ become messages from `fs` to <id> (fs_read, fs_write, fs_mkdir, fs_remove, fs_rename) with a 10 s timeout. vfs.rs wraps the wasi:filesystem implementation of wasmtime-wasi.
This commit is contained in:
+32
-1
@@ -20,6 +20,7 @@ use wasmtime::component::Component;
|
||||
use crate::candidate;
|
||||
use crate::runtime::{InstanceConfig, Mount, Runtime};
|
||||
use crate::supervisor::{Control, Reply, Supervisor};
|
||||
use crate::vfs;
|
||||
use crate::world::{self, ActorMeta, NATIVE, VersionMeta, World};
|
||||
|
||||
pub const MAILBOX_SIZE: usize = 1000;
|
||||
@@ -60,12 +61,15 @@ pub struct Broker {
|
||||
seq: AtomicU64,
|
||||
/// Set by the `exit` request: the host process should stop.
|
||||
exit: tokio::sync::Notify,
|
||||
/// Requests of the host from `fs` (see `vfs.rs`) that wait for a reply, by message ID.
|
||||
asks: Mutex<HashMap<String, oneshot::Sender<Value>>>,
|
||||
me: std::sync::Weak<Broker>,
|
||||
}
|
||||
|
||||
impl Broker {
|
||||
pub fn new(world: World, runtime: Arc<Runtime>) -> Result<Arc<Self>> {
|
||||
let metas = world.actor_ids()?.into_iter().map(|id| (id.clone(), world.read_meta(&id))).collect();
|
||||
Ok(Arc::new(Self {
|
||||
Ok(Arc::new_cyclic(|me| Self {
|
||||
world,
|
||||
runtime,
|
||||
mailboxes: Mutex::new(HashMap::new()),
|
||||
@@ -74,9 +78,27 @@ impl Broker {
|
||||
op_locks: Mutex::new(HashMap::new()),
|
||||
seq: AtomicU64::new(1),
|
||||
exit: tokio::sync::Notify::new(),
|
||||
asks: Mutex::new(HashMap::new()),
|
||||
me: me.clone(),
|
||||
}))
|
||||
}
|
||||
|
||||
/// Send `body` from `fs` to `to` now. The future resolves to the reply
|
||||
/// body, or `None` after `vfs::ASK_TIMEOUT`.
|
||||
pub fn ask(self: &Arc<Self>, to: &str, body: Value) -> impl Future<Output = Option<Value>> + Send + 'static {
|
||||
let own = format!("q{}", self.seq.fetch_add(1, Ordering::Relaxed));
|
||||
let id = format!("{}/{own}", vfs::ID);
|
||||
let (tx, rx) = oneshot::channel();
|
||||
self.asks.lock().unwrap().insert(id.clone(), tx);
|
||||
self.send(vfs::ID, Some(to), Some(&own), None, body);
|
||||
let this = self.clone();
|
||||
async move {
|
||||
let reply = tokio::time::timeout(vfs::ASK_TIMEOUT, rx).await;
|
||||
this.asks.lock().unwrap().remove(&id);
|
||||
reply.ok()?.ok()
|
||||
}
|
||||
}
|
||||
|
||||
/// Wait until an actor sends `{"type": "exit"}` to `broker`. The `sausage`
|
||||
/// binary then stops all actors and exits, so that a wrapper such as
|
||||
/// `nix run .#loop` can start a fresh (updated) host.
|
||||
@@ -155,6 +177,13 @@ impl Broker {
|
||||
}
|
||||
|
||||
fn deliver(&self, env: Envelope) {
|
||||
if env.to == vfs::ID {
|
||||
let waiting = env.reply_to.as_ref().and_then(|r| self.asks.lock().unwrap().remove(r));
|
||||
if let Some(tx) = waiting {
|
||||
let _ = tx.send(env.body);
|
||||
}
|
||||
return;
|
||||
}
|
||||
let tx = self.mailboxes.lock().unwrap().get(&env.to).cloned();
|
||||
let error = match tx {
|
||||
None => format!("no actor with ID {}", env.to),
|
||||
@@ -201,6 +230,8 @@ impl Broker {
|
||||
network: scratch.is_none(),
|
||||
stderr_log: own.join("stderr.log"),
|
||||
env,
|
||||
actor: id.to_string(),
|
||||
broker: self.me.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user