diff --git a/crons/main.go b/crons/main.go index 78d739e..6eee827 100644 --- a/crons/main.go +++ b/crons/main.go @@ -27,7 +27,7 @@ func (cm *CronManager) Start() { for range ticker.C { cm.CleanupRooms() cm.CleanupActions() - cm.CleanupInactiveRooms() + cm.CleanupPlayersRoom() } }() } @@ -71,6 +71,7 @@ func (cm *CronManager) CleanupRooms() { } continue } + creatorInRoom := false for _, player := range players { if player.Username == room.CreatorName { @@ -78,8 +79,32 @@ func (cm *CronManager) CleanupRooms() { break } } - if !creatorInRoom { - cm.log.Info("deleting room because creator left", "room_id", room.ID) + + isInactive := false + // If the creator is in the room and the room is more than one hour old, check for inactivity + if creatorInRoom && time.Since(room.CreatedAt) > time.Hour { + lastActionTime, err := cm.repo.ActionGetLastTimeByRoomID(ctx, room.ID) + if err != nil && !errors.Is(err, sql.ErrNoRows) { + cm.log.Error("failed to get last action time for room", "room_id", room.ID, "err", err) + // Skip setting isInactive and proceed + } else { + // If there are no actions, lastActionTime is the zero value (or from sql.ErrNoRows we get zero as well) + if lastActionTime.IsZero() { + isInactive = true + } else if time.Since(lastActionTime) > time.Hour { + isInactive = true + } + } + } + + // If the creator is not in the room or the room is inactive, it's time to delete + if !creatorInRoom || isInactive { + reason := "creator left" + if isInactive { + reason = "inactive" + } + cm.log.Info("deleting room", "room_id", room.ID, "reason", reason) + for _, player := range players { if player.IsBot { if err := cm.repo.PlayerDelete(ctx, room.ID, player.Username); err != nil { @@ -91,12 +116,16 @@ func (cm *CronManager) CleanupRooms() { } } } + if err := cm.repo.RoomDeleteByID(ctx, room.ID); err != nil { - cm.log.Error("failed to delete room after creator left", "room_id", room.ID, "err", err) + cm.log.Error("failed to delete room", "room_id", room.ID, "reason", reason, "err", err) } if err := cm.repo.SettingsDeleteByRoomID(ctx, room.ID); err != nil { - cm.log.Error("failed to delete settings after creator left", "room_id", room.ID, "err", err) + cm.log.Error("failed to delete settings for room", "room_id", room.ID, "reason", reason, "err", err) } + + // Move to the next room + continue } } if err := tx.Commit(); err != nil { @@ -129,50 +158,3 @@ func (cm *CronManager) CleanupActions() { cm.log.Error("failed to commit transaction for actions cleanup", "err", err) } } - -func (cm *CronManager) CleanupInactiveRooms() { - ctx, tx, err := cm.repo.InitTx(context.Background()) - if err != nil { - cm.log.Error("failed to init transaction for inactive rooms cleanup", "err", err) - return - } - defer func() { - if r := recover(); r != nil { - if err := tx.Rollback(); err != nil { - cm.log.Error("failed to rollback transaction for inactive rooms cleanup", "err", err) - } - panic(r) - } - }() - rooms, err := cm.repo.RoomList(ctx) - if err != nil { - cm.log.Error("failed to get rooms list for inactive rooms cleanup", "err", err) - if err := tx.Rollback(); err != nil { - cm.log.Error("failed to rollback transaction for inactive rooms cleanup", "err", err) - } - return - } - for _, room := range rooms { - lastActionTime, err := cm.repo.ActionGetLastTimeByRoomID(ctx, room.ID) - if err != nil && !errors.Is(err, sql.ErrNoRows) { - cm.log.Error("failed to get last action time for room", "room_id", room.ID, "err", err) - continue - } - if lastActionTime.IsZero() && time.Since(room.CreatedAt) > time.Hour { - cm.log.Info("deleting inactive room (no actions)", "room_id", room.ID, "created_at", room.CreatedAt) - if err := cm.repo.RoomDeleteByID(ctx, room.ID); err != nil { - cm.log.Error("failed to delete inactive room (no actions)", "room_id", room.ID, "err", err) - } - continue - } - if !lastActionTime.IsZero() && time.Since(lastActionTime) > time.Hour && time.Since(room.CreatedAt) > time.Hour { - cm.log.Info("deleting inactive room (last action older than 1 hour)", "room_id", room.ID, "last_action_time", lastActionTime) - if err := cm.repo.RoomDeleteByID(ctx, room.ID); err != nil { - cm.log.Error("failed to delete inactive room (last action older than 1 hour)", "room_id", room.ID, "err", err) - } - } - } - if err := tx.Commit(); err != nil { - cm.log.Error("failed to commit transaction for inactive rooms cleanup", "err", err) - } -} diff --git a/crons/players.go b/crons/players.go new file mode 100644 index 0000000..228e5bf --- /dev/null +++ b/crons/players.go @@ -0,0 +1,58 @@ +package crons + +import "context" + +func (cm *CronManager) CleanupPlayersRoom() { + ctx, tx, err := cm.repo.InitTx(context.Background()) + if err != nil { + cm.log.Error("failed to init transaction for actions cleanup", "err", err) + return + } + defer func() { + if r := recover(); r != nil { + if err := tx.Rollback(); err != nil { + cm.log.Error("failed to rollback transaction for actions cleanup", "err", err) + } + panic(r) + } + }() + players, err := cm.repo.PlayerListAll(ctx) + if err != nil { + cm.log.Error("failed to list players", "err", err) + if err := tx.Rollback(); err != nil { + cm.log.Error("failed to rollback transaction for actions cleanup", "err", err) + } + return + } + // get all rooms to have only one req + rooms, err := cm.repo.RoomList(ctx) + if err != nil { + cm.log.Error("failed to list rooms", "err", err) + if err := tx.Rollback(); err != nil { + cm.log.Error("failed to rollback transaction for actions cleanup", "err", err) + } + return + } + for _, player := range players { + found := false + for _, room := range rooms { + // check if room exists + if player.RoomID != nil && room.ID == *player.RoomID { + found = true + break + } + } + if !found { + // delete roomid from player + if err := cm.repo.PlayerExitRoom(ctx, player.Username); err != nil { + cm.log.Error("failed to unset room", "err", err) + if err := tx.Rollback(); err != nil { + cm.log.Error("failed to rollback transaction for actions cleanup", "err", err) + } + } + } + } + if err := tx.Commit(); err != nil { + cm.log.Error("failed to commit transaction for actions cleanup", "err", err) + } +} diff --git a/repos/players.go b/repos/players.go index 13378b7..0c86dfd 100644 --- a/repos/players.go +++ b/repos/players.go @@ -17,6 +17,7 @@ type PlayersRepo interface { PlayerExitRoom(ctx context.Context, username string) error PlayerListNames(ctx context.Context) ([]string, error) PlayerList(ctx context.Context, isBot bool) ([]models.Player, error) + PlayerListAll(ctx context.Context) ([]models.Player, error) PlayerListByRoom(ctx context.Context, roomID string) ([]models.Player, error) } @@ -95,6 +96,16 @@ func (p *RepoProvider) PlayerList(ctx context.Context, isBot bool) ([]models.Pla return players, nil } +func (p *RepoProvider) PlayerListAll(ctx context.Context) ([]models.Player, error) { + var players []models.Player + query := "SELECT id, room_id, username, team, role, is_bot FROM players;" + err := sqlx.SelectContext(ctx, p.DB, &players, query) + if err != nil { + return nil, err + } + return players, nil +} + func (p *RepoProvider) PlayerListByRoom(ctx context.Context, roomID string) ([]models.Player, error) { var players []models.Player err := sqlx.SelectContext(ctx, p.DB, &players, "SELECT id, room_id, username, team, role, is_bot FROM players WHERE room_id = ?", roomID)