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.
Description
make mongodbcannot bring up a working database from a clean checkout. Two independent defects, either of which is fatal on its own.(a)
ensureIndexthrows on a namespace that does not exist.scripts/create-indexes.js'sensureIndexhelper callscoll.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:(
code: 26,codeName: NamespaceNotFound.)jobsis the first and only collection the script routes throughensureIndex; every other index is a baredb.<coll>.createIndex(), which is immune becausecreateIndexcreates the namespace implicitly.set -eat the top of/startup.shinDockerfile.mongodbthen 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 ongit clonethe directory does not exist andCOPY database/ /data/database/fails the build outright: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 thatc62ce7ahad committed, without updating the Dockerfile to match. It only appears to work on developer machines where a stray file such as.DS_Storekeeps the directory alive — see #112, which is what let that happen.Steps to reproduce
Expected Behavior
make mongodbbrings up a running MongoDB container with all indexes applied, both from a clean checkout with no dump present and from a checkout where amongodump --gziptree has been dropped intodatabase/. An absent dump is the normal case, not an error — the database is meant to start empty and be populated withPOST /sync.Root Cause
mongorestoreis not part of the failure and needs no change: it handled the dump-less directory correctly, logging0 document(s) restoredand exiting 0.The fix (already implemented in the working tree on
82-higlass-tileset-endpoints, uncommitted):scripts/create-indexes.js— wrapgetIndexes()in a try/catch that treats onlyNamespaceNotFoundas "no existing index to conflict with" and falls through tocreateIndex, which creates the collection. This is the semantically exact statement; the alternatives (pre-createCollectionevery collection, or droppingensureIndexfor barecreateIndex) both lose theIndexOptionsConflictdrop-and-recreate behaviour thatensureIndexexists for.Dockerfile.mongodb— dropCOPY database/in favour ofRUN 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— mountdatabase/read-only at run time (-v $(CURDIR)/database:/data/database:ro), withmkdir -p databaseso the mount source always exists.README.md— the Docker Startup section claimed step 1 restores sample data and thatPOST /syncwas optional. Both are false; correct them and note thatdatabase/is the drop-in point for an optional dump.set -eis 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.pybeing 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.