Release / update-version (push) Has been cancelled
Release / build-frontend (push) Has been cancelled
Release / release (push) Has been cancelled
Release / sync-version-file (push) Has been cancelled
CI / shell (push) Canceled after 0s
CI / test (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
CI / golangci-lint (push) Canceled after 0s
Security Scan / backend-security (push) Canceled after 0s
Security Scan / frontend-security (push) Canceled after 0s
180 lines
4.8 KiB
Go
180 lines
4.8 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
type groupCapacityAccountRepoStub struct {
|
|
AccountRepository
|
|
rows []GroupAccountCapacityRow
|
|
requested []int64
|
|
}
|
|
|
|
func (s *groupCapacityAccountRepoStub) ListSchedulableCapacityByGroupIDs(_ context.Context, groupIDs []int64) ([]GroupAccountCapacityRow, error) {
|
|
s.requested = append([]int64(nil), groupIDs...)
|
|
return append([]GroupAccountCapacityRow(nil), s.rows...), nil
|
|
}
|
|
|
|
type groupCapacityGroupRepoStub struct {
|
|
GroupRepository
|
|
groupIDs []int64
|
|
listCalls int
|
|
}
|
|
|
|
func (s *groupCapacityGroupRepoStub) ListActiveIDs(context.Context) ([]int64, error) {
|
|
s.listCalls++
|
|
return append([]int64(nil), s.groupIDs...), nil
|
|
}
|
|
|
|
type groupCapacityConcurrencyCacheStub struct {
|
|
ConcurrencyCache
|
|
counts map[int64]int
|
|
requested []int64
|
|
}
|
|
|
|
func (s *groupCapacityConcurrencyCacheStub) GetAccountConcurrencyBatch(_ context.Context, accountIDs []int64) (map[int64]int, error) {
|
|
s.requested = append([]int64(nil), accountIDs...)
|
|
out := make(map[int64]int, len(accountIDs))
|
|
for _, id := range accountIDs {
|
|
out[id] = s.counts[id]
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
type groupCapacitySessionCacheStub struct {
|
|
SessionLimitCache
|
|
counts map[int64]int
|
|
requested []int64
|
|
idleTimeouts map[int64]time.Duration
|
|
}
|
|
|
|
func (s *groupCapacitySessionCacheStub) GetActiveSessionCountBatch(_ context.Context, accountIDs []int64, idleTimeouts map[int64]time.Duration) (map[int64]int, error) {
|
|
s.requested = append([]int64(nil), accountIDs...)
|
|
s.idleTimeouts = make(map[int64]time.Duration, len(idleTimeouts))
|
|
for id, timeout := range idleTimeouts {
|
|
s.idleTimeouts[id] = timeout
|
|
}
|
|
out := make(map[int64]int, len(accountIDs))
|
|
for _, id := range accountIDs {
|
|
out[id] = s.counts[id]
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
type groupCapacityRPMCacheStub struct {
|
|
RPMCache
|
|
counts map[int64]int
|
|
requested []int64
|
|
}
|
|
|
|
func (s *groupCapacityRPMCacheStub) GetRPMBatch(_ context.Context, accountIDs []int64) (map[int64]int, error) {
|
|
s.requested = append([]int64(nil), accountIDs...)
|
|
out := make(map[int64]int, len(accountIDs))
|
|
for _, id := range accountIDs {
|
|
out[id] = s.counts[id]
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
func TestGetAllGroupCapacityBatchAggregatesRuntimeAndLimits(t *testing.T) {
|
|
accountRepo := &groupCapacityAccountRepoStub{
|
|
rows: []GroupAccountCapacityRow{
|
|
{
|
|
GroupID: 10,
|
|
AccountID: 1,
|
|
Concurrency: 2,
|
|
Extra: map[string]any{
|
|
"max_sessions": 3,
|
|
"session_idle_timeout_minutes": 7,
|
|
"base_rpm": 11,
|
|
},
|
|
},
|
|
{
|
|
GroupID: 20,
|
|
AccountID: 1,
|
|
Concurrency: 2,
|
|
Extra: map[string]any{
|
|
"max_sessions": 3,
|
|
"session_idle_timeout_minutes": 7,
|
|
"base_rpm": 11,
|
|
},
|
|
},
|
|
{
|
|
GroupID: 20,
|
|
AccountID: 2,
|
|
Concurrency: 4,
|
|
Extra: map[string]any{
|
|
"max_sessions": 1,
|
|
"session_idle_timeout_minutes": 9,
|
|
"base_rpm": 13,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
groupRepo := &groupCapacityGroupRepoStub{groupIDs: []int64{10, 20}}
|
|
concurrencyCache := &groupCapacityConcurrencyCacheStub{counts: map[int64]int{1: 1, 2: 2}}
|
|
sessionCache := &groupCapacitySessionCacheStub{counts: map[int64]int{1: 2, 2: 1}}
|
|
rpmCache := &groupCapacityRPMCacheStub{counts: map[int64]int{1: 5, 2: 7}}
|
|
svc := NewGroupCapacityService(
|
|
accountRepo,
|
|
groupRepo,
|
|
NewConcurrencyService(concurrencyCache),
|
|
sessionCache,
|
|
rpmCache,
|
|
)
|
|
|
|
results, err := svc.GetAllGroupCapacity(context.Background())
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, 1, groupRepo.listCalls)
|
|
require.Equal(t, []int64{10, 20}, accountRepo.requested)
|
|
require.Equal(t, []int64{1, 2}, concurrencyCache.requested)
|
|
require.ElementsMatch(t, []int64{1, 2}, sessionCache.requested)
|
|
require.ElementsMatch(t, []int64{1, 2}, rpmCache.requested)
|
|
require.Equal(t, 7*time.Minute, sessionCache.idleTimeouts[1])
|
|
require.Equal(t, 9*time.Minute, sessionCache.idleTimeouts[2])
|
|
|
|
require.Equal(t, []GroupCapacitySummary{
|
|
{
|
|
GroupID: 10,
|
|
ConcurrencyUsed: 1,
|
|
ConcurrencyMax: 2,
|
|
SessionsUsed: 2,
|
|
SessionsMax: 3,
|
|
RPMUsed: 5,
|
|
RPMMax: 11,
|
|
},
|
|
{
|
|
GroupID: 20,
|
|
ConcurrencyUsed: 3,
|
|
ConcurrencyMax: 6,
|
|
SessionsUsed: 3,
|
|
SessionsMax: 4,
|
|
RPMUsed: 12,
|
|
RPMMax: 24,
|
|
},
|
|
}, results)
|
|
}
|
|
|
|
func TestGetAllGroupCapacityBatchKeepsEmptyGroupRows(t *testing.T) {
|
|
accountRepo := &groupCapacityAccountRepoStub{
|
|
rows: []GroupAccountCapacityRow{
|
|
{GroupID: 20, AccountID: 2, Concurrency: 4},
|
|
},
|
|
}
|
|
groupRepo := &groupCapacityGroupRepoStub{groupIDs: []int64{10, 20}}
|
|
svc := NewGroupCapacityService(accountRepo, groupRepo, nil, nil, nil)
|
|
|
|
results, err := svc.GetAllGroupCapacity(context.Background())
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, []GroupCapacitySummary{
|
|
{GroupID: 10},
|
|
{GroupID: 20, ConcurrencyMax: 4},
|
|
}, results)
|
|
}
|