Skip to content

Convert MongoDB from standalone to replica set#4184

Closed
Copilot wants to merge 25 commits into
masterfrom
copilot/convert-standalone-to-replica-set
Closed

Convert MongoDB from standalone to replica set#4184
Copilot wants to merge 25 commits into
masterfrom
copilot/convert-standalone-to-replica-set

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Feb 26, 2026

MongoDB standalone mode does not support multi-document transactions, which are required for atomic merge operations across FrontierCollection and MergeCollection. This converts to a single-member replica set (rs0) in both development and Docker/Kubernetes environments.

Development (npm start)

  • scripts/startDatabase.js (new): Replaces predatabase+database npm scripts and the now-removed setupMongo.js. Spawns mongod --replSet rs0, polls until ready, calls rs.initiate(), then stays alive until mongod exits. Failures are fatal: SIGINT/SIGTERM handlers are registered early, startup/init failures call process.exit(1), and mongod's exit code is propagated via process.exit(exitCode ?? 1).
  • scripts/setupMongo.js (removed): No longer needed; its directory-creation logic is handled by startDatabase.js.
  • package.json: database script → node scripts/startDatabase.js; predatabase removed.
  • .gitignore: Replaced setupMongo.js exception with startDatabase.js exception.

Docker / Kubernetes

  • database/init/00-replica-set.js (new): Placed in /docker-entrypoint-initdb.d/, runs on first container startup. Calls rs.initiate() with a configurable advertised hostname via MONGO_INITDB_REPLICA_HOST (defaults to localhost:27017). Waits up to 30s for PRIMARY election before allowing subsequent init scripts to run.
  • database.yaml (Kubernetes Helm): Adds args: ["--replSet", "rs0"] and sets MONGO_INITDB_REPLICA_HOST to the pod IP so the replica set member hostname is tracked per pod. The postStart lifecycle hook initializes the replica set on first start and reconfigures the member host (rs.reconfig) when the pod IP changes after a restart, keeping the replica set config in sync.

Configuration

  • appsettings.json: Connection strings now explicitly include ?replicaSet=rs0.
  • .vscode/tasks.json: run-mongo task updated to invoke npm run database (which runs scripts/startDatabase.js) instead of calling mongod directly, ensuring replica set initialization is performed automatically on first run.
  • README.md: MongoDB Compass connection string updated to mongodb://localhost:27017/?replicaSet=rs0.

✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.


This change is Reviewable

Summary by CodeRabbit

  • New Features

    • Enabled MongoDB replica set (rs0) support for both local development and Kubernetes deployments.
    • Improved database initialization with automatic replica set configuration and validation.
  • Documentation

    • Updated MongoDB connection instructions and database maintenance commands with replica set configuration.

Copilot AI and others added 2 commits February 26, 2026 14:26
Co-authored-by: imnasnainaec <6411521+imnasnainaec@users.noreply.github.com>
Co-authored-by: imnasnainaec <6411521+imnasnainaec@users.noreply.github.com>
Copilot AI changed the title [WIP] Convert MongoDB from standalone to replica set Convert MongoDB from standalone to replica set Feb 26, 2026
@imnasnainaec

This comment was marked as resolved.

Co-authored-by: imnasnainaec <6411521+imnasnainaec@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Feb 26, 2026

@copilot Remove setupMongo.js and all references to it, if it's no longer needed.

Done in 34a4308. Removed scripts/setupMongo.js (its ensureDir logic is now handled inside startDatabase.js) and dropped the !scripts/setupMongo.js exception from .gitignore.

@github-actions github-actions Bot added documentation Improvements or additions to documentation backend deployment dependencies Pull requests that update a dependency file labels Feb 26, 2026
@imnasnainaec

This comment was marked as resolved.

Co-authored-by: imnasnainaec <6411521+imnasnainaec@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Feb 26, 2026

@copilot npm run fmt-frontend-check fails.

Fixed in 46d3f10. Ran prettier --write on scripts/startDatabase.js and .vscode/tasks.json. fmt-frontend-check now passes.

@imnasnainaec

This comment was marked as resolved.

@coderabbitai

This comment was marked as outdated.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Feb 26, 2026

Important

Review skipped

Bot user detected.

To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0885ca28-2f11-4866-ba13-f1326546fd58

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Changes convert the MongoDB deployment from a standalone daemon to a single-node replica set: add replica-set init scripts, start/management scripts for local development, Helm/container lifecycle hooks and env, update connection strings, and adjust related tooling/config files.

Changes

Cohort / File(s) Summary
Helm & container runtime
deploy/helm/thecombine/charts/database/templates/database.yaml, database/Dockerfile
Enable mongod --replSet rs0, add postStart lifecycle that waits for mongod and runs replica-set/init and optional semantic-domain update scripts; copy new init scripts into container.
Replica-set init script
database/init/00-replica-set.js
Add startup JS to initialize/ensure a single-node replica set and align advertised host, with polling, reconfig logic, and timeout handling.
Local dev DB orchestration
scripts/startDatabase.js, scripts/setupMongo.js
Add new startDatabase.js that spawns mongod with --replSet, waits for readiness and initiates replica set; remove directory creation from setupMongo.js.
Tooling & tasks
.vscode/tasks.json, package.json, .gitignore
Switch dev task to run npm script; package.json database script now runs node scripts/startDatabase.js and predatabase removed; .gitignore changed to allow scripts/startDatabase.js.
Config & docs
Backend/appsettings.json, README.md, docs/deploy/README.md
Append ?replicaSet=rs0 to MongoDB connection strings and update README path for semantic domains maintenance script.

Sequence Diagram(s)

sequenceDiagram
  participant K8s as "Kubernetes Pod"
  participant Container as "DB Container\n(entrypoint + postStart)"
  participant Mongod as "mongod"
  participant InitJS as "00-replica-set.js"
  participant App as "Application / Client"

  K8s->>Container: start pod -> run container
  Container->>Mongod: launch mongod (--replSet rs0)
  Container->>Container: postStart: wait for mongod ready
  Container->>InitJS: execute /opt/thecombine/00-replica-set.js
  InitJS->>Mongod: connect via mongosh, run rs.initiate / rs.reconfig
  Mongod-->>InitJS: PRIMARY confirmed
  App->>Mongod: connect using mongodb://.../?replicaSet=rs0
  Mongod-->>App: accept connections (replica-set primary)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

Suggested labels

goal, 🟥High

Suggested reviewers

  • jasonleenaylor

Poem

"I’m a rabbit with a tiny spade,
I dug a trench where replicas trade,
One node stands tall, configured just right,
I hop and cheer through the long night,
Databases hum — what a lovely sight! 🐇"

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and accurately summarizes the primary change: converting MongoDB from standalone mode to replica set mode across development, Docker, and Kubernetes environments.
Docstring Coverage ✅ Passed Docstring coverage is 81.82% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch copilot/convert-standalone-to-replica-set
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
deploy/helm/thecombine/charts/database/templates/database.yaml (1)

49-54: Consider parameterizing replica-set values in chart config.

rs0 and database:27017 are hardcoded here. Moving them to Helm values reduces drift risk across deployment, scripts, and connection strings.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@deploy/helm/thecombine/charts/database/templates/database.yaml` around lines
49 - 54, The template hardcodes the replica set name and host/port; change
database/templates/database.yaml to use Helm values instead of "rs0" and
"database:27017" by replacing the args entry ("--replSet", "rs0") and the env
var MONGO_INITDB_REPLICA_HOST value with templated values (e.g.,
.Values.database.replicaSetName and .Values.database.hostPort or similar), and
add corresponding defaults in values.yaml (e.g., database.replicaSetName: "rs0",
database.hostPort: "database:27017"); ensure the template uses proper Helm
quoting/template syntax so the rendered args and env.value are valid.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.vscode/tasks.json:
- Around line 30-38: The "run-mongo" VSCode task currently invokes "mongod"
directly with args ("--dbpath", "${workspaceFolder}/mongo_database",
"--replSet", "rs0") which enables replica-set mode but does not run
rs.initiate(), causing first-run connection failures; update the "run-mongo"
task to run the existing initialization script instead (invoke "npm run
database" or the equivalent npm script used to start and initialize the DB) so
the startup sequence performs replica set initialization automatically; keep the
task label "run-mongo" and replace the "command":"mongod" invocation with a
command that runs the npm script (ensuring the task type and args are adjusted
to execute the npm script).

In `@scripts/startDatabase.js`:
- Around line 51-66: The startup currently logs readiness/init failures and
drops mongod exit codes, allowing the process to succeed incorrectly; update the
logic around waitForMongo() and initReplicaSet() (functions referenced) to treat
failures as fatal (throw or return falsy should cause process.exit with a
non-zero code), ensure initReplicaSet() errors are awaited and checked (or
caught and cause process.exit(1)), and replace the final Promise that resolves
the mongod "close" event with logic that reads the child process exit code and
calls process.exit(code || 1) so any non-zero or unexpected termination results
in a non-zero exit; also ensure the SIGINT/SIGTERM handlers forward termination
(stop/kill mongod) but do not swallow failure—propagate error/exit accordingly.

---

Nitpick comments:
In `@deploy/helm/thecombine/charts/database/templates/database.yaml`:
- Around line 49-54: The template hardcodes the replica set name and host/port;
change database/templates/database.yaml to use Helm values instead of "rs0" and
"database:27017" by replacing the args entry ("--replSet", "rs0") and the env
var MONGO_INITDB_REPLICA_HOST value with templated values (e.g.,
.Values.database.replicaSetName and .Values.database.hostPort or similar), and
add corresponding defaults in values.yaml (e.g., database.replicaSetName: "rs0",
database.hostPort: "database:27017"); ensure the template uses proper Helm
quoting/template syntax so the rendered args and env.value are valid.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bd576b9 and 46d3f10.

📒 Files selected for processing (9)
  • .gitignore
  • .vscode/tasks.json
  • Backend/appsettings.json
  • README.md
  • database/init/00-replica-set.js
  • deploy/helm/thecombine/charts/database/templates/database.yaml
  • package.json
  • scripts/setupMongo.js
  • scripts/startDatabase.js
💤 Files with no reviewable changes (1)
  • scripts/setupMongo.js

Comment thread .vscode/tasks.json Outdated
Comment thread scripts/startDatabase.js Outdated
@imnasnainaec

This comment was marked as resolved.

Co-authored-by: imnasnainaec <6411521+imnasnainaec@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Feb 26, 2026

@copilot
In .vscode/tasks.json around lines 30 - 38, The "run-mongo" VSCode task currently invokes "mongod" directly with args ("--dbpath", "${workspaceFolder}/mongo_database", "...

Fixed in d0942b0. The run-mongo task now runs npm run database (which executes scripts/startDatabase.js to spawn mongod and call rs.initiate()) instead of invoking mongod directly.

@imnasnainaec
Copy link
Copy Markdown
Collaborator

@copilot In deploy/helm/thecombine/charts/database/templates/database.yaml, the postStart lifecycle hook (lines 52-70) needs to be updated so that when rs.status() succeeds (replica set already initialized), it also checks whether the current member host matches the value of MONGO_INITDB_REPLICA_HOST. If they differ (which happens after a pod restart with a new IP), it should reconfigure the replica set member to use the new host. The mongosh --eval script on line 63 should be changed from:

try { rs.status(); print('Replica set already initialized'); } catch (e) { ... }

to something like:

const host = '${MONGO_INITDB_REPLICA_HOST}'; try { rs.status(); const conf = rs.conf(); if (conf.members[0].host !== host) { print('Updating replica set member host to ' + host); conf.members[0].host = host; conf.version++; rs.reconfig(conf); } else { print('Replica set already initialized with correct host'); } } catch (e) { print('Initializing replica set (' + e + ')'); rs.initiate({_id: 'rs0', members: [{_id: 0, host: host}]}); }

This ensures the replica set member address stays in sync with the current pod IP after restarts.

…d restart

Co-authored-by: imnasnainaec <6411521+imnasnainaec@users.noreply.github.com>
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 11, 2026

@copilot In deploy/helm/thecombine/charts/database/templates/database.yaml, the postStart lifecycle hook (lines 52-70) needs to be updated so that when rs.status() succeeds (replica ...

Fixed in 369677c. The postStart mongosh --eval script now checks conf.members[0].host against MONGO_INITDB_REPLICA_HOST when rs.status() succeeds, and calls rs.reconfig(conf) to update the member address if they differ. This keeps the replica set member host in sync after pod restarts with new IPs.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Mar 11, 2026

⚠️ Commit Message Format Issues ⚠️
commit 369677ce45:
1: T1 Title exceeds max length (78>72): "Update postStart hook to reconfigure replica set member host after pod restart"

@imnasnainaec

This comment was marked as resolved.

@coderabbitai

This comment was marked as outdated.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (1)
scripts/startDatabase.js (1)

35-39: ⚠️ Potential issue | 🟠 Major

Still hard-killing mongod on Ctrl+C / SIGTERM.

Line 37 and Lines 61-63 still funnel shutdown through forceExit(), and Lines 43-56 immediately send SIGKILL before process.exit(). That leaves local stops as unclean MongoDB shutdowns and bypasses the child exit propagation in Lines 150-159 on signal-driven exits.

Also applies to: 43-56, 61-64, 150-159

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/startDatabase.js` around lines 35 - 39, The current Ctrl+C / SIGTERM
handlers call forceExit() and send SIGKILL immediately which causes unclean
mongod shutdowns and bypasses the child exit propagation; change the keypress
and signal handlers (the process.stdin.on("keypress") handler and SIGINT/SIGTERM
listeners) to attempt a graceful shutdown by sending SIGTERM to the mongod child
process (use the existing child process variable and its .kill('SIGTERM')
method), then wait for the child's 'exit' event (or a short timeout fallback)
before calling forceExit() as a last resort; remove any immediate SIGKILL/send
of SIGKILL prior to waiting so the child exit propagation code (the
child.on('exit') logic) runs on signal-driven exits.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@deploy/helm/thecombine/charts/database/templates/database.yaml`:
- Around line 69-72: The postStart hook uses the construct `if ! mongosh --quiet
--host 127.0.0.1 /opt/thecombine/00-replica-set.js; then exit $?; fi` which ends
up using the exit status of the `!` operator instead of the original `mongosh`
exit code; update the hook around the `mongosh` invocation (the postStart block
calling 00-replica-set.js) so that you capture the actual exit status of
`mongosh` and propagate it as the container exit (e.g., run `mongosh` and
store/inspect its exit code, then `exit` with that code when it fails) to ensure
a failing replica set check prevents the pod from starting.

In `@scripts/startDatabase.js`:
- Around line 115-124: initReplicaSet currently returns as soon as rs.initiate
is accepted but doesn't wait for the node to become PRIMARY; add a new
waitForPrimary() that polls mongosh evaluating db.hello().isWritablePrimary with
the existing retry pattern (use maxAttempts and retryIntervalSeconds like
waitForMongo()), make initReplicaSet remain responsible for initiating the set
and in main() call waitForPrimary() after initReplicaSet() succeeds so the
startup waits until the replica set member is elected PRIMARY before proceeding.

---

Duplicate comments:
In `@scripts/startDatabase.js`:
- Around line 35-39: The current Ctrl+C / SIGTERM handlers call forceExit() and
send SIGKILL immediately which causes unclean mongod shutdowns and bypasses the
child exit propagation; change the keypress and signal handlers (the
process.stdin.on("keypress") handler and SIGINT/SIGTERM listeners) to attempt a
graceful shutdown by sending SIGTERM to the mongod child process (use the
existing child process variable and its .kill('SIGTERM') method), then wait for
the child's 'exit' event (or a short timeout fallback) before calling
forceExit() as a last resort; remove any immediate SIGKILL/send of SIGKILL prior
to waiting so the child exit propagation code (the child.on('exit') logic) runs
on signal-driven exits.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f52f0ac3-f410-465b-b3a7-95cecbd87a08

📥 Commits

Reviewing files that changed from the base of the PR and between 36d0f2f and 6aadfbe.

📒 Files selected for processing (7)
  • .gitignore
  • database/Dockerfile
  • database/init/00-replica-set.js
  • deploy/helm/thecombine/charts/database/templates/database.yaml
  • docs/deploy/README.md
  • package.json
  • scripts/startDatabase.js
🚧 Files skipped from review as they are similar to previous changes (1)
  • .gitignore

Comment thread deploy/helm/thecombine/charts/database/templates/database.yaml Outdated
Comment thread scripts/startDatabase.js
Comment on lines +115 to +124
async function initReplicaSet() {
try {
const result = runMongosh(
[
"--eval",
`try { rs.status() } catch { rs.initiate({ _id: '${replSetName}', members: [{ _id: 0, host: 'localhost:27017' }] }) }`,
],
{ stdio: "inherit" }
);
return result.status === 0;
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot Mar 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "[scripts/startDatabase.js]"
sed -n '115,168p' scripts/startDatabase.js

echo
echo "[database/init/00-replica-set.js]"
sed -n '37,65p' database/init/00-replica-set.js

Repository: sillsdev/TheCombine

Length of output: 2181


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Full context of scripts/startDatabase.js ==="
wc -l scripts/startDatabase.js

echo
echo "=== Lines 1-50 (variable definitions) ==="
sed -n '1,50p' scripts/startDatabase.js

echo
echo "=== Lines 150-170 (checking the 'Also applies to' lines) ==="
sed -n '150,170p' scripts/startDatabase.js

echo
echo "=== Searching for maxAttempts and retryIntervalSeconds ==="
rg "maxAttempts|retryIntervalSeconds" scripts/startDatabase.js

Repository: sillsdev/TheCombine

Length of output: 2202


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== waitForMongo function (to see the retry pattern) ==="
sed -n '65,110p' scripts/startDatabase.js

echo
echo "=== runMongosh function (to verify how it's called) ==="
rg -A 5 "function runMongosh" scripts/startDatabase.js

echo
echo "=== Check getErrorMessage function ==="
rg -A 3 "function getErrorMessage" scripts/startDatabase.js

Repository: sillsdev/TheCombine

Length of output: 1708


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Checking the complete main() function (lines 130-174) ==="
sed -n '130,174p' scripts/startDatabase.js

echo
echo "=== Verify package.json line 30 to confirm parallel startup ==="
sed -n '25,35p' package.json

Repository: sillsdev/TheCombine

Length of output: 2118


Add PRIMARY readiness check after replica set initialization.

initReplicaSet() returns success as soon as rs.initiate() is accepted, but the replica set member is not usable until it elects itself PRIMARY. Since package.json starts backend and database in parallel (line 30: run-p), the startup can race this window. The Kubernetes bootstrap in database/init/00-replica-set.js already implements the correct pattern with db.hello().isWritablePrimary; apply the same here.

Add a waitForPrimary() function that polls for db.hello().isWritablePrimary with the same retry pattern as waitForMongo(), then call it in main() after initReplicaSet() succeeds. Required variables (maxAttempts, retryIntervalSeconds) are already defined.

Suggested fix
 async function initReplicaSet() {
   try {
     const result = runMongosh(
       [
         "--eval",
         `try { rs.status() } catch { rs.initiate({ _id: '${replSetName}', members: [{ _id: 0, host: 'localhost:27017' }] }) }`,
       ],
       { stdio: "inherit" }
     );
     return result.status === 0;
   } catch (error) {
     console.error(`Replica set init failed: ${getErrorMessage(error)}`);
     return false;
   }
 }
+
+async function waitForPrimary() {
+  for (let i = 0; i < maxAttempts; i++) {
+    try {
+      const result = runMongosh([
+        "--eval",
+        "quit(db.hello().isWritablePrimary ? 0 : 1)",
+      ]);
+      if (result.status === 0) {
+        return true;
+      }
+    } catch (error) {
+      console.warn(`MongoDB primary check failed: ${getErrorMessage(error)}`);
+    }
+
+    await new Promise((res) => setTimeout(res, retryIntervalSeconds * 1000));
+  }
+
+  return false;
+}
 
 async function main() {
   setUpInterruptHandling();
@@ -161,6 +181,10 @@ async function main() {
   if (!(await initReplicaSet())) {
     console.error("Replica set initialization failed");
     forceExit(1);
   }
+  if (!(await waitForPrimary())) {
+    console.error("Replica set did not become PRIMARY in time");
+    forceExit(1);
+  }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@scripts/startDatabase.js` around lines 115 - 124, initReplicaSet currently
returns as soon as rs.initiate is accepted but doesn't wait for the node to
become PRIMARY; add a new waitForPrimary() that polls mongosh evaluating
db.hello().isWritablePrimary with the existing retry pattern (use maxAttempts
and retryIntervalSeconds like waitForMongo()), make initReplicaSet remain
responsible for initiating the set and in main() call waitForPrimary() after
initReplicaSet() succeeds so the startup waits until the replica set member is
elected PRIMARY before proceeding.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this fixed?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "=== Search for waitForPrimary in startDatabase.js ==="
rg -n "waitForPrimary" scripts/startDatabase.js || echo "NOT FOUND"

