Enha: cron for cleaning rooms from players

This commit is contained in:
Grail Finder
2025-07-06 10:13:38 +03:00
parent a685686b32
commit a38472a685
3 changed files with 103 additions and 52 deletions

View File

@ -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)
}
}

58
crons/players.go Normal file
View File

@ -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)
}
}

View File

@ -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)