feat(deploy): konteyner başlatma adımı ve sağlık kontrolünde replica set

- scripts/bootstrap.ts: replica set/PRIMARY kontrolü, migration'lar, production'da ilk admin
- esbuild ile tek dosya (dist/bootstrap.mjs), docker-entrypoint.sh ile uygulamadan önce
- /api/health yanıtında replicaSet alanı; healthcheck başlangıç payı 60 sn

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-07 02:13:10 +03:00
parent 42561b570a
commit 7d7dd61c60
9 changed files with 80 additions and 5 deletions
+43
View File
@@ -0,0 +1,43 @@
/**
* Canlı başlatma (Docker entrypoint, uygulamadan önce): replica set kontrolü, bekleyen migration'lar
* ve SEED_ADMIN_* tanımlıysa ilk admin hesabı (varsa dokunulmaz). İdempotent; her deploy'da çalışır.
* İmajda esbuild ile tek dosyaya derlenir (scripts/bootstrap.mjs). Lokal: npm run bootstrap
*/
import mongoose from "mongoose";
import { getDb, getMongoClient } from "@/lib/db/mongo";
import { env } from "@/lib/env";
import { runMigrations } from "./migrations";
import { closeSeedConnections, runSeed } from "./seed/run";
async function main() {
const e = env();
const hello = await getDb().admin().command({ hello: 1 });
if (!hello.setName) {
throw new Error(
"MongoDB replica set olarak çalışmıyor; transaction'lı yazmalar başarısız olur. " +
"docs/DEPLOY.md › 'MongoDB replica set' adımlarını uygulayın.",
);
}
if (!hello.isWritablePrimary) throw new Error("MongoDB düğümü PRIMARY değil (yazılamaz).");
console.log(`• MongoDB ${hello.setName} PRIMARY`);
if (e.NODE_ENV === "production" && e.SEED_ADMIN_EMAIL && e.SEED_ADMIN_PASSWORD) {
// Production'da seed yalnızca migration + admin yapar (örnek veri oluşturulmaz).
await runSeed();
} else {
await runMigrations();
if (e.NODE_ENV === "production")
console.log("• SEED_ADMIN_* tanımlı değil; admin kontrolü atlandı.");
}
}
main()
.catch((err: unknown) => {
console.error(`✗ Başlatma hatası: ${err instanceof Error ? err.message : err}`);
process.exitCode = 1;
})
.finally(async () => {
await closeSeedConnections();
await mongoose.disconnect();
await getMongoClient().close();
});