Skip to content

Commit

Permalink
debug(remove): log rooms being removed after sorted
Browse files Browse the repository at this point in the history
  • Loading branch information
hspedro committed Aug 22, 2024
1 parent 48a9fa9 commit 979af9e
Show file tree
Hide file tree
Showing 7 changed files with 324 additions and 253 deletions.
32 changes: 13 additions & 19 deletions internal/core/operations/rooms/remove/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import (
"context"
"errors"
"fmt"
"sync"

"github.com/topfreegames/maestro/internal/core/entities/game_room"
"github.com/topfreegames/maestro/internal/core/entities/operation"
Expand All @@ -35,6 +34,7 @@ import (
"github.com/topfreegames/maestro/internal/core/ports"
porterrors "github.com/topfreegames/maestro/internal/core/ports/errors"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"golang.org/x/sync/errgroup"
)

Expand Down Expand Up @@ -110,31 +110,25 @@ func (e *Executor) removeRoomsByIDs(ctx context.Context, schedulerName string, r
}

func (e *Executor) removeRoomsByAmount(ctx context.Context, logger *zap.Logger, schedulerName string, amount int, op *operation.Operation, reason string) error {
rooms, err := e.roomManager.ListRoomsWithDeletionPriority(ctx, schedulerName, "", amount, &sync.Map{})
activeScheduler, err := e.schedulerManager.GetActiveScheduler(ctx, schedulerName)
if err != nil {
return err
}

activeScheduler, err := e.schedulerManager.GetActiveScheduler(ctx, schedulerName)
rooms, err := e.roomManager.ListRoomsWithDeletionPriority(ctx, activeScheduler, amount)
if err != nil {
logger.Warn("error getting active scheduler, not sorting by version", zap.Error(err))
} else {
var activeVersionRooms []*game_room.GameRoom
var mostPrioRoomsToBeRemoved []*game_room.GameRoom
for _, room := range rooms {
if room.Status == game_room.GameStatusOccupied || room.Status == game_room.GameStatusReady || room.Status == game_room.GameStatusPending {
if room.Version == activeScheduler.Spec.Version {
activeVersionRooms = append(activeVersionRooms, room)
} else {
mostPrioRoomsToBeRemoved = append(mostPrioRoomsToBeRemoved, room)
}
} else {
mostPrioRoomsToBeRemoved = append(mostPrioRoomsToBeRemoved, room)
}
}
rooms = append(mostPrioRoomsToBeRemoved, activeVersionRooms...)
return err
}

logger.Info("removing rooms by amount sorting by version",
zap.Array("originalRoomsOrder", zapcore.ArrayMarshalerFunc(func(enc zapcore.ArrayEncoder) error {
for _, room := range rooms {
enc.AppendString(fmt.Sprintf("%s-%s-%s", room.ID, room.Version, room.Status.String()))
}
return nil
})),
)

err = e.deleteRooms(ctx, rooms, op, reason)
if err != nil {
return err
Expand Down
141 changes: 90 additions & 51 deletions internal/core/operations/rooms/remove/executor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,26 +41,25 @@ import (

"github.com/topfreegames/maestro/internal/core/entities/game_room"
"github.com/topfreegames/maestro/internal/core/entities/operation"
"github.com/topfreegames/maestro/internal/core/entities/port"
)

func TestExecutor_Execute(t *testing.T) {

t.Run("RemoveRoom by Amount", func(t *testing.T) {
t.Run("should succeed - no rooms to be removed => returns without error", func(t *testing.T) {
executor, _, roomsManager, _, schedulerManager := testSetup(t)
t.Run("should fail - if fails to get active scheduler => returns error", func(t *testing.T) {
executor, _, _, _, schedulerManager := testSetup(t)

schedulerName := uuid.NewString()
scheduler := newValidScheduler()
definition := &Definition{Amount: 2}
op := &operation.Operation{ID: "random-uuid", SchedulerName: schedulerName}
op := &operation.Operation{ID: "random-uuid", SchedulerName: scheduler.Name}

ctx := context.Background()

emptyGameRoomSlice := []*game_room.GameRoom{}
schedulerManager.EXPECT().GetActiveScheduler(gomock.Any(), schedulerName).Return(nil, errors.New("error getting active scheduler"))
roomsManager.EXPECT().ListRoomsWithDeletionPriority(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(emptyGameRoomSlice, nil)
schedulerManager.EXPECT().GetActiveScheduler(gomock.Any(), scheduler.Name).Return(nil, errors.New("error getting active scheduler"))

err := executor.Execute(ctx, op, definition)
require.Nil(t, err)
require.NotNil(t, err)
})

t.Run("should succeed and sort rooms by active scheduler version", func(t *testing.T) {
Expand Down Expand Up @@ -108,7 +107,7 @@ func TestExecutor_Execute(t *testing.T) {
availableRooms[7], // P2v2
}
schedulerManager.EXPECT().GetActiveScheduler(gomock.Any(), schedulerName).Return(schedulerV2, nil)
roomsManager.EXPECT().ListRoomsWithDeletionPriority(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(availableRooms, nil)
roomsManager.EXPECT().ListRoomsWithDeletionPriority(gomock.Any(), gomock.Any(), gomock.Any()).Return(availableRooms, nil)
roomsManager.EXPECT().DeleteRoom(gomock.Any(), expectedSortedRoomsOrder[0], gomock.Any()).Times(1)
roomsManager.EXPECT().DeleteRoom(gomock.Any(), expectedSortedRoomsOrder[1], gomock.Any()).Times(1)
roomsManager.EXPECT().DeleteRoom(gomock.Any(), expectedSortedRoomsOrder[2], gomock.Any()).Times(1)
Expand All @@ -125,17 +124,17 @@ func TestExecutor_Execute(t *testing.T) {
t.Run("when any room failed to delete with unexpected error it returns with error", func(t *testing.T) {
executor, _, roomsManager, operationManager, schedulerManager := testSetup(t)

schedulerName := uuid.NewString()
scheduler := newValidScheduler()
definition := &Definition{Amount: 2, Reason: "reason"}
op := &operation.Operation{ID: "random-uuid", SchedulerName: schedulerName}
op := &operation.Operation{ID: "random-uuid", SchedulerName: scheduler.Name}

availableRooms := []*game_room.GameRoom{
{ID: "first-room", SchedulerID: schedulerName, Status: game_room.GameStatusReady, Metadata: map[string]interface{}{}},
{ID: "second-room", SchedulerID: schedulerName, Status: game_room.GameStatusReady, Metadata: map[string]interface{}{}},
{ID: "first-room", SchedulerID: scheduler.Name, Status: game_room.GameStatusReady, Metadata: map[string]interface{}{}},
{ID: "second-room", SchedulerID: scheduler.Name, Status: game_room.GameStatusReady, Metadata: map[string]interface{}{}},
}

schedulerManager.EXPECT().GetActiveScheduler(gomock.Any(), schedulerName).Return(nil, errors.New("error getting active scheduler"))
roomsManager.EXPECT().ListRoomsWithDeletionPriority(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(availableRooms, nil)
schedulerManager.EXPECT().GetActiveScheduler(gomock.Any(), scheduler.Name).Return(scheduler, nil)
roomsManager.EXPECT().ListRoomsWithDeletionPriority(gomock.Any(), gomock.Any(), gomock.Any()).Return(availableRooms, nil)

roomsManager.EXPECT().DeleteRoom(gomock.Any(), availableRooms[0], definition.Reason).Return(nil)

Expand All @@ -149,17 +148,17 @@ func TestExecutor_Execute(t *testing.T) {
t.Run("when any room failed to delete with timeout error it returns with error", func(t *testing.T) {
executor, _, roomsManager, operationManager, schedulerManager := testSetup(t)

schedulerName := uuid.NewString()
scheduler := newValidScheduler()
definition := &Definition{Amount: 2, Reason: "reason"}
op := &operation.Operation{ID: "random-uuid", SchedulerName: schedulerName}
op := &operation.Operation{ID: "random-uuid", SchedulerName: scheduler.Name}

availableRooms := []*game_room.GameRoom{
{ID: "first-room", SchedulerID: schedulerName, Status: game_room.GameStatusReady, Metadata: map[string]interface{}{}},
{ID: "second-room", SchedulerID: schedulerName, Status: game_room.GameStatusReady, Metadata: map[string]interface{}{}},
{ID: "first-room", SchedulerID: scheduler.Name, Status: game_room.GameStatusReady, Metadata: map[string]interface{}{}},
{ID: "second-room", SchedulerID: scheduler.Name, Status: game_room.GameStatusReady, Metadata: map[string]interface{}{}},
}

schedulerManager.EXPECT().GetActiveScheduler(gomock.Any(), schedulerName).Return(nil, errors.New("error getting active scheduler"))
roomsManager.EXPECT().ListRoomsWithDeletionPriority(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(availableRooms, nil)
schedulerManager.EXPECT().GetActiveScheduler(gomock.Any(), scheduler.Name).Return(scheduler, nil)
roomsManager.EXPECT().ListRoomsWithDeletionPriority(gomock.Any(), gomock.Any(), gomock.Any()).Return(availableRooms, nil)
roomsManager.EXPECT().DeleteRoom(gomock.Any(), availableRooms[0], definition.Reason).Return(nil)

roomsManager.EXPECT().DeleteRoom(gomock.Any(), availableRooms[1], definition.Reason).Return(serviceerrors.NewErrGameRoomStatusWaitingTimeout("some error"))
Expand All @@ -170,13 +169,14 @@ func TestExecutor_Execute(t *testing.T) {
})

t.Run("when list rooms has error returns with error", func(t *testing.T) {
executor, _, roomsManager, _, _ := testSetup(t)
executor, _, roomsManager, _, schedulerManager := testSetup(t)

schedulerName := uuid.NewString()
scheduler := newValidScheduler()
definition := &Definition{Amount: 2}
op := &operation.Operation{ID: "random-uuid", SchedulerName: schedulerName}
op := &operation.Operation{ID: "random-uuid", SchedulerName: scheduler.Name}

roomsManager.EXPECT().ListRoomsWithDeletionPriority(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, errors.New("error"))
schedulerManager.EXPECT().GetActiveScheduler(gomock.Any(), scheduler.Name).Return(scheduler, nil)
roomsManager.EXPECT().ListRoomsWithDeletionPriority(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil, errors.New("error"))

err := executor.Execute(context.Background(), op, definition)
require.NotNil(t, err)
Expand All @@ -188,9 +188,9 @@ func TestExecutor_Execute(t *testing.T) {
t.Run("should succeed - no rooms to be removed => returns without error", func(t *testing.T) {
executor, _, _, _, _ := testSetup(t)

schedulerName := uuid.NewString()
scheduler := newValidScheduler()
definition := &Definition{RoomsIDs: []string{}}
op := &operation.Operation{ID: "random-uuid", SchedulerName: schedulerName}
op := &operation.Operation{ID: "random-uuid", SchedulerName: scheduler.Name}

err := executor.Execute(context.Background(), op, definition)
require.Nil(t, err)
Expand All @@ -202,17 +202,17 @@ func TestExecutor_Execute(t *testing.T) {
firstRoomID := "first-room-id"
secondRoomID := "second-room-id"

schedulerName := uuid.NewString()
scheduler := newValidScheduler()
definition := &Definition{RoomsIDs: []string{firstRoomID, secondRoomID}, Reason: "reason"}
op := &operation.Operation{ID: "random-uuid", SchedulerName: schedulerName}
op := &operation.Operation{ID: "random-uuid", SchedulerName: scheduler.Name}

room := &game_room.GameRoom{
ID: firstRoomID,
SchedulerID: schedulerName,
SchedulerID: scheduler.Name,
}
secondRoom := &game_room.GameRoom{
ID: secondRoomID,
SchedulerID: schedulerName,
SchedulerID: scheduler.Name,
}

roomsManager.EXPECT().DeleteRoom(gomock.Any(), room, definition.Reason).Return(nil)
Expand All @@ -228,17 +228,17 @@ func TestExecutor_Execute(t *testing.T) {
firstRoomID := "first-room-id"
secondRoomID := "second-room-id"

schedulerName := uuid.NewString()
scheduler := newValidScheduler()
definition := &Definition{RoomsIDs: []string{firstRoomID, secondRoomID}, Reason: "reason"}
op := &operation.Operation{ID: "random-uuid", SchedulerName: schedulerName}
op := &operation.Operation{ID: "random-uuid", SchedulerName: scheduler.Name}

room := &game_room.GameRoom{
ID: firstRoomID,
SchedulerID: schedulerName,
SchedulerID: scheduler.Name,
}
secondRoom := &game_room.GameRoom{
ID: secondRoomID,
SchedulerID: schedulerName,
SchedulerID: scheduler.Name,
}

roomsManager.EXPECT().DeleteRoom(gomock.Any(), room, definition.Reason).Return(nil)
Expand All @@ -256,17 +256,17 @@ func TestExecutor_Execute(t *testing.T) {
firstRoomID := "first-room-id"
secondRoomID := "second-room-id"

schedulerName := uuid.NewString()
scheduler := newValidScheduler()
definition := &Definition{RoomsIDs: []string{firstRoomID, secondRoomID}}
op := &operation.Operation{ID: "random-uuid", SchedulerName: schedulerName}
op := &operation.Operation{ID: "random-uuid", SchedulerName: scheduler.Name}

room := &game_room.GameRoom{
ID: firstRoomID,
SchedulerID: schedulerName,
SchedulerID: scheduler.Name,
}
secondRoom := &game_room.GameRoom{
ID: secondRoomID,
SchedulerID: schedulerName,
SchedulerID: scheduler.Name,
}

roomsManager.EXPECT().DeleteRoom(gomock.Any(), room, definition.Reason).Return(nil)
Expand All @@ -283,17 +283,17 @@ func TestExecutor_Execute(t *testing.T) {
firstRoomID := "first-room-id"
secondRoomID := "second-room-id"

schedulerName := uuid.NewString()
scheduler := newValidScheduler()
definition := &Definition{RoomsIDs: []string{firstRoomID, secondRoomID}, Reason: "reason"}
op := &operation.Operation{ID: "random-uuid", SchedulerName: schedulerName}
op := &operation.Operation{ID: "random-uuid", SchedulerName: scheduler.Name}

room := &game_room.GameRoom{
ID: firstRoomID,
SchedulerID: schedulerName,
SchedulerID: scheduler.Name,
}
secondRoom := &game_room.GameRoom{
ID: secondRoomID,
SchedulerID: schedulerName,
SchedulerID: scheduler.Name,
}

roomsManager.EXPECT().DeleteRoom(gomock.Any(), room, definition.Reason).Return(nil)
Expand All @@ -309,9 +309,9 @@ func TestExecutor_Execute(t *testing.T) {
t.Run("should succeed - no rooms to be removed => returns without error", func(t *testing.T) {
executor, _, _, _, _ := testSetup(t)

schedulerName := uuid.NewString()
scheduler := newValidScheduler()
definition := &Definition{}
op := &operation.Operation{ID: "random-uuid", SchedulerName: schedulerName}
op := &operation.Operation{ID: "random-uuid", SchedulerName: scheduler.Name}

err := executor.Execute(context.Background(), op, definition)
require.Nil(t, err)
Expand All @@ -325,30 +325,30 @@ func TestExecutor_Execute(t *testing.T) {
thirdRoomID := "third-room-id"
fourthRoomID := "fourth-room-id"

schedulerName := uuid.NewString()
scheduler := newValidScheduler()
definition := &Definition{
RoomsIDs: []string{firstRoomID, secondRoomID},
Amount: 2,
Reason: "reason",
}
op := &operation.Operation{ID: "random-uuid", SchedulerName: schedulerName}
op := &operation.Operation{ID: "random-uuid", SchedulerName: scheduler.Name}

thirdRoom := &game_room.GameRoom{
ID: thirdRoomID,
SchedulerID: schedulerName,
SchedulerID: scheduler.Name,
Status: game_room.GameStatusReady,
}
fourthRoom := &game_room.GameRoom{
ID: fourthRoomID,
SchedulerID: schedulerName,
SchedulerID: scheduler.Name,
Status: game_room.GameStatusReady,
}

roomsManager.EXPECT().DeleteRoom(gomock.Any(), gomock.Any(), definition.Reason).Return(nil).Times(2)

availableRooms := []*game_room.GameRoom{thirdRoom, fourthRoom}
schedulerManager.EXPECT().GetActiveScheduler(gomock.Any(), schedulerName).Return(nil, errors.New("error getting active scheduler"))
roomsManager.EXPECT().ListRoomsWithDeletionPriority(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(availableRooms, nil)
schedulerManager.EXPECT().GetActiveScheduler(gomock.Any(), scheduler.Name).Return(scheduler, nil)
roomsManager.EXPECT().ListRoomsWithDeletionPriority(gomock.Any(), gomock.Any(), gomock.Any()).Return(availableRooms, nil)
roomsManager.EXPECT().DeleteRoom(gomock.Any(), gomock.Any(), definition.Reason).Return(nil).Times(2)

err := executor.Execute(context.Background(), op, definition)
Expand All @@ -366,3 +366,42 @@ func testSetup(t *testing.T) (*Executor, *mockports.MockRoomStorage, *mockports.
executor := NewExecutor(roomsManager, roomsStorage, operationManager, schedulerManager)
return executor, roomsStorage, roomsManager, operationManager, schedulerManager
}

func newValidScheduler() *entities.Scheduler {
return &entities.Scheduler{
Name: "scheduler",
Game: "game",
State: entities.StateCreating,
MaxSurge: "5",
RollbackVersion: "",
Spec: game_room.Spec{
Version: "v1.0.0",
TerminationGracePeriod: 60,
Toleration: "toleration",
Affinity: "affinity",
Containers: []game_room.Container{
{
Name: "default",
Image: "some-image:v1",
ImagePullPolicy: "IfNotPresent",
Command: []string{"hello"},
Ports: []game_room.ContainerPort{
{Name: "tcp", Protocol: "tcp", Port: 80},
},
Requests: game_room.ContainerResources{
CPU: "10m",
Memory: "100Mi",
},
Limits: game_room.ContainerResources{
CPU: "10m",
Memory: "100Mi",
},
},
},
},
PortRange: &port.PortRange{
Start: 40000,
End: 60000,
},
}
}
9 changes: 4 additions & 5 deletions internal/core/ports/mock/rooms_ports_mock.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 979af9e

Please sign in to comment.