Skip to content
Draft
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Session.vim
scripts/*.js
!scripts/frontendScripts.js
!scripts/jestTest.js
!scripts/setupMongo.js
!scripts/startDatabase.js
*.log
*-debug.log*
*-error.log*
Expand Down
4 changes: 2 additions & 2 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@
},
{
"label": "run-mongo",
"command": "mongod",
"command": "npm",
"type": "process",
"args": ["--dbpath", "${workspaceFolder}/mongo_database"],
"args": ["run", "database"],
"problemMatcher": "$tsc"
}
]
Expand Down
4 changes: 2 additions & 2 deletions Backend/appsettings.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"MongoDB": {
"ConnectionString": "mongodb://localhost:27017",
"ContainerConnectionString": "mongodb://database:27017",
"ConnectionString": "mongodb://localhost:27017/?replicaSet=rs0",
"ContainerConnectionString": "mongodb://database:27017/?replicaSet=rs0",
"CombineDatabase": "CombineDatabase"
},
"Logging": {
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,7 @@ npm run license-report-frontend

To browse the database locally during development, open [MongoDB Compass](https://www.mongodb.com/try/download/compass).

1. Under New Connection, enter `mongodb://localhost:27017`
1. Under New Connection, enter `mongodb://localhost:27017/?replicaSet=rs0`
2. Under Databases, select CombineDatabase

### Add or Update Dictionary Files
Expand Down
31 changes: 31 additions & 0 deletions database/init/00-replica-set.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Initialize the replica set on first startup.
// See: https://www.mongodb.com/docs/manual/tutorial/convert-standalone-to-replica-set/
//
// MONGO_INITDB_REPLICA_HOST can be set to the resolvable hostname:port
// used to advertise this member (e.g. the Kubernetes Service name "database:27017").
// It defaults to "localhost:27017" for local development.
try {
rs.status();
} catch (e) {
print(`Replica set not yet initialized (${e}), initializing now...`);
const host = process.env.MONGO_INITDB_REPLICA_HOST || "localhost:27017";
rs.initiate({ _id: "rs0", members: [{ _id: 0, host: host }] });
// Wait for replica set to reach PRIMARY state before other init scripts run.
const maxWaitMs = 30000;
const intervalMs = 500;
let waited = 0;
let isPrimary = false;
while (!isPrimary && waited < maxWaitMs) {
sleep(intervalMs);
waited += intervalMs;
const status = rs.status();
isPrimary =
status.members !== undefined &&
status.members.some((m) => m.stateStr === "PRIMARY");
}
if (!isPrimary) {
throw new Error(
`Replica set did not reach PRIMARY state after ${maxWaitMs}ms`
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ spec:
- image: {{ include "database.containerImage" . }}
imagePullPolicy: {{ .Values.global.imagePullPolicy }}
name: database
args:
- "--replSet"
- "rs0"
env:
- name: MONGO_INITDB_REPLICA_HOST
value: "database:27017"
ports:
- containerPort: 27017
resources:
Expand Down
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@
"backend": "dotnet watch --project Backend/BackendFramework.csproj",
"build": "parcel build",
"build:analyze": "npm run build -- --reporter @parcel/reporter-bundle-analyzer",
"predatabase": "node scripts/setupMongo.js",
"database": "mongod --dbpath=./mongo_database",
"database": "node scripts/startDatabase.js",
"drop-database": "tsc scripts/dropDB.ts && node scripts/dropDB.js",
"find-circular-deps": "npx --ignore-scripts -y madge -c src/index.tsx --ts-config tsconfig.json",
"fmt-backend": " dotnet format && dotnet format Backend.Tests",
Expand Down
7 changes: 0 additions & 7 deletions scripts/setupMongo.js

This file was deleted.

71 changes: 71 additions & 0 deletions scripts/startDatabase.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
"use strict";

const { spawn, spawnSync } = require("child_process");
const { ensureDir } = require("fs-extra");

const dbPath = "./mongo_database";
const replSetName = "rs0";
const maxAttempts = 30;
const retryInterval = 1000; // ms

async function waitForMongo() {
for (let i = 0; i < maxAttempts; i++) {
const result = spawnSync("mongosh", [
"--eval",
"db.adminCommand('ping')",
"--quiet",
]);
if (result.status === 0) {
return true;
}
await new Promise((resolve) => setTimeout(resolve, retryInterval));
}
return false;
}

async function initReplicaSet() {
const result = spawnSync(
"mongosh",
["--eval", "try { rs.status() } catch(e) { rs.initiate() }", "--quiet"],
{ stdio: "inherit" }
);
return result.status === 0;
}

async function main() {
await ensureDir(dbPath);

const mongod = spawn(
"mongod",
[`--dbpath=${dbPath}`, "--replSet", replSetName],
{
stdio: "inherit",
}
);

mongod.on("error", (err) => {
console.error(`mongod error: ${err.message}`);
process.exit(1);
});

const ready = await waitForMongo();
if (ready) {
await initReplicaSet();
} else {
console.error("MongoDB did not start in time");
}

process.on("SIGINT", () => {
mongod.kill("SIGINT");
});
process.on("SIGTERM", () => {
mongod.kill("SIGTERM");
});

await new Promise((resolve) => mongod.on("close", (code) => resolve(code)));
}

main().catch((err) => {
console.error(err);
process.exit(1);
});