mirror of
https://github.com/EZ-Api/ez-api.git
synced 2026-01-13 17:47:51 +00:00
Restructure the provider management system by separating the monolithic Provider model into two distinct entities: - ProviderGroup: defines shared upstream configuration (type, base_url, google settings, models, status) - APIKey: represents individual credentials within a group (api_key, weight, status, auto_ban, ban settings) This change also updates: - Binding model to reference GroupID instead of RouteGroup string - All CRUD handlers for the new provider-group and api-key endpoints - Sync service to rebuild provider snapshots from joined tables - Model registry to aggregate capabilities across group/key pairs - Access handler to validate namespace existence and subset constraints - Migration importer to handle the new schema structure - All related tests to use the new model relationships BREAKING CHANGE: Provider API endpoints replaced with /provider-groups and /api-keys endpoints; Binding.RouteGroup replaced with Binding.GroupID
76 lines
2.0 KiB
Go
76 lines
2.0 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
"time"
|
|
|
|
"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 TestModelRegistry_Check(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
dsn := fmt.Sprintf("file:%s?mode=memory&cache=shared", t.Name())
|
|
db, err := gorm.Open(sqlite.Open(dsn), &gorm.Config{})
|
|
if err != nil {
|
|
t.Fatalf("open sqlite: %v", err)
|
|
}
|
|
if err := db.AutoMigrate(&model.ProviderGroup{}, &model.APIKey{}, &model.Binding{}, &model.Model{}); err != nil {
|
|
t.Fatalf("migrate: %v", err)
|
|
}
|
|
|
|
const latestSHA = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
|
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.URL.Path != "/repos/sst/models.dev/commits/dev" {
|
|
http.NotFound(w, r)
|
|
return
|
|
}
|
|
w.Header().Set("Content-Type", "application/json")
|
|
_, _ = w.Write([]byte(`{"sha":"` + latestSHA + `"}`))
|
|
}))
|
|
defer srv.Close()
|
|
|
|
mr := miniredis.RunT(t)
|
|
rdb := redis.NewClient(&redis.Options{Addr: mr.Addr()})
|
|
|
|
// Prefix-matching should treat short current as up-to-date.
|
|
mr.HSet("meta:models_meta", "version", "aaaaaaaa")
|
|
mr.HSet("meta:models_meta", "upstream_ref", "dev")
|
|
|
|
svc := NewModelRegistryService(db, rdb, ModelRegistryConfig{
|
|
Enabled: true,
|
|
RefreshEvery: time.Hour,
|
|
ModelsDevAPIBaseURL: srv.URL,
|
|
ModelsDevRef: "dev",
|
|
Timeout: 5 * time.Second,
|
|
})
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
|
defer cancel()
|
|
|
|
out, err := svc.Check(ctx, "")
|
|
if err != nil {
|
|
t.Fatalf("check: %v", err)
|
|
}
|
|
if out.NeedsRefresh {
|
|
t.Fatalf("expected needs_refresh=false, got true (current=%q latest=%q)", out.CurrentVersion, out.LatestVersion)
|
|
}
|
|
|
|
mr.HSet("meta:models_meta", "version", "bbbbbbbb")
|
|
out, err = svc.Check(ctx, "dev")
|
|
if err != nil {
|
|
t.Fatalf("check2: %v", err)
|
|
}
|
|
if !out.NeedsRefresh {
|
|
t.Fatalf("expected needs_refresh=true, got false (current=%q latest=%q)", out.CurrentVersion, out.LatestVersion)
|
|
}
|
|
}
|