Add production hardening: monitoring, backups, caching, and high-traffic resilience
- Recovery middleware (no more crash-on-panic), request metrics/monitoring store + admin API, in-memory TTL caching for read-heavy option/question/ category lookups, gzip + rate-limiting middleware, sanitized chat message encoding, and pg_dump-based database backups with an admin API. - Fix N+1 queries in the discover feed, candidate detail, and match list endpoints by batching selection/photo/user/last-message lookups into single queries instead of one-per-item loops. - Tune DB connection pooling and add HTTP server timeouts + graceful shutdown so the API degrades gracefully instead of falling over under load. - Fix a null (vs empty array) JSON response for candidates/matches without photos or interests, which crashed the web app's swipe card.
This commit is contained in:
@@ -16,6 +16,8 @@ type Handlers struct {
|
||||
Admin *handler.AdminHandler
|
||||
Discovery *handler.DiscoveryHandler
|
||||
Chat *handler.ChatHandler
|
||||
Monitoring *handler.MonitoringHandler
|
||||
Backup *handler.BackupHandler
|
||||
}
|
||||
|
||||
func Setup(
|
||||
@@ -25,6 +27,7 @@ func Setup(
|
||||
userRepo *repository.UserRepository,
|
||||
) {
|
||||
engine.Use(middleware.CORS())
|
||||
engine.Use(middleware.Gzip())
|
||||
|
||||
engine.GET("/health", func(c *gin.Context) {
|
||||
c.JSON(200, gin.H{"status": "ok"})
|
||||
@@ -36,10 +39,13 @@ func Setup(
|
||||
api := engine.Group("/api/v1")
|
||||
|
||||
// -------- احراز هویت (عمومی) --------
|
||||
// درخواست OTP هزینهی پیامک داره و هدف مناسبی برای اسپم/brute-force هست؛
|
||||
// حداکثر ۵ درخواست، بعد هر ثانیه یک توکن شارژ میشه (یعنی حدود ۵ تا در دقیقهی اول و بعدش پیوسته).
|
||||
otpRateLimit := middleware.RateLimiter(5, 1.0/12.0)
|
||||
auth := api.Group("/auth")
|
||||
{
|
||||
auth.POST("/request-otp", h.Auth.RequestOTP)
|
||||
auth.POST("/verify-otp", h.Auth.VerifyOTP)
|
||||
auth.POST("/request-otp", otpRateLimit, h.Auth.RequestOTP)
|
||||
auth.POST("/verify-otp", otpRateLimit, h.Auth.VerifyOTP)
|
||||
auth.POST("/token/refresh", h.Auth.RefreshToken)
|
||||
}
|
||||
|
||||
@@ -106,5 +112,14 @@ func Setup(
|
||||
admin.POST("/profile-questions", h.Admin.CreateQuestion)
|
||||
admin.PATCH("/profile-questions/:id", h.Admin.UpdateQuestion)
|
||||
admin.DELETE("/profile-questions/:id", h.Admin.DeleteQuestion)
|
||||
|
||||
// مانیتورینگ: بار/زمان/ریسپانس درخواستهای اخیر سرور
|
||||
admin.GET("/monitoring/summary", h.Monitoring.Summary)
|
||||
admin.GET("/monitoring/requests", h.Monitoring.RecentRequests)
|
||||
|
||||
// بکآپ دیتابیس
|
||||
admin.GET("/backups", h.Backup.List)
|
||||
admin.POST("/backups", h.Backup.Create)
|
||||
admin.GET("/backups/:filename", h.Backup.Download)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user