pub struct SessionRegistryV2 { /* private fields */ }Expand description
Registry that manages the lifecycle of v2 execution sessions.
Clone is cheap — the inner Arc<RwLock<...>> is reference-counted.
Implementations§
Source§impl SessionRegistryV2
impl SessionRegistryV2
Sourcepub fn new(
executor: Arc<Executor>,
state_store: Arc<JsonFileStore>,
card_store: Arc<FileCardStore>,
scenarios_dir: PathBuf,
) -> Self
pub fn new( executor: Arc<Executor>, state_store: Arc<JsonFileStore>, card_store: Arc<FileCardStore>, scenarios_dir: PathBuf, ) -> Self
Create a new empty registry backed by executor, with the storage paths
that will be injected into each spawned VM session.
The state_store / card_store / scenarios_dir mirror the legacy
AppService resolution against the AppConfig::app_dir() layout, so a
v2 caller produces the same on-disk side effects as a legacy caller.
Sourcepub async fn spawn_v2(&self, spec: SessionSpec) -> Result<SessionId, SpawnError>
pub async fn spawn_v2(&self, spec: SessionSpec) -> Result<SessionId, SpawnError>
Start a new v2 execution session, returning the SessionId immediately.
Execution proceeds in the background via tokio::spawn(driver_loop(...)).
The caller receives the SessionId without waiting for execution to complete
or for the first event (Invariant 6 / debt #40955).
Only algocline_core::execution::SpecKind::Run is supported in this subtask.
Other variants return SpawnError::InvalidSpec. Subtask 3 will extend this
to handle Advice and Eval through the full AppService path.
§Errors
SpawnError::Engine— the executor failed to start the session.SpawnError::InvalidSpec— the provided spec is malformed or uses an unsupported kind.
Sourcepub async fn state(&self, id: &SessionId) -> Result<ExecutionState, StateError>
pub async fn state(&self, id: &SessionId) -> Result<ExecutionState, StateError>
Query the current ExecutionState of a session.
§Errors
StateError::NotFound— no session with the given id exists.
Sourcepub async fn resume(
&self,
id: &SessionId,
payload: ResumePayload,
) -> Result<ResumeOutcome, ResumeError>
pub async fn resume( &self, id: &SessionId, payload: ResumePayload, ) -> Result<ResumeOutcome, ResumeError>
Resume a paused session by delivering LLM responses.
§Errors
ResumeError::NotFound— no session with the given id exists.ResumeError::NotPaused— the session is not in thePausedstate.ResumeError::AlreadyCancelled— the session is already cancelled.
Sourcepub async fn cancel(
&self,
id: &SessionId,
reason: CancelReason,
) -> Result<(), CancelError>
pub async fn cancel( &self, id: &SessionId, reason: CancelReason, ) -> Result<(), CancelError>
Request cooperative cancellation of a session.
Idempotent: returns Ok(()) for sessions already in a terminal state.
§Errors
CancelError::NotFound— no session with the given id exists.
Sourcepub fn observe(
&self,
id: &SessionId,
) -> Result<Box<dyn ObserverHandle>, ObserveError>
pub fn observe( &self, id: &SessionId, ) -> Result<Box<dyn ObserverHandle>, ObserveError>
Subscribe to the progress event stream for a session.
This is a synchronous fn: broadcast::Sender::subscribe() is
synchronous and does not perform I/O. Multiple concurrent subscribers
each receive the full event stream independently (Crux R3).
§Errors
ObserveError::NotFound— no session with the given id exists, ortry_read()experienced lock contention (write lock held byspawn). The contention path emitstracing::warn!(target = "session.observe", ...); callers cannot distinguish it from a true absent-session result.
Sourcepub async fn await_terminal(
&self,
id: &SessionId,
) -> Result<TerminalOutcome, AwaitError>
pub async fn await_terminal( &self, id: &SessionId, ) -> Result<TerminalOutcome, AwaitError>
Await the terminal state of a session.
Polls the shared state until it reaches a terminal variant (Done,
Cancelled, or Failed). The JoinHandle is never .abort()-ed
(Crux R2).
§Errors
AwaitError::NotFound— no session with the given id exists.
Sourcepub fn spawn_gc_task(&self, ttl: Duration, interval: Duration)
pub fn spawn_gc_task(&self, ttl: Duration, interval: Duration)
Spawn a background GC task that periodically evicts idle, terminal sessions.
Mirrors the legacy SessionRegistry::spawn_gc_task contract (Crux #3 legacy
parity) with two extensions:
- Subscriber-count gate (Crux #1): a session is only evicted when
bus_tx.receiver_count() == 0at the moment the write guard is held, ensuring no use-after-eviction for active observers. - Parameterised
interval(Crux #2): callers can supply a sub-second interval for test determinism without requiringtokio::time::pause.
The JoinHandle returned by tokio::spawn is intentionally dropped —
the task runs until process exit (legacy fire-and-forget contract).
§K-4 invariant
The sessions write guard is acquired once per GC tick. All operations
inside the guard (receiver_count(), AtomicI64::load, HashMap::remove)
are synchronous — no .await is called while the guard is held.
Trait Implementations§
Source§impl Clone for SessionRegistryV2
impl Clone for SessionRegistryV2
Source§fn clone(&self) -> SessionRegistryV2
fn clone(&self) -> SessionRegistryV2
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreAuto Trait Implementations§
impl !RefUnwindSafe for SessionRegistryV2
impl !UnwindSafe for SessionRegistryV2
impl Freeze for SessionRegistryV2
impl Send for SessionRegistryV2
impl Sync for SessionRegistryV2
impl Unpin for SessionRegistryV2
impl UnsafeUnpin for SessionRegistryV2
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreimpl<T> MaybeSend for Twhere
T: Send,
Source§impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
impl<SS, SP> SupersetOf<SS> for SPwhere
SS: SubsetOf<SP>,
Source§fn to_subset(&self) -> Option<SS>
fn to_subset(&self) -> Option<SS>
self from the equivalent element of its
superset. Read moreSource§fn is_in_subset(&self) -> bool
fn is_in_subset(&self) -> bool
self is actually part of its subset T (and can be converted to it).Source§fn to_subset_unchecked(&self) -> SS
fn to_subset_unchecked(&self) -> SS
self.to_subset but without any property checks. Always succeeds.Source§fn from_subset(element: &SS) -> SP
fn from_subset(element: &SS) -> SP
self to the equivalent element of its superset.