Skip to content
Closed
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
224 changes: 112 additions & 112 deletions scripts/migrations/2026-03-12-consolidate-indexes.mongosh.js
Original file line number Diff line number Diff line change
@@ -1,112 +1,112 @@
"use strict";
if (typeof db === "undefined" || db === null) {
throw new Error("This script must be run inside mongosh.");
}
const CONFIG = {
targetDatabases: [], // Leave empty to run on all discovered tenants
globalDbName: "modl",
serversCollName: "servers"
};
const INDEX_DEFINITIONS = [
{
collection: "system_logs",
indexes: [
{ name: "idx_system_logs_timestamp", keys: { timestamp: -1 } },
{ name: "idx_system_logs_level_timestamp", keys: { level: 1, timestamp: -1 } },
{ name: "idx_system_logs_source_timestamp", keys: { source: 1, timestamp: -1 } }
]
},
{
collection: "security_events",
indexes: [
{ name: "idx_security_events_timestamp", keys: { timestamp: -1 } },
{ name: "idx_security_events_severity_timestamp", keys: { severity: 1, timestamp: -1 } }
]
},
{
collection: "metric_snapshots",
indexes: [
{ name: "idx_metric_snapshots_date", keys: { date: -1 } }
]
},
{
collection: "logs",
indexes: [
{ name: "idx_logs_created", keys: { created: -1 } },
{ name: "idx_logs_source_created", keys: { source: 1, created: -1 } }
]
},
{
collection: "migrations",
indexes: [
{ name: "idx_migrations_status_startedAt", keys: { status: 1, startedAt: -1 } }
]
},
{
collection: "sessions",
indexes: [
{ name: "idx_sessions_email_expiresAt", keys: { email: 1, expiresAt: 1 } }
]
}
];
async function main() {
print(`\n--- Consolidate Indexes Migration ---`);
try {
const serversDb = db.getSiblingDB(CONFIG.globalDbName);
const servers = serversDb.getCollection(CONFIG.serversCollName).find({ databaseName: { $exists: true, $ne: null } }).toArray();
const tenants = CONFIG.targetDatabases.length > 0
? servers.filter(s => CONFIG.targetDatabases.includes(s.databaseName))
: servers;
print(`Targeting ${tenants.length} tenant databases...\n`);
let globalCreated = 0;
let globalSkipped = 0;
for (const tenant of tenants) {
const result = ensureIndexesForTenant(tenant.databaseName);
globalCreated += result.created;
globalSkipped += result.skipped;
print(`[${tenant.databaseName}] Created: ${result.created} | Already existed: ${result.skipped}`);
}
print(`\n--- GLOBAL SUMMARY ---`);
print(`Total indexes created: ${globalCreated}`);
print(`Total indexes already existed: ${globalSkipped}`);
print(`----------------------\n`);
} catch (error) {
print(`\n[FATAL ERROR] Script execution failed: ${error.message}`);
}
}
function ensureIndexesForTenant(databaseName) {
const tenantDb = db.getSiblingDB(databaseName);
let created = 0;
let skipped = 0;
for (const def of INDEX_DEFINITIONS) {
const coll = tenantDb.getCollection(def.collection);
const existing = coll.getIndexes().map(idx => idx.name);
for (const idx of def.indexes) {
if (existing.includes(idx.name)) {
skipped++;
continue;
}
coll.createIndex(idx.keys, { name: idx.name });
created++;
}
}
return { created, skipped };
}
main();
"use strict";

if (typeof db === "undefined" || db === null) {
throw new Error("This script must be run inside mongosh.");
}

const CONFIG = {
targetDatabases: [], // Leave empty to run on all discovered tenants
globalDbName: "modl",
serversCollName: "servers"
};

const INDEX_DEFINITIONS = [
{
collection: "system_logs",
indexes: [
{ name: "idx_system_logs_timestamp", keys: { timestamp: -1 } },
{ name: "idx_system_logs_level_timestamp", keys: { level: 1, timestamp: -1 } },
{ name: "idx_system_logs_source_timestamp", keys: { source: 1, timestamp: -1 } }
]
},
{
collection: "security_events",
indexes: [
{ name: "idx_security_events_timestamp", keys: { timestamp: -1 } },
{ name: "idx_security_events_severity_timestamp", keys: { severity: 1, timestamp: -1 } }
]
},
{
collection: "metric_snapshots",
indexes: [
{ name: "idx_metric_snapshots_date", keys: { date: -1 } }
]
},
{
collection: "logs",
indexes: [
{ name: "idx_logs_created", keys: { created: -1 } },
{ name: "idx_logs_source_created", keys: { source: 1, created: -1 } }
]
},
{
collection: "migrations",
indexes: [
{ name: "idx_migrations_status_startedAt", keys: { status: 1, startedAt: -1 } }
]
},
{
collection: "sessions",
indexes: [
{ name: "idx_sessions_email_expiresAt", keys: { email: 1, expiresAt: 1 } }
]
}
];

