feat: add a wait surface and EffectStatus to the EffectExecutor seam
commit
e79ea10feat: add a wait surface and EffectStatus to the EffectExecutor seam
The poll/await surface the trait’s own comment reserved for WS7: spawn returns a handle, wait blocks until the effect settles and returns what the executor could observe — SettledRemotely covers exec-sprites, whose outcome returns via the attested results push rather than through the machine.
refactor: rename MaterializedInputs cache_dir to cache, a cache name each backend maps into its own sandbox layout Assisted-by: Claude:claude-sonnet-5
Reviews
No reviews of this commit yet — record a verdict below.
Start a review
crates/git-backend/src/effect.rs
@@ -34,25 +34,57 @@
pub tree: gix_hash::ObjectId,
/// Each activated toolchain's resolved `PATH` entry, keyed by name.
pub toolchain_paths: std::collections::BTreeMap<String, String>,
- /// The effect's cache directory, if it names one.
- pub cache_dir: Option<String>,
+ /// The effect's cache *name*, if it declares one. A name, not a path:
+ /// where the cache lands is a property of each backend's own sandbox
+ /// layout (a bind-mounted `/cache/<name>` in a local container, a
+ /// persistent directory in a Sprite), so the backend maps the name
+ /// itself — mirroring how the effect engine's backends each derive
+ /// their own cache directory for the same declared cache.
+ pub cache: Option<String>,
}
-/// A handle to a spawned effect. Opaque for now — WS7 (`exec-local`,
-/// `exec-sprites`) adds the poll/await surface once a real executor backend
-/// exists; this trait only needs to name the seam.
+/// A handle to a spawned effect, returned by [`EffectExecutor::spawn`] and
+/// consumed by [`EffectExecutor::wait`]. The id is backend-chosen and
+/// opaque to callers: a worker-thread key for `exec-local`, a Fly Machine
+/// id for `exec-sprites`.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EffectHandle {
/// A backend-chosen opaque identifier for the spawned effect.
pub id: String,
}
+/// The terminal state of a spawned effect, as observed by the
+/// [`EffectExecutor`] that ran it (see [`EffectExecutor::wait`]).
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum EffectStatus {
+ /// The command ran to completion and exited zero.
+ Pass,
+ /// The command ran to completion and exited non-zero.
+ Fail,
+ /// The executor could not run the command to an observable exit (a
+ /// sandbox that would not start, a timeout, a lost worker).
+ Error,
+ /// The effect settled, but its outcome is not observable through this
+ /// executor: it returns out-of-band, via the attested push of its
+ /// results and cache refs with a worker member key
+ /// (`docs/scale-out.adoc`, WS7 — the `exec-sprites` path, where the
+ /// machine's termination tells the dispatcher only that the effect
+ /// settled, and the recorded run refs carry the outcome).
+ SettledRemotely,
+}
+
/// Where a [`MaterializedInputs::tree`] actually runs: a sandboxed
-/// subprocess today (`exec-local`), a Fly Machine later (`exec-sprites`).
-/// Application code (the effect engine) is written once against this
-/// trait; which backend answers `spawn` is a deployment detail.
+/// subprocess today (`exec-local`), a Fly Machine hosted (`exec-sprites`).
+/// Application code (the effect engine, the WS7 dispatcher) is written once
+/// against this trait; which backend answers `spawn` is a deployment
+/// detail.
pub trait EffectExecutor: Send + Sync {
/// Spawn `effect` against `inputs`, returning a handle to the running
/// effect. Does not block for completion.
fn spawn(&self, effect: &EffectDef, inputs: MaterializedInputs) -> Result<EffectHandle>;
+
+ /// Block until the effect behind `handle` settles, returning the
+ /// terminal state this executor could observe. Consumes the handle's
+ /// backend-side state: waiting twice on one handle is an error.
+ fn wait(&self, handle: &EffectHandle) -> Result<EffectStatus>;
}
crates/git-backend/src/lib.rs
@@ -28,7 +28,7 @@
mod object_store;
mod ref_store;
-pub use effect::{EffectDef, EffectExecutor, EffectHandle, MaterializedInputs};
+pub use effect::{EffectDef, EffectExecutor, EffectHandle, EffectStatus, MaterializedInputs};
pub use object_store::{Object, ObjectStore, PackStream, QuarantineId};
pub use ref_store::{
Expected, RefEdit, RefEvent, RefEventStream, RefIter, RefLogEntry, RefLogIter, RefName,