feat: Gateway store 桩换真实 GORM/Postgres + go-redis (含自动迁移与优雅降级)
第 2 层网关持久层落地,遵守 sundynix_ 表名前缀 + AutoMigrate 约定。 - store: GORM(NamingStrategy 前缀 sundynix_/单数) → User=sundynix_user, Task=sundynix_task 启动 AutoMigrate;go-redis/v9 滑动窗口限流(Incr+Expire,按 IP) - 优雅降级:连不上库则 warn 继续(不 fatal),保证无 Docker 的 make demo 仍跑通 - handler: SubmitTask 持久化任务(best-effort),Billing 真实读库返回 tasks_submitted - main: OpenPostgres/OpenRedis 读 POSTGRES_DSN/REDIS_ADDR 环境变量 - 验证: 4 模块 build ✓;e2e 3 测试 PASS;live 双路径(真实库持久化 + 坏DSN降级)实测通过 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,9 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/sundynix/sundynix-gateway/internal/store"
|
||||
@@ -16,10 +19,16 @@ func Guardrail() gin.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
// RateLimit 基于 Redis 的会话级限流。
|
||||
// RateLimit 基于 Redis 的会话级限流(按客户端 IP,每分钟上限)。
|
||||
// Redis 降级时 Allow 始终放行,不阻断业务。
|
||||
func RateLimit(cache *store.Redis) gin.HandlerFunc {
|
||||
const perMinute = 120
|
||||
return func(c *gin.Context) {
|
||||
// TODO: 令牌桶 / 滑动窗口
|
||||
ok, _ := cache.Allow(c.Request.Context(), c.ClientIP(), perMinute, time.Minute)
|
||||
if !ok {
|
||||
c.AbortWithStatusJSON(http.StatusTooManyRequests, gin.H{"error": "rate limit exceeded"})
|
||||
return
|
||||
}
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user