mirror of
https://github.com/EZ-Api/ez-api.git
synced 2026-01-13 17:47:51 +00:00
Write 'meta:providers_meta' to Redis during provider synchronization, including version, timestamp, and configuration checksum. This aligns provider sync with model metadata handling and enables better cache invalidation.
125 lines
3.2 KiB
Go
125 lines
3.2 KiB
Go
package service
|
|
|
|
import (
|
|
"encoding/json"
|
|
"strconv"
|
|
"testing"
|
|
|
|
"github.com/alicebob/miniredis/v2"
|
|
"github.com/ez-api/ez-api/internal/model"
|
|
"github.com/redis/go-redis/v9"
|
|
"gorm.io/driver/sqlite"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
func TestSyncProviders_WritesSnapshot(t *testing.T) {
|
|
mr := miniredis.RunT(t)
|
|
rdb := redis.NewClient(&redis.Options{Addr: mr.Addr()})
|
|
svc := NewSyncService(rdb)
|
|
|
|
db, err := gorm.Open(sqlite.Open("file:"+t.Name()+"?mode=memory&cache=shared"), &gorm.Config{})
|
|
if err != nil {
|
|
t.Fatalf("open sqlite: %v", err)
|
|
}
|
|
if err := db.AutoMigrate(&model.ProviderGroup{}, &model.APIKey{}); err != nil {
|
|
t.Fatalf("migrate: %v", err)
|
|
}
|
|
|
|
group := model.ProviderGroup{
|
|
Name: "default",
|
|
Type: "vertex-express",
|
|
BaseURL: "https://vertex.example",
|
|
GoogleLocation: "global",
|
|
Models: "gemini-3-pro-preview",
|
|
Status: "active",
|
|
}
|
|
if err := db.Create(&group).Error; err != nil {
|
|
t.Fatalf("create group: %v", err)
|
|
}
|
|
key := model.APIKey{
|
|
GroupID: group.ID,
|
|
APIKey: "k",
|
|
Status: "active",
|
|
AutoBan: true,
|
|
}
|
|
if err := db.Create(&key).Error; err != nil {
|
|
t.Fatalf("create key: %v", err)
|
|
}
|
|
|
|
if err := svc.SyncProviders(db); err != nil {
|
|
t.Fatalf("SyncProviders: %v", err)
|
|
}
|
|
|
|
raw := mr.HGet("config:providers", jsonID(key.ID))
|
|
if raw == "" {
|
|
t.Fatalf("expected config:providers hash entry")
|
|
}
|
|
var snap map[string]any
|
|
if err := json.Unmarshal([]byte(raw), &snap); err != nil {
|
|
t.Fatalf("invalid snapshot json: %v", err)
|
|
}
|
|
if snap["group"] != "default" {
|
|
t.Fatalf("expected group default, got %#v", snap["group"])
|
|
}
|
|
|
|
if v := mr.HGet("meta:providers_meta", "version"); v == "" {
|
|
t.Fatalf("expected meta:providers_meta.version")
|
|
}
|
|
if v := mr.HGet("meta:providers_meta", "updated_at"); v == "" {
|
|
t.Fatalf("expected meta:providers_meta.updated_at")
|
|
}
|
|
if v := mr.HGet("meta:providers_meta", "checksum"); v == "" {
|
|
t.Fatalf("expected meta:providers_meta.checksum")
|
|
}
|
|
}
|
|
|
|
func TestSyncKey_WritesTokenID(t *testing.T) {
|
|
mr := miniredis.RunT(t)
|
|
rdb := redis.NewClient(&redis.Options{Addr: mr.Addr()})
|
|
svc := NewSyncService(rdb)
|
|
|
|
k := &model.Key{
|
|
TokenHash: "hash",
|
|
MasterID: 1,
|
|
IssuedAtEpoch: 1,
|
|
Status: "active",
|
|
Group: "default",
|
|
Scopes: "chat:write",
|
|
DefaultNamespace: "default",
|
|
Namespaces: "default",
|
|
}
|
|
k.ID = 123
|
|
|
|
if err := svc.SyncKey(k); err != nil {
|
|
t.Fatalf("SyncKey: %v", err)
|
|
}
|
|
|
|
if got := mr.HGet("auth:token:hash", "id"); got != "123" {
|
|
t.Fatalf("expected auth:token:hash.id=123, got %q", got)
|
|
}
|
|
}
|
|
|
|
func TestSyncModelDelete_RemovesMeta(t *testing.T) {
|
|
mr := miniredis.RunT(t)
|
|
rdb := redis.NewClient(&redis.Options{Addr: mr.Addr()})
|
|
svc := NewSyncService(rdb)
|
|
|
|
mr.HSet("meta:models", "ns.m", `{"name":"ns.m"}`)
|
|
|
|
m := &model.Model{Name: "ns.m"}
|
|
if err := svc.SyncModelDelete(m); err != nil {
|
|
t.Fatalf("SyncModelDelete: %v", err)
|
|
}
|
|
|
|
if got := mr.HGet("meta:models", "ns.m"); got != "" {
|
|
t.Fatalf("expected meta:models entry removed, got %q", got)
|
|
}
|
|
if v := mr.HGet("meta:models_meta", "version"); v == "" {
|
|
t.Fatalf("expected meta:models_meta.version to be set")
|
|
}
|
|
}
|
|
|
|
func jsonID(id uint) string {
|
|
return strconv.FormatUint(uint64(id), 10)
|
|
}
|