exlab_wizard.tray.dependencies#

Production AppDependencies factory. Backend Spec §4.5, §4.6.

The tray entry point constructs every component the FastAPI surface and the NiceGUI wizard need at runtime, packs them into an AppDependencies, and hands the bundle to create_app. Each component is built in its own try/except so a single broken collaborator (absent LIMS endpoint, missing template directory, NAS DB unreachable) degrades to a structured 503 / “unavailable” banner instead of crashing the tray. The pattern mirrors the §4.5 lifespan contract (“best-effort; failure logs WARN”).

The order matters: validator depends on the cache writers, controller composes validator + plugin host + template engine + cache writers, the quiescence poller depends on the NAS-sync queue. We construct upstream pieces first and pass them into downstream constructors; any upstream failure short-circuits the chain so a None upstream produces a None downstream rather than a partially-constructed object.

Functions

apply_live_config(deps, new_config)

Push a freshly saved config.yaml into the running components.

build_production_dependencies(state_dir)

Return a populated AppDependencies for the live tray.

exlab_wizard.tray.dependencies.apply_live_config(deps, new_config)[source]#

Push a freshly saved config.yaml into the running components.

Replaces the old “write config + force a tray relaunch” flow: the settings dialog, the Add-Equipment wizard, and the PUT /config / POST /config/equipment routes all call this after persisting, so a config change takes effect in-process – no restart.

Two regimes per component:

  • Reconfigure – the component already exists (the steady state after setup): its config is swapped in place via apply_config / reconfigure. The validator and NAS-sync client are mutated in place precisely so the controller and poller – which hold references to them – keep working against the same instances.

  • Fresh build – on a first-install save the config-dependent components were built with config=None and are absent; they are constructed here from the now-valid config, and the NAS-sync client + quiescence poller have their async init / start scheduled on the running event loop.

Every step is best-effort and isolated: one component raising logs a WARN and does not abort the rest. deps.config is assigned last so a partial failure still leaves the canonical config readable.

Parameters:
Return type:

None

exlab_wizard.tray.dependencies.build_production_dependencies(state_dir)[source]#

Return a populated AppDependencies for the live tray.

Every per-component construction is wrapped in best-effort error handling: on failure the field is left None and a WARN is logged. The API surface already understands None dependencies (it returns a structured 503 from require_* helpers), and the NiceGUI mount helper wraps each page handler’s dep access in the same try/except so the GUI degrades to an “unavailable” banner.

Parameters:

state_dir (Path)

Return type:

AppDependencies