mirror of
https://github.com/nprasad2077/NBA_Go.git
synced 2026-09-22 14:05:13 +00:00
PG DB reroute
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/nprasad2077/NBA_Go/models"
|
||||
"github.com/nprasad2077/NBA_Go/utils/security"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/plugin/dbresolver"
|
||||
)
|
||||
|
||||
// very small middleware: require header X‑Admin‑Secret == $ADMIN_SECRET
|
||||
@@ -26,7 +27,8 @@ func RegisterKeyAdminRoutes(app *fiber.App, db *gorm.DB) {
|
||||
|
||||
admin.Get("/", func(c *fiber.Ctx) error {
|
||||
var keys []models.APIKey
|
||||
db.Find(&keys)
|
||||
// Query write DB to guarantee immediate read-after-write consistency
|
||||
db.Clauses(dbresolver.Write).Find(&keys)
|
||||
return c.JSON(keys)
|
||||
})
|
||||
|
||||
@@ -45,7 +47,7 @@ func RegisterKeyAdminRoutes(app *fiber.App, db *gorm.DB) {
|
||||
Hash: security.HashKey(raw),
|
||||
Label: body.Label,
|
||||
}
|
||||
db.Create(&key)
|
||||
db.Clauses(dbresolver.Write).Create(&key)
|
||||
|
||||
// return ONLY the raw key once
|
||||
return c.JSON(fiber.Map{
|
||||
@@ -56,7 +58,7 @@ func RegisterKeyAdminRoutes(app *fiber.App, db *gorm.DB) {
|
||||
|
||||
admin.Post("/:id/revoke", func(c *fiber.Ctx) error {
|
||||
id := c.Params("id")
|
||||
db.Model(&models.APIKey{}).Where("id = ?", id).Update("revoked", true)
|
||||
db.Clauses(dbresolver.Write).Model(&models.APIKey{}).Where("id = ?", id).Update("revoked", true)
|
||||
return c.JSON(fiber.Map{"revoked": id})
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/plugin/dbresolver"
|
||||
)
|
||||
|
||||
type TargetHealth struct {
|
||||
Status string `json:"status"`
|
||||
Target string `json:"target"`
|
||||
LatencyMs float64 `json:"latencyMs"`
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
type ReadinessResponse struct {
|
||||
Status string `json:"status"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Targets map[string]TargetHealth `json:"targets"`
|
||||
}
|
||||
|
||||
// RegisterHealthRoutes mounts /healthz and /readyz probes
|
||||
func RegisterHealthRoutes(app *fiber.App, db *gorm.DB) {
|
||||
app.Get("/healthz", func(c *fiber.Ctx) error {
|
||||
return c.JSON(fiber.Map{
|
||||
"status": "UP",
|
||||
"timestamp": time.Now().UTC(),
|
||||
})
|
||||
})
|
||||
|
||||
app.Get("/readyz", func(c *fiber.Ctx) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
||||
defer cancel()
|
||||
|
||||
targets := make(map[string]TargetHealth)
|
||||
overallHealthy := true
|
||||
|
||||
writeHost := os.Getenv("DB_WRITE_HOST")
|
||||
if writeHost == "" {
|
||||
writeHost = "178.105.149.129"
|
||||
}
|
||||
writePort := os.Getenv("DB_WRITE_PORT")
|
||||
if writePort == "" {
|
||||
writePort = "5437"
|
||||
}
|
||||
|
||||
readHost := os.Getenv("DB_READ_HOST")
|
||||
if readHost == "" {
|
||||
readHost = "178.105.149.129"
|
||||
}
|
||||
readPort := os.Getenv("DB_READ_PORT")
|
||||
if readPort == "" {
|
||||
readPort = "5438"
|
||||
}
|
||||
|
||||
// Check Write Ingress (:5437)
|
||||
writeTarget := fmt.Sprintf("%s:%s", writeHost, writePort)
|
||||
writeStart := time.Now()
|
||||
writeDB, err := db.Clauses(dbresolver.Write).DB()
|
||||
if err != nil || writeDB == nil || writeDB.PingContext(ctx) != nil {
|
||||
overallHealthy = false
|
||||
errMsg := "Write ingress unreachable"
|
||||
if err != nil {
|
||||
errMsg = err.Error()
|
||||
}
|
||||
targets["db_write"] = TargetHealth{
|
||||
Status: "DOWN",
|
||||
Target: writeTarget,
|
||||
Error: errMsg,
|
||||
}
|
||||
} else {
|
||||
targets["db_write"] = TargetHealth{
|
||||
Status: "UP",
|
||||
Target: writeTarget,
|
||||
LatencyMs: float64(time.Since(writeStart).Microseconds()) / 1000.0,
|
||||
}
|
||||
}
|
||||
|
||||
// Check Read Ingress (:5438)
|
||||
readTarget := fmt.Sprintf("%s:%s", readHost, readPort)
|
||||
readStart := time.Now()
|
||||
readDB, err := db.Clauses(dbresolver.Read).DB()
|
||||
if err != nil || readDB == nil || readDB.PingContext(ctx) != nil {
|
||||
overallHealthy = false
|
||||
errMsg := "Read ingress unreachable"
|
||||
if err != nil {
|
||||
errMsg = err.Error()
|
||||
}
|
||||
targets["db_read"] = TargetHealth{
|
||||
Status: "DOWN",
|
||||
Target: readTarget,
|
||||
Error: errMsg,
|
||||
}
|
||||
} else {
|
||||
targets["db_read"] = TargetHealth{
|
||||
Status: "UP",
|
||||
Target: readTarget,
|
||||
LatencyMs: float64(time.Since(readStart).Microseconds()) / 1000.0,
|
||||
}
|
||||
}
|
||||
|
||||
statusCode := fiber.StatusOK
|
||||
statusText := "UP"
|
||||
if !overallHealthy {
|
||||
statusCode = fiber.StatusServiceUnavailable
|
||||
statusText = "DEGRADED"
|
||||
}
|
||||
|
||||
return c.Status(statusCode).JSON(ReadinessResponse{
|
||||
Status: statusText,
|
||||
Timestamp: time.Now().UTC(),
|
||||
Targets: targets,
|
||||
})
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user