echo
echo "=== Full file content ==="
cat scripts/startDatabase.js

Length of output: 4305


@imnasnainaec, not yet fixed. The waitForPrimary() function is absent from scripts/startDatabase.js, and main() still returns immediately after initReplicaSet() without polling for PRIMARY election. The race condition with run-p (parallel backend + database startup) remains.

Here's the change needed — it slots cleanly between initReplicaSet and main:

/** Wait until the replica set member becomes PRIMARY. */
async function waitForPrimary() {
  for (let i = 0; i < maxAttempts; i++) {
    try {
      const result = runMongosh([
        "--eval",
        "quit(db.hello().isWritablePrimary ? 0 : 1)",
      ]);
      if (result.status === 0) {
        return true;
      }
    } catch (error) {
      console.warn(`MongoDB primary check failed: ${getErrorMessage(error)}`);
    }
    if (i < maxAttempts - 1) {
      await new Promise((res) => setTimeout(res, retryIntervalSeconds * 1000));
    }
  }
  return false;
}

And in main(), after the existing initReplicaSet block:

  if (!(await waitForPrimary())) {
    console.error("Replica set did not become PRIMARY in time");
    forceExit(1);
  }

@imnasnainaec imnasnainaec marked this pull request as ready for review March 13, 2026 19:20
@imnasnainaec imnasnainaec marked this pull request as draft March 13, 2026 19:24
@imnasnainaec
Copy link
Copy Markdown
Collaborator

Subsumed in #4198

@imnasnainaec imnasnainaec deleted the copilot/convert-standalone-to-replica-set branch March 19, 2026 14:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend dependencies Pull requests that update a dependency file deployment docker documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants