AI Gateway Go 0.10.0 源码快照 + 旗舰版需求规划报告
M0-M7 已完成:核心网关(身份/RBAC/TOTP/OIDC/SAML/Provider/配额/路由/内容策略/审计/定价)+ 资源市场(MCP/Skills/数字员工)。 含 22 个 PostgreSQL 迁移、管理端/门户端前端源码、OpenAPI 契约、部署 compose。 Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
package audit
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
func TestMaintenancePartitionsRetentionAndIdempotency(t *testing.T) {
|
||||
databaseURL := os.Getenv("AUDIT_MAINTENANCE_TEST_DATABASE_URL")
|
||||
if databaseURL == "" {
|
||||
t.Skip("AUDIT_MAINTENANCE_TEST_DATABASE_URL is not configured")
|
||||
}
|
||||
ctx := context.Background()
|
||||
pool, err := pgxpool.New(ctx, databaseURL)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
defer pool.Close()
|
||||
const oldID = "44444444-4444-4444-8444-444444444444"
|
||||
const currentID = "55555555-5555-4555-8555-555555555555"
|
||||
_, err = pool.Exec(ctx, `INSERT INTO gateway.audit_events(id,request_id,protocol,status_code,recorded_at) VALUES
|
||||
($1,'maintenance-old','/v1/test',200,'2026-01-15T00:00:00Z'),
|
||||
($2,'maintenance-current','/v1/test',200,'2026-08-10T00:00:00Z')`, oldID, currentID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
now := time.Date(2026, 8, 11, 0, 0, 0, 0, time.UTC)
|
||||
first, err := NewMaintenance(pool, 300*24*time.Hour, 730*24*time.Hour, 1).Run(ctx, now)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !contains(first.CreatedPartitions, "audit_events_202601") || !contains(first.CreatedPartitions, "audit_events_202608") {
|
||||
t.Fatalf("expected old and current partitions, got %#v", first.CreatedPartitions)
|
||||
}
|
||||
second, err := NewMaintenance(pool, 90*24*time.Hour, 730*24*time.Hour, 1).Run(ctx, now)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !contains(second.DroppedPartitions, "audit_events_202601") {
|
||||
t.Fatalf("expected stale partition to be dropped, got %#v", second.DroppedPartitions)
|
||||
}
|
||||
var currentTable string
|
||||
if err := pool.QueryRow(ctx, `SELECT tableoid::regclass::text FROM gateway.audit_events WHERE id=$1`, currentID).Scan(¤tTable); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if currentTable != "gateway.audit_events_202608" && currentTable != "audit_events_202608" {
|
||||
t.Fatalf("current row was not routed to monthly partition: %s", currentTable)
|
||||
}
|
||||
var oldCount int
|
||||
if err := pool.QueryRow(ctx, `SELECT count(*) FROM gateway.audit_events WHERE id=$1`, oldID).Scan(&oldCount); err != nil || oldCount != 0 {
|
||||
t.Fatalf("expired row still exists: count=%d err=%v", oldCount, err)
|
||||
}
|
||||
third, err := NewMaintenance(pool, 90*24*time.Hour, 730*24*time.Hour, 1).Run(ctx, now)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(third.CreatedPartitions) != 0 || len(third.DroppedPartitions) != 0 {
|
||||
t.Fatalf("maintenance must be idempotent: %#v", third)
|
||||
}
|
||||
}
|
||||
|
||||
func contains(values []string, wanted string) bool {
|
||||
for _, value := range values {
|
||||
if value == wanted {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
Reference in New Issue
Block a user