feat: runtime manager

This commit is contained in:
Ilia Denisov
2026-04-28 20:39:18 +02:00
committed by GitHub
parent e0a99b346b
commit a7cee15115
289 changed files with 45660 additions and 2207 deletions
@@ -4,14 +4,15 @@ import (
"context"
"io"
"log/slog"
"sync"
"testing"
"time"
"galaxy/lobby/internal/adapters/gamestub"
"galaxy/lobby/internal/adapters/gapactivationstub"
"galaxy/lobby/internal/adapters/intentpubstub"
"galaxy/lobby/internal/adapters/invitestub"
"galaxy/lobby/internal/adapters/membershipstub"
"galaxy/lobby/internal/adapters/gameinmem"
"galaxy/lobby/internal/adapters/gapactivationinmem"
"galaxy/lobby/internal/adapters/inviteinmem"
"galaxy/lobby/internal/adapters/membershipinmem"
"galaxy/lobby/internal/adapters/mocks"
"galaxy/lobby/internal/domain/common"
"galaxy/lobby/internal/domain/game"
"galaxy/lobby/internal/domain/invite"
@@ -21,8 +22,34 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/mock/gomock"
)
type intentRec struct {
mu sync.Mutex
published []notificationintent.Intent
}
func (r *intentRec) record(_ context.Context, intent notificationintent.Intent) (string, error) {
r.mu.Lock()
defer r.mu.Unlock()
r.published = append(r.published, intent)
return "1", nil
}
func (r *intentRec) snapshot() []notificationintent.Intent {
r.mu.Lock()
defer r.mu.Unlock()
return append([]notificationintent.Intent(nil), r.published...)
}
func newIntentMock(t *testing.T, rec *intentRec) *mocks.MockIntentPublisher {
t.Helper()
m := mocks.NewMockIntentPublisher(gomock.NewController(t))
m.EXPECT().Publish(gomock.Any(), gomock.Any()).DoAndReturn(rec.record).AnyTimes()
return m
}
const (
gameID = common.GameID("game-private")
ownerUserID = "user-owner"
@@ -34,11 +61,12 @@ func fixedClock(at time.Time) func() time.Time { return func() time.Time { retur
type fixture struct {
now time.Time
games *gamestub.Store
invites *invitestub.Store
memberships *membershipstub.Store
gapStore *gapactivationstub.Store
intents *intentpubstub.Publisher
games *gameinmem.Store
invites *inviteinmem.Store
memberships *membershipinmem.Store
gapStore *gapactivationinmem.Store
intentRec *intentRec
intents *mocks.MockIntentPublisher
game game.Game
}
@@ -86,16 +114,18 @@ func newFixture(t *testing.T, opts fixtureOptions) *fixture {
require.NoError(t, err)
rec.Status = game.StatusEnrollmentOpen
games := gamestub.NewStore()
games := gameinmem.NewStore()
require.NoError(t, games.Save(context.Background(), rec))
intentRecord := &intentRec{}
return &fixture{
now: now,
games: games,
invites: invitestub.NewStore(),
memberships: membershipstub.NewStore(),
gapStore: gapactivationstub.NewStore(),
intents: intentpubstub.NewPublisher(),
invites: inviteinmem.NewStore(),
memberships: membershipinmem.NewStore(),
gapStore: gapactivationinmem.NewStore(),
intentRec: intentRecord,
intents: newIntentMock(t, intentRecord),
game: rec,
}
}
@@ -159,11 +189,11 @@ func currentStatus(t *testing.T, f *fixture) game.Status {
func TestNewWorkerRejectsZeroInterval(t *testing.T) {
t.Parallel()
_, err := enrollmentautomation.NewWorker(enrollmentautomation.Dependencies{
Games: gamestub.NewStore(),
Memberships: membershipstub.NewStore(),
Invites: invitestub.NewStore(),
Intents: intentpubstub.NewPublisher(),
GapStore: gapactivationstub.NewStore(),
Games: gameinmem.NewStore(),
Memberships: membershipinmem.NewStore(),
Invites: inviteinmem.NewStore(),
Intents: newIntentMock(t, &intentRec{}),
GapStore: gapactivationinmem.NewStore(),
Interval: 0,
})
require.Error(t, err)
@@ -185,7 +215,7 @@ func TestTickDeadlineTriggers(t *testing.T) {
require.NoError(t, err)
assert.Equal(t, invite.StatusExpired, expired.Status)
intents := f.intents.Published()
intents := f.intentRec.snapshot()
require.Len(t, intents, 1)
assert.Equal(t, notificationintent.NotificationTypeLobbyInviteExpired, intents[0].NotificationType)
}
@@ -200,7 +230,7 @@ func TestTickDeadlineSkipsBelowMinPlayers(t *testing.T) {
f.newWorker(t, tickAt).Tick(context.Background())
assert.Equal(t, game.StatusEnrollmentOpen, currentStatus(t, f))
assert.Empty(t, f.intents.Published())
assert.Empty(t, f.intentRec.snapshot())
}
func TestTickGapTimeTriggers(t *testing.T) {
@@ -260,7 +290,7 @@ func TestTickIsIdempotent(t *testing.T) {
worker.Tick(context.Background())
assert.Equal(t, game.StatusReadyToStart, currentStatus(t, f))
assert.Len(t, f.intents.Published(), 1)
assert.Len(t, f.intentRec.snapshot(), 1)
}
func TestRunStopsOnContextCancel(t *testing.T) {