fix(orchestrator): move ItemBase to domain layer to fix circular import#141
Merged
Conversation
ItemBase (id + creation_date) is a domain concept that was misplaced in the interface layer, causing domain → interface dependency inversion.
ConfigManager raised FastAPI HTTPException directly, coupling application logic to the HTTP transport. Replaced with domain exceptions (ConfigNotFoundError, InvalidConfigNameError) mapped to HTTP status codes via exception handlers registered in the interface layer.
uv sync installs the project in editable mode by default, leaving a .pth file pointing to /app/src. Since the runtime stage only copies .venv and not src/, the module is not found at startup. --no-editable forces a proper wheel install so the venv is self-contained. Fixes edge_tflite_serving, edge_camera, and edge_orchestrator containers.
…LDOS arg edge_model_serving.yml had context: .. (pointing to edge/model_serving/) with dockerfile: tflite_serving/Dockerfile. After the multi-stage rewrite, the Dockerfile expects pyproject.toml and src/ at the context root, so the context must be . (the tflite_serving/ directory itself). Also removes the BUILDOS build arg from tflite_serving and orchestrator service files — no Dockerfile declares it anymore.
…uilds docker compose up --build always rebuilds regardless of cache. Separated into vio-edge-build / vio-edge-up (and hub/full equivalents) so images are only rebuilt on explicit request. Also removed the now-unused BUILDOS env var from the vio-* targets (no Dockerfile declares that arg anymore).
… env var CameraConfig had service_url hardcoded to http://localhost:8001. In Docker, configs loaded without an explicit service_url were connecting to localhost instead of the edge_camera container. Now uses CAMERA_SERVICE_URL with localhost fallback for local development.
…Ls in configs
Volume was mounted at /edge_orchestrator/config but CONFIG_DIR=/app/config
in the Dockerfile — configs were never loaded in Docker. Fixed to /app/config.
Also replaced hardcoded localhost URLs in all station configs with env var
interpolation so Docker deployments use service names automatically:
service_url: ${CAMERA_SERVICE_URL:-http://localhost:8001}
model_serving_url: ${SERVING_MODEL_URL:-http://localhost:8501}/
…bugs - Move edge/model_serving/tflite_serving/ → edge/tflite_serving/, promote models/tflite/ contents up to models/ (simpler, flatter layout) - Fix uv sync --no-editable in all three Python Dockerfiles (camera, orchestrator, tflite_serving) to avoid editable .pth breakage in multi-stage builds - Fix docker-compose.yml build context override for edge_model_serving - Fix tflite_interpreter.py and its test: cwd()/models instead of cwd().parent/models after directory restructure - Revert nginx resolver directive; rely on system /etc/resolv.conf for Podman aardvark-dns resolution of edge_orchestrator - Fix Zod CameraInfoSchema: position uses .nullish() to accept null - Fix StatusBar.vue v-for on object to destructure (info, id) correctly - Add Save & Activate button to TechnicianPage config editor - Update CI workflows and root Makefile paths to edge/tflite_serving
- Call healthStore.poll() after config activation so OperatorPage's activeConfig updates immediately instead of waiting for next tick - Use z.nullable() instead of z.nullish() for camera position field (API always sends the key, value is null not absent) - Remove redundant build override for edge_model_serving in docker-compose.yml (context: . now resolves correctly after flatten)
Models are loaded at FastAPI startup — the CI service container starts
before checkout so no volume is available. Baking models in with
COPY models /models makes the image self-contained; in production the
docker-compose volume mount overrides /models as before.
Also remove models/ from .dockerignore and normalize base URLs with
rstrip('/') in _build_model_url and get_models_available.
Pass the config object directly to setActiveConfigName so OperatorPage's activeConfig is updated immediately without a poll() HTTP round-trip. Avoids unhandled network errors in tests and removes the async dependency.
poll() uses Promise.allSettled but crashes synchronously on Object.values(undefined.services) when getServicesHealth returns undefined. Fix: add proper mock return values for getLiveness, getServicesHealth and getActiveConfig in both test files.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
ItemBase (id + creation_date) is a domain concept that was misplaced in the interface layer, causing domain → interface dependency inversion.