async function main() {
print(`\n--- Consolidate Indexes Migration ---`);

try {
const serversDb = db.getSiblingDB(CONFIG.globalDbName);
const servers = serversDb.getCollection(CONFIG.serversCollName).find({ databaseName: { $exists: true, $ne: null } }).toArray();

const tenants = CONFIG.targetDatabases.length > 0
? servers.filter(s => CONFIG.targetDatabases.includes(s.databaseName))
: servers;

print(`Targeting ${tenants.length} tenant databases...\n`);

let globalCreated = 0;
let globalSkipped = 0;

for (const tenant of tenants) {
const result = ensureIndexesForTenant(tenant.databaseName);
globalCreated += result.created;
globalSkipped += result.skipped;
print(`[${tenant.databaseName}] Created: ${result.created} | Already existed: ${result.skipped}`);
}

print(`\n--- GLOBAL SUMMARY ---`);
print(`Total indexes created: ${globalCreated}`);
print(`Total indexes already existed: ${globalSkipped}`);
print(`----------------------\n`);

} catch (error) {
print(`\n[FATAL ERROR] Script execution failed: ${error.message}`);
}
}

function ensureIndexesForTenant(databaseName) {
const tenantDb = db.getSiblingDB(databaseName);
let created = 0;
let skipped = 0;

for (const def of INDEX_DEFINITIONS) {
const coll = tenantDb.getCollection(def.collection);
const existing = coll.getIndexes().map(idx => idx.name);

for (const idx of def.indexes) {
if (existing.includes(idx.name)) {
skipped++;
continue;
}

coll.createIndex(idx.keys, { name: idx.name });
created++;
}
}

return { created, skipped };
}

main();
60 changes: 30 additions & 30 deletions src/main/java/gg/modl/backend/BackendApplication.java
Original file line number Diff line number Diff line change
@@ -1,30 +1,30 @@
package gg.modl.backend;
import io.github.cdimascio.dotenv.Dotenv;
import io.github.cdimascio.dotenv.DotenvException;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
@SpringBootApplication
@ConfigurationPropertiesScan
public class BackendApplication {
public static void main(String[] args) {
loadDotenvIntoSystemProperties();
SpringApplication.run(BackendApplication.class, args);
}
private static void loadDotenvIntoSystemProperties() {
try {
final Dotenv dotenv = Dotenv.configure().ignoreIfMissing().load();
dotenv.entries(Dotenv.Filter.DECLARED_IN_ENV_FILE).forEach(entry ->
System.setProperty(entry.getKey(), entry.getValue())
);
} catch (DotenvException e) {
System.err.println("[BackendApplication] Could not read .env file (it may be a "
+ "directory or unreadable, e.g. an empty bind-mount). Continuing with "
+ "environment/-e variables only. Cause: " + e.getMessage());
}
}
}
package gg.modl.backend;

import io.github.cdimascio.dotenv.Dotenv;
import io.github.cdimascio.dotenv.DotenvException;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;

@SpringBootApplication
@ConfigurationPropertiesScan
public class BackendApplication {
public static void main(String[] args) {
loadDotenvIntoSystemProperties();

SpringApplication.run(BackendApplication.class, args);
}

private static void loadDotenvIntoSystemProperties() {
try {
final Dotenv dotenv = Dotenv.configure().ignoreIfMissing().load();
dotenv.entries(Dotenv.Filter.DECLARED_IN_ENV_FILE).forEach(entry ->
System.setProperty(entry.getKey(), entry.getValue())
);
} catch (DotenvException e) {
System.err.println("[BackendApplication] Could not read .env file (it may be a "
+ "directory or unreadable, e.g. an empty bind-mount). Continuing with "
+ "environment/-e variables only. Cause: " + e.getMessage());
}
}
}
40 changes: 20 additions & 20 deletions src/main/java/gg/modl/backend/Constants.java
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
package gg.modl.backend;
public final class Constants {
public static final String BRAND_NAME = "modl.gg";
private Constants() {}
public static final class Domain {
public static final String API = "api.modl.gg";
public static final String ADMIN = "admin.modl.gg";
public static final String HTTPS_ADMIN = "https://" + ADMIN;
private Domain() {}
}
public static final class Email {
public static final String ADMIN = "admin@modl.gg";
private Email() {}
}
}
package gg.modl.backend;

public final class Constants {
public static final String BRAND_NAME = "modl.gg";

private Constants() {}

public static final class Domain {
public static final String API = "api.modl.gg";
public static final String ADMIN = "admin.modl.gg";
public static final String HTTPS_ADMIN = "https://" + ADMIN;
private Domain() {}
}

public static final class Email {
public static final String ADMIN = "admin@modl.gg";

private Email() {}
}
}
Loading
Loading