Skip to content

Fix make mongodb failing to start from a clean checkout #113

Description

@conradbzura

Description

make mongodb cannot bring up a working database from a clean checkout. Two independent defects, either of which is fatal on its own.

(a) ensureIndex throws on a namespace that does not exist. scripts/create-indexes.js's ensureIndex helper calls coll.getIndexes() to look for a conflicting index before creating one. On a database where the collection has never been created, that throws rather than returning an empty list:

MongoServerError: ns does not exist: cfdb.jobs

(code: 26, codeName: NamespaceNotFound.) jobs is the first and only collection the script routes through ensureIndex; every other index is a bare db.<coll>.createIndex(), which is immune because createIndex creates the namespace implicitly. set -e at the top of /startup.sh in Dockerfile.mongodb then takes the container down with exit 1, so the failure presents as a container that dies seconds after starting.

(b) The image cannot build at all from a fresh clone. database/ is gitignored (.gitignore:86), so on git clone the directory does not exist and COPY database/ /data/database/ fails the build outright:

ERROR: failed to solve: ... "/database": not found

This has been latent since 2fc98f8 ("Replace file metadata view with concrete collection; Build indexes in Mongo container"), which added the ignore rule and deleted the 4DN dump that c62ce7a had committed, without updating the Dockerfile to match. It only appears to work on developer machines where a stray file such as .DS_Store keeps the directory alive — see #112, which is what let that happen.

Steps to reproduce

git clone <repo> && cd cfdb
make mongodb
docker ps -a   # container exited 1
docker logs mongodb | tail

Expected Behavior

make mongodb brings up a running MongoDB container with all indexes applied, both from a clean checkout with no dump present and from a checkout where a mongodump --gzip tree has been dropped into database/. An absent dump is the normal case, not an error — the database is meant to start empty and be populated with POST /sync.

Root Cause

mongorestore is not part of the failure and needs no change: it handled the dump-less directory correctly, logging 0 document(s) restored and exiting 0.

The fix (already implemented in the working tree on 82-higlass-tileset-endpoints, uncommitted):

  • scripts/create-indexes.js — wrap getIndexes() in a try/catch that treats only NamespaceNotFound as "no existing index to conflict with" and falls through to createIndex, which creates the collection. This is the semantically exact statement; the alternatives (pre-createCollection every collection, or dropping ensureIndex for bare createIndex) both lose the IndexOptionsConflict drop-and-recreate behaviour that ensureIndex exists for.
  • Dockerfile.mongodb — drop COPY database/ in favour of RUN mkdir -p /data/database, and guard the restore on the directory being non-empty. Secondary benefit: the image no longer varies with what a developer happens to have on disk, and obtaining a dump later becomes a container restart rather than a rebuild.
  • Makefile — mount database/ read-only at run time (-v $(CURDIR)/database:/data/database:ro), with mkdir -p database so the mount source always exists.
  • README.md — the Docker Startup section claimed step 1 restores sample data and that POST /sync was optional. Both are false; correct them and note that database/ is the drop-in point for an optional dump.

set -e is deliberately kept. It surfaced a real bug rather than causing one, and a failed restore of a dump that is present should stop the container rather than leave a half-loaded database looking healthy.

Note that the container's index bootstrap still earns its place despite src/cfdb/indexes.py being the app-owned source of truth: the API lifespan ensures the operational set (jobs, locks) on startup, but the data indexes only come from the JS on a database that has never synced. src/cfdb/indexes.py's own docstring records that the JS is retained as the bootstrap for this image, with a test pinning the two in lockstep.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions