Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
8 changes: 8 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,16 @@ ANALYTICS_CONTRACT_ID=your_analytics_contract_id_here
ADMIN_PRIVATE_KEY=your_admin_secret_key_here

# Database Configuration
# PostgreSQL is the primary relational store (users, enrollments, payments,
# courses, etc.). MongoDB is the document store used by mongoose-backed
# services (content delivery, notifications, offline sync, quizzes,
# translations, whiteboard sessions, ...).
DATABASE_URL=postgresql://username:password@localhost:5432/aethermint_education
REDIS_URL=redis://localhost:6379
# MongoDB connection string. Required at startup: the backend fails fast if
# this is unset while Mongoose models are registered, so index synchronization
# and mongoose-backed routes never silently run without a database.
MONGODB_URI=mongodb://localhost:27017/aethermint

# Database Backup Configuration (used by scripts/backup-db.sh & db-backup workflow)
# Target bucket and optional key prefix for uploaded backups.
Expand Down
18 changes: 18 additions & 0 deletions backend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,26 @@ NODE_ENV=development
LOG_LEVEL=debug
DATABASE_URL=postgresql://user:password@localhost:5432/db
REDIS_URL=redis://localhost:6379
MONGODB_URI=mongodb://localhost:27017/aethermint
```

### Databases

The backend uses two databases with distinct responsibilities:

- **PostgreSQL** (via `DATABASE_URL`) is the primary relational store. It holds
transactional data — users, enrollments, payments, courses, and audit logs —
and is managed through SQL migrations in `backend/migrations/`.
- **MongoDB** (via `MONGODB_URI`) is the document store used by Mongoose-backed
services: content delivery and versions, notifications, offline sync,
quizzes and assignments, translations, whiteboard sessions, and similar
document-shaped data.

`MONGODB_URI` is required at startup: the backend fails fast if Mongoose models
are registered but no MongoDB URI is configured, so index synchronization and
Mongoose-backed routes never silently run without a database. `docker-compose.yml`
provides a `mongodb` service and wires `MONGODB_URI` for the backend container.

### Logger Configuration
Logs are written to:
- `logs/error.log` - Error logs only
Expand Down
23 changes: 17 additions & 6 deletions backend/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -471,9 +471,25 @@ const PORT = process.env.PORT || 3001;
*/
async function ensureMongooseIndexes(): Promise<void> {
const mongoUri = process.env.MONGODB_URI || process.env.MONGO_URI;
const modelNames = mongoose.modelNames();

// Fail fast when Mongoose models are registered but no MongoDB URI is
// configured. Continuing would silently skip index synchronization and
// leave mongoose-backed routes behaving as if no database existed.
// (Issue #471)
if (!mongoUri && modelNames.length > 0) {
throw new Error(
'MongoDB is not configured: MONGODB_URI is unset while Mongoose models are ' +
'registered. Set MONGODB_URI in your environment (see .env.example).'
);
}

if (!mongoUri) {
return;
}

// Attempt to connect if a MongoDB URI is configured and not yet connected
if (mongoUri && mongoose.connection.readyState !== 1) {
if (mongoose.connection.readyState !== 1) {
try {
await mongoose.connect(mongoUri);
logger.info('MongoDB connected for index synchronization');
Expand All @@ -483,11 +499,6 @@ async function ensureMongooseIndexes(): Promise<void> {
}
}

if (mongoose.connection.readyState !== 1) {
return;
}

const modelNames = mongoose.modelNames();
if (modelNames.length === 0) return;

logger.info(`Ensuring Mongoose indexes for ${modelNames.length} model(s)...`);
Expand Down