feat: game lobby service

This commit is contained in:
Ilia Denisov
2026-04-25 23:20:55 +02:00
committed by GitHub
parent 32dc29359a
commit 48b0056b49
336 changed files with 57074 additions and 1418 deletions
+12 -22
View File
@@ -22,7 +22,7 @@ const (
initialEntitlementActorType common.ActorType = "service"
initialEntitlementActorID common.ActorID = "user-service"
ensureCreateRetryLimit = 8
ensureCreateRetryLimit = 10
)
// ResolveByEmailInput stores one auth-facing resolve-by-email request.
@@ -155,7 +155,6 @@ type Ensurer struct {
store ports.AuthDirectoryStore
clock ports.Clock
idGenerator ports.IDGenerator
policy ports.RaceNamePolicy
logger *slog.Logger
telemetry *telemetry.Runtime
profilePublisher ports.ProfileChangedPublisher
@@ -168,9 +167,8 @@ func NewEnsurer(
store ports.AuthDirectoryStore,
clock ports.Clock,
idGenerator ports.IDGenerator,
policy ports.RaceNamePolicy,
) (*Ensurer, error) {
return NewEnsurerWithObservability(store, clock, idGenerator, policy, nil, nil, nil, nil, nil)
return NewEnsurerWithObservability(store, clock, idGenerator, nil, nil, nil, nil, nil)
}
// NewEnsurerWithObservability returns one ensure-by-email use case instance
@@ -180,7 +178,6 @@ func NewEnsurerWithObservability(
store ports.AuthDirectoryStore,
clock ports.Clock,
idGenerator ports.IDGenerator,
policy ports.RaceNamePolicy,
logger *slog.Logger,
telemetryRuntime *telemetry.Runtime,
profilePublisher ports.ProfileChangedPublisher,
@@ -194,14 +191,11 @@ func NewEnsurerWithObservability(
return nil, fmt.Errorf("authdirectory ensurer: clock must not be nil")
case idGenerator == nil:
return nil, fmt.Errorf("authdirectory ensurer: id generator must not be nil")
case policy == nil:
return nil, fmt.Errorf("authdirectory ensurer: race-name policy must not be nil")
default:
return &Ensurer{
store: store,
clock: clock,
idGenerator: idGenerator,
policy: policy,
logger: logger,
telemetry: telemetryRuntime,
profilePublisher: profilePublisher,
@@ -256,7 +250,7 @@ func (service *Ensurer) Execute(ctx context.Context, input EnsureByEmailInput) (
if err != nil {
return EnsureByEmailResult{}, shared.ServiceUnavailable(err)
}
raceName, err := service.idGenerator.NewInitialRaceName()
userName, err := service.idGenerator.NewUserName()
if err != nil {
return EnsureByEmailResult{}, shared.ServiceUnavailable(err)
}
@@ -264,7 +258,7 @@ func (service *Ensurer) Execute(ctx context.Context, input EnsureByEmailInput) (
accountRecord := account.UserAccount{
UserID: userID,
Email: email,
RaceName: raceName,
UserName: userName,
PreferredLanguage: preferredLanguage,
TimeZone: timeZone,
CreatedAt: now,
@@ -294,21 +288,16 @@ func (service *Ensurer) Execute(ctx context.Context, input EnsureByEmailInput) (
StartsAt: now,
CreatedAt: now,
}
reservation, err := shared.BuildRaceNameReservation(service.policy, userID, raceName, now)
if err != nil {
return EnsureByEmailResult{}, shared.ServiceUnavailable(err)
}
ensureResult, err := service.store.EnsureByEmail(ctx, ports.EnsureByEmailInput{
Email: email,
Account: accountRecord,
Entitlement: entitlementSnapshot,
EntitlementRecord: entitlementRecord,
Reservation: reservation,
})
if err != nil {
if errors.Is(err, ports.ErrRaceNameConflict) && service.telemetry != nil {
service.telemetry.RecordRaceNameReservationConflict(ctx, "ensure_by_email")
if errors.Is(err, ports.ErrUserNameConflict) && service.telemetry != nil {
service.telemetry.RecordUserNameConflict(ctx, "ensure_by_email")
}
if errors.Is(err, ports.ErrConflict) {
continue
@@ -349,11 +338,12 @@ func (service *Ensurer) publishInitializedEvents(
occurredAt := accountRecord.UpdatedAt.UTC()
service.publishProfileChanged(ctx, ports.ProfileChangedEvent{
UserID: accountRecord.UserID,
OccurredAt: occurredAt,
Source: initialEntitlementSource,
Operation: ports.ProfileChangedOperationInitialized,
RaceName: accountRecord.RaceName,
UserID: accountRecord.UserID,
OccurredAt: occurredAt,
Source: initialEntitlementSource,
Operation: ports.ProfileChangedOperationInitialized,
UserName: accountRecord.UserName,
DisplayName: accountRecord.DisplayName,
})
service.publishSettingsChanged(ctx, ports.SettingsChangedEvent{
UserID: accountRecord.UserID,