feat: complete MongoDB to CouchDB migration

- Migrate Report model to CouchDB with embedded street/user data
- Migrate UserBadge model to CouchDB with badge population
- Update all remaining routes (reports, users, badges, payments) to use CouchDB
- Add CouchDB health check and graceful shutdown to server.js
- Add missing methods to couchdbService (checkConnection, findWithPagination, etc.)
- Update Kubernetes deployment manifests for CouchDB support
- Add comprehensive CouchDB setup documentation

All core functionality now uses CouchDB as primary database while maintaining
MongoDB for backward compatibility during transition period.

🤖 Generated with [AI Assistant]

Co-Authored-By: AI Assistant <noreply@ai-assistant.com>
This commit is contained in:
William Valentin
2025-11-01 13:29:48 -07:00
parent 9ac21fca72
commit df94c17e1f
14 changed files with 684 additions and 155 deletions

View File

@@ -72,7 +72,10 @@ mongoose
// CouchDB (primary database)
couchdbService.initialize()
.then(() => console.log("CouchDB initialized"))
.catch((err) => console.log("CouchDB initialization error:", err));
.catch((err) => {
console.log("CouchDB initialization error:", err);
process.exit(1); // Exit if CouchDB fails to initialize since it's the primary database
});
// Socket.IO Authentication Middleware
io.use(socketAuth);
@@ -123,13 +126,27 @@ app.use("/api/auth/login", authLimiter);
app.use("/api", apiLimiter);
// Health check endpoint (for Kubernetes liveness/readiness probes)
app.get("/api/health", (req, res) => {
res.status(200).json({
status: "healthy",
timestamp: new Date().toISOString(),
uptime: process.uptime(),
mongodb: mongoose.connection.readyState === 1 ? "connected" : "disconnected",
});
app.get("/api/health", async (req, res) => {
try {
const couchdbStatus = await couchdbService.checkConnection();
res.status(200).json({
status: "healthy",
timestamp: new Date().toISOString(),
uptime: process.uptime(),
mongodb: mongoose.connection.readyState === 1 ? "connected" : "disconnected",
couchdb: couchdbStatus ? "connected" : "disconnected",
});
} catch (error) {
res.status(503).json({
status: "unhealthy",
timestamp: new Date().toISOString(),
uptime: process.uptime(),
mongodb: mongoose.connection.readyState === 1 ? "connected" : "disconnected",
couchdb: "disconnected",
error: error.message,
});
}
});
// Routes
@@ -156,3 +173,42 @@ app.use(errorHandler);
server.listen(port, () => {
console.log(`Server running on port ${port}`);
});
// Graceful shutdown
process.on("SIGTERM", async () => {
console.log("SIGTERM received, shutting down gracefully");
try {
// Close MongoDB connection
await mongoose.connection.close();
console.log("MongoDB connection closed");
// Close server
server.close(() => {
console.log("Server closed");
process.exit(0);
});
} catch (error) {
console.error("Error during shutdown:", error);
process.exit(1);
}
});
process.on("SIGINT", async () => {
console.log("SIGINT received, shutting down gracefully");
try {
// Close MongoDB connection
await mongoose.connection.close();
console.log("MongoDB connection closed");
// Close server
server.close(() => {
console.log("Server closed");
process.exit(0);
});
} catch (error) {
console.error("Error during shutdown:", error);
process.exit(1);
}
});