pub struct ContainerRuntimeHandle {
slot: RwLock<RuntimeSlot>,
dev_proxy: RwLock<Option<DevProxyRegistry>>,
}Expand description
Self-healing holder for the container runtime connection.
A plain Option<ContainerManager> fixed at process boot means a Docker
daemon that starts (or a socket/named-pipe that appears) AFTER AgentMux
launched is never picked up without an app restart — every consumer
(the availability probe AND the actual container-launch code paths)
would see a permanent None. This type retries on demand instead, so
“start Docker Desktop while AgentMux is already running” is picked up
within one call, everywhere container_manager is read.
See docs/retro/RETRO_DOCKER_DETECTION_DIVERGENCE_2026_07_04.md.
Fields§
§slot: RwLock<RuntimeSlot>§dev_proxy: RwLock<Option<DevProxyRegistry>>Dev-proxy registry to attach to every ContainerManager this handle
ever produces — including across reconnects, each of which creates
a fresh manager instance with its own unset attach_dev_proxy_registry
state. None until set_dev_proxy_registry is called (bootstrap
wires this in once both this handle and the registry exist); tests
using disabled() never set it, and get() never even constructs
a manager in that case. See
docs/specs/SPEC_NATIVE_CONTAINER_DEV_PROXY_2026_09_19.md.
Implementations§
Source§impl ContainerRuntimeHandle
impl ContainerRuntimeHandle
Sourcepub fn connect_at_startup() -> Self
pub fn connect_at_startup() -> Self
Boot-time constructor. Attempts one connect (same as the prior
behavior) but never permanently gives up on failure — a failed
attempt leaves the slot Empty so get()/is_available() retry
later instead of staying stuck for the process lifetime.
Sourcepub fn set_dev_proxy_registry(&self, registry: DevProxyRegistry)
pub fn set_dev_proxy_registry(&self, registry: DevProxyRegistry)
Wire a dev-proxy registry into this handle so every
ContainerManager it produces — now and after any future Docker
reconnect — has stop/remove clear that agent’s routes. Call
once at bootstrap, after both this handle and the registry exist
(see bootstrap::build_app_state).
Sourcepub async fn get(&self) -> Option<ContainerManager>
pub async fn get(&self) -> Option<ContainerManager>
Returns a connected manager, retrying ContainerManager::connect()
if the slot is currently Empty. Cheap on the happy path (a
read-lock plus a cheap Arc-backed clone); only takes the write
lock and re-dials when we don’t already have a manager.
Sourcepub async fn is_available(&self) -> bool
pub async fn is_available(&self) -> bool
True iff a manager is available AND its daemon answers a live ping
right now. Never trusts a cached Connected slot alone — the
daemon can go down again after a successful connect, and
check_available is a real docker.ping(), not a cached flag.
Auto Trait Implementations§
impl !Freeze for ContainerRuntimeHandle
impl !RefUnwindSafe for ContainerRuntimeHandle
impl !UnwindSafe for ContainerRuntimeHandle
impl Send for ContainerRuntimeHandle
impl Sync for ContainerRuntimeHandle
impl Unpin for ContainerRuntimeHandle
impl UnsafeUnpin for ContainerRuntimeHandle
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
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.§impl<T> DowncastSync for T
impl<T> DowncastSync for T
impl<A, B, T> HttpServerConnExec<A, B> for Twhere
B: Body,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> 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 more