P0: - rpm_override 嵌入 Auth Cache Snapshot,消除每请求 DB 查询 (snapshot v6→v7) - 429 RPM 响应返回 Retry-After 头(当前分钟剩余秒数) P1: - ClearAll 按钮直连 DELETE API,带 loading 防重复 - 新增 GET /admin/users/:id/rpm-status 管理员 RPM 用量查询端点 优化: - checkRPM 从级联互斥改为并行取最严,user.rpm_limit 作为全局硬上限始终生效 - Override/Group 变更后自动失效 auth cache - fail-open 语义不变,Redis 故障不阻塞业务
70 lines
1.9 KiB
Go
70 lines
1.9 KiB
Go
//go:build unit
|
|
|
|
package service
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// rpmUserRepoStub 复用 admin_service_update_balance_test.go 的基础 stub 结构,
|
|
// 只在 Update 时把入参克隆一份,便于断言修改后的 RPMLimit。
|
|
type rpmUserRepoStub struct {
|
|
*userRepoStub
|
|
lastUpdated *User
|
|
}
|
|
|
|
func (s *rpmUserRepoStub) Update(_ context.Context, user *User) error {
|
|
if user == nil {
|
|
return nil
|
|
}
|
|
clone := *user
|
|
s.lastUpdated = &clone
|
|
if s.userRepoStub != nil {
|
|
s.userRepoStub.user = &clone
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func TestAdminService_UpdateUser_InvalidatesAuthCacheOnRPMLimitChange(t *testing.T) {
|
|
base := &userRepoStub{user: &User{ID: 42, Email: "u@example.com", RPMLimit: 10}}
|
|
repo := &rpmUserRepoStub{userRepoStub: base}
|
|
invalidator := &authCacheInvalidatorStub{}
|
|
svc := &adminServiceImpl{
|
|
userRepo: repo,
|
|
redeemCodeRepo: &redeemRepoStub{},
|
|
authCacheInvalidator: invalidator,
|
|
}
|
|
|
|
newRPM := 60
|
|
updated, err := svc.UpdateUser(context.Background(), 42, &UpdateUserInput{
|
|
RPMLimit: &newRPM,
|
|
})
|
|
require.NoError(t, err)
|
|
require.NotNil(t, updated)
|
|
require.Equal(t, 60, updated.RPMLimit)
|
|
require.Equal(t, []int64{42}, invalidator.userIDs, "仅修改 RPMLimit 也应失效 API Key 认证缓存")
|
|
}
|
|
|
|
func TestAdminService_UpdateUser_NoInvalidateWhenRPMLimitUnchanged(t *testing.T) {
|
|
base := &userRepoStub{user: &User{ID: 42, Email: "u@example.com", RPMLimit: 10, Username: "old"}}
|
|
repo := &rpmUserRepoStub{userRepoStub: base}
|
|
invalidator := &authCacheInvalidatorStub{}
|
|
svc := &adminServiceImpl{
|
|
userRepo: repo,
|
|
redeemCodeRepo: &redeemRepoStub{},
|
|
authCacheInvalidator: invalidator,
|
|
}
|
|
|
|
newName := "new"
|
|
sameRPM := 10
|
|
_, err := svc.UpdateUser(context.Background(), 42, &UpdateUserInput{
|
|
Username: &newName,
|
|
RPMLimit: &sameRPM,
|
|
})
|
|
require.NoError(t, err)
|
|
require.Empty(t, invalidator.userIDs, "只改 username 不应触发认证缓存失效")
|
|
}
|