Run locally
Run these commands from the repository root:
cd apps/quicklookup
cp .env.example .env
docker compose -f docker-compose.test.yml up -d
uv sync --frozen --extra test --extra docs
uv run --extra docs mkdocs build --strict
uv run python manage.py migrate
uv run python manage.py seed_uom_catalog
uv run python manage.py sync_ctx_adapters
uv run uvicorn quicklookup.asgi:application --host 127.0.0.1 --port 8090
Run uv run python manage.py run_publication_worker in another terminal. Open
http://127.0.0.1:8090/admin/ for the admin and /docs/ for this site.
Run unit tests while the development catalogue is in use. The contract and integration suites flush the Compose PostgreSQL schema and must use a disposable database.
Preserve the databases
docker compose down stops the stack and keeps its named volumes. Do not use down -v
when the PostgreSQL or ClickHouse contents must survive. Starting the same Compose project
reattaches those volumes.
The integration suite uses the configured Compose PostgreSQL database and flushes the QuickLookup schema. Do not run it while the local UI or another user depends on that catalogue. A volume surviving Docker cleanup does not mean its container, network, or Compose project name survived; inspect the configured volumes before recreating services.
After an intentional test run, these commands reconstruct only the standard UOM and CTX service catalogue from checked-in definitions and the live FDW inventory:
uv run python manage.py migrate
uv run python manage.py seed_uom_catalog
uv run python manage.py sync_ctx_adapters
uv run python manage.py run_publication_worker --once
Run the worker again while ClickHouse projection records remain pending. Customer-created definitions and catalogue grants are not reconstructed by those commands; restore them from a PostgreSQL backup. ClickHouse data volumes are independent, but rows are usable only when their PostgreSQL definitions and grants also exist.
When an upgrade changes the canonical CTX-owned path grammar, stop the API and worker, drain pending projections and observation copies, then use the existing recoverable identity cutover:
uv run python manage.py migrate_gid_namespace --normalize-current-ctx
uv run python manage.py migrate_gid_namespace --normalize-current-ctx --apply \
--backup-dir /private/tmp/NEW-private-backup-directory
uv run python manage.py migrate_gid_namespace --project
uv run python manage.py sync_ctx_adapters
uv run python manage.py audit_series_families --fail-on-blockers
The preview is read-only. Apply copies affected ClickHouse rows, retains their old identities, creates compatibility aliases, corrects dependent immutable publication heads, and refuses to run without a new PostgreSQL backup directory. A repeated preview must report no matching identities before writers restart.
For a deployed, data-bearing catalogue, scale the API and worker to zero through GitOps,
disable the post-sync catalogue job, and run the maintenance image with
QUICKLOOKUP_DB_APPLICATION_NAME=quicklookup-maintenance plus
--normalize-current-ctx --deployed-maintenance --apply. The command refuses to start
while any API/worker database session named by
QUICKLOOKUP_DB_WRITER_APPLICATION_NAME remains.
Verify /healthz, /readyz, the admin catalogue counts, and the publication backlog
before using the restored stack. Then run one stored ClickHouse query and one CTX FDW query
with a representative token.
The same maintenance command repairs family identities created before the canonical
/families/ grammar. Preview first, then use a new backup directory for apply:
uv run python manage.py migrate_gid_namespace --normalize-series-families
uv run python manage.py migrate_gid_namespace --normalize-series-families --apply \
--backup-dir /private/tmp/NEW-private-backup-directory
uv run python manage.py sync_ctx_adapters
uv run python manage.py sync_trading_economics
uv run python manage.py audit_series_families --fail-on-blockers
This mode is limited to the known legacy CTX and Trading Economics family generators. It creates one-hop aliases and corrected immutable heads; the reconciliations then assign the canonical family contracts.