Move live device resolve to direct_control; drop config-service's outbound call - #112
Merged
Anthony Sligar (sligara7) merged 7 commits intoAug 3, 2026
Conversation
A foreign IOC bound to 5064 (another project's simulator) was silently reused as the test IOC, hanging every EPICS test on connect timeouts. DIRECT_CONTROL_TEST_IOC_PORT now picks a free port for both the caproto server and the CA clients.
…tbound HTTP Each backend service must run standalone as well as composed, and the resolver enrichment callback was the one place a dependency arrow reversed: configuration_service called direct_control's /devices/enrich, while direct_control (and everything else) calls configuration_service - the only service-to-service cycle in the system. - direct_control: new POST /api/v1/devices/resolve resolves dotted device addresses to PV names by live introspection, using its registry provider (config-service in http mode, local file in standalone mode) and the existing ophyd-cache walk. Handles the ophyd FormattedComponent runtime placeholders static resolution cannot. Replaces the config-facing /devices/enrich endpoint (its only consumer). - configuration_service: /devices/resolve is now static-only; needs_enrichment is a terminal outcome pointing at direct_control's resolve. The direct-control client, CONFIG_DIRECT_CONTROL_URL, the enrichment cache, and the enrichment_unavailable outcome are removed. The service makes no outbound HTTP calls at all. - OpenAPI schemas regenerated; docs and orientation pages updated.
Both suites pass against 0.21.0 (config 438, direct-control 343); pyproject constraints were already open so CI resolves latest.
The guard pinned config-service's enrich client models against direct_control's published schema. With the enrich client removed and live resolve moved to direct_control, there is no cross-service enrich wire left to pin; the resolve endpoint's request/response shapes are covered by direct_control's own tests and the OpenAPI drift gate.
There was a problem hiding this comment.
Pull request overview
This PR removes the last configuration_service → direct_control dependency cycle by moving the “live” (runtime-placeholder-capable) device address resolution into direct_control as POST /api/v1/devices/resolve, while making configuration_service’s /devices/resolve explicitly static-only and terminal on needs_enrichment.
Changes:
- Added direct_control
POST /api/v1/devices/resolvethat resolves dotted device addresses to PV names via live device instantiation + ophyd-cache walk, using the configured registry provider for specs/PV maps. - Removed the old direct_control
/devices/enrichendpoint and eliminated configuration_service’s outbound direct-control client, cache, andenrichment_unavailableoutcome. - Updated OpenAPI schemas and orientation/integration docs to reflect the new split (static resolve in configuration_service; live resolve in direct_control) and the “configuration never calls out” convention; updated direct_control test IOC port configurability.
Reviewed changes
Copilot reviewed 24 out of 27 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| shared-schema/direct_control.openapi.json | Replaces /devices/enrich with /devices/resolve and adds new resolve request/response/outcome schemas. |
| shared-schema/configuration_service.openapi.json | Updates /devices/resolve description and removes enrichment_unavailable from outcome enum. |
| docs/orientation/side-a.html | Updates the architecture diagram and narrative to reflect direct_control as client on all paths and adds live resolve description. |
| docs/orientation/direct-control-service.html | Updates endpoint list to document POST /api/v1/devices/resolve instead of enrich. |
| docs/orientation/configuration-service.html | Updates key endpoints section to describe static-only resolve and the handoff to direct_control for live resolution. |
| docs/frontend-backend-integration.html | Updates outcome semantics for needs_enrichment and removes enrichment_unavailable guidance. |
| backend/direct_control_service/tests/test_resolve_endpoint.py | Adds new integration tests for the new live resolve endpoint, including a FormattedComponent placeholder case. |
| backend/direct_control_service/tests/test_enrich_endpoint.py | Removes tests for the deleted enrich endpoint. |
| backend/direct_control_service/tests/test_enrich_config_integration.py | Removes integration tests for configuration_service’s removed direct-control enrich client. |
| backend/direct_control_service/tests/conftest.py | Makes the caproto test IOC port overridable and updates registry stub shape for new resolve needs. |
| backend/direct_control_service/src/direct_control/models.py | Introduces resolve request/response/outcome models and makes ok a computed field derived from outcome. |
| backend/direct_control_service/src/direct_control/main.py | Implements POST /api/v1/devices/resolve and removes the old enrich route. |
| backend/direct_control_service/README.md | Documents the new resolve endpoint. |
| backend/direct_control_service/.gitignore | Stops ignoring uv.lock in this service directory. |
| backend/configuration_service/uv.lock | Bumps ophyd-async to 0.21.0. |
| backend/configuration_service/tests/test_resolver_loader_store_fixes.py | Removes tests covering now-deleted direct-control client failure behavior. |
| backend/configuration_service/tests/test_enrichment_fallback.py | Removes resolver enrichment fallback tests since config no longer calls direct_control. |
| backend/configuration_service/tests/test_direct_control_client.py | Removes direct-control client unit tests since the client is deleted. |
| backend/configuration_service/tests/test_classes.py | Removes test-only ophyd classes used solely by enrichment fallback tests. |
| backend/configuration_service/tests/init.py | Updates package rationale docstring after removing the dedicated test_classes module. |
| backend/configuration_service/src/configuration_service/path_resolver.py | Removes ENRICHMENT_UNAVAILABLE and redefines NEEDS_ENRICHMENT as terminal in config-service. |
| backend/configuration_service/src/configuration_service/main.py | Removes direct-control client wiring + enrichment pass; resolve is now single-pass static-only. |
| backend/configuration_service/src/configuration_service/direct_control_client.py | Deletes the direct-control enrichment HTTP client. |
| backend/configuration_service/src/configuration_service/config.py | Removes settings for CONFIG_DIRECT_CONTROL_URL/timeouts used by the deleted client. |
| backend/configuration_service/docs/reference/api.md | Updates API reference to describe needs_enrichment as terminal and point to direct_control resolve. |
| .gitignore | Adds .reflow2/ to ignores. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Anthony Sligar (sligara7)
force-pushed
the
refactor/resolve-in-direct-control
branch
from
August 3, 2026 15:25
7f03873 to
1a2c861
Compare
…ups per device A batch addressing the same device repeatedly now hits the registry once per lookup kind instead of once per address (get_device_pvs has no client-side cache, so a 200-address single-device batch could cost up to 400 sequential HTTP calls). Failed lookups are memoized too. Regression test asserts the call counts.
Anthony Sligar (sligara7)
deleted the
refactor/resolve-in-direct-control
branch
August 3, 2026 16:17
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.
Each backend service must run standalone as well as composed. The resolver enrichment callback was the one place a dependency arrow reversed: configuration_service called direct_control's /devices/enrich, while everything else calls configuration_service — the only service-to-service cycle in the system.
No deployed environment sets CONFIG_DIRECT_CONTROL_URL, and nothing calls the old enriched resolve, so no consumer breaks.
Tests: configuration_service 438 passed; direct_control 343 passed (incl. 13 new resolve-endpoint tests with a live FormattedComponent case); ruff clean on both.