CDM Adapter
CDMAdapter holds the primary engine, vocabulary engine, and routed session factory for a resolved CDM database. It is the shared connection layer used by VocabService and OmopGraphAdapter.
What it is
CDMAdapter is a thin connection-management object. It does not issue queries itself. Its purpose is to:
- hold the primary and vocabulary
sqlalchemy.Engineobjects - expose a routed session factory for callers that query role-tagged OMOP tables
- be constructed once per CDM database in
build_application()and shared across the components that need it
Who uses it
| Component | How |
|---|---|
VocabService |
Takes a CDMAdapter as its only constructor argument. Uses the session factory to open per-call sessions for vocabulary table queries. |
OmopGraphAdapter |
Uses the routed session factory so vocabulary and primary-role graph tables reach their configured databases. |
The adapter is created once per CDM database at application startup and wired through build_application(). It is not per-request.
Construction
CDMAdapter is config-agnostic. It accepts an engine and optional routed factory, while build_application() creates them through omop_alchemy.config.create_cdm_engines() and omop_alchemy.cross_database.cdm_sessionmaker():
- the adapter remains testable by passing a SQLite engine directly
- changing the connection source means changing
build_application()only;CDMAdapterand every service that uses it are untouched
Usage from build_application()
from groundworkers.app import build_application
from groundworkers.bootstrap import build_app_config
config = build_app_config()
app = build_application(config)
# CDMAdapter is available at:
app.adapters.cdm
VocabService is wired automatically:
app.services.vocab # backed by app.adapters.cdm
Lifecycle
build_app_config() creates role engines through create_cdm_engines(..., register_claims=False). Startup fails fast when either database role is unreachable and prints the scrubbed reason with a database recovery hint. CDMAdapter.is_available() also performs a lightweight Core query (SELECT 1).
close() disposes both role engines. Call it explicitly in teardown (for example in a test fixture yield/finally block) when you need to ensure connections are returned promptly. Process-level startup and shutdown wiring belongs in the application or transport layer, not in the adapter itself.