161 lines
4.5 KiB
Go
161 lines
4.5 KiB
Go
package crons
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"errors"
|
|
"gralias/repos"
|
|
"log/slog"
|
|
"time"
|
|
)
|
|
|
|
type CronManager struct {
|
|
repo repos.AllRepos
|
|
log *slog.Logger
|
|
}
|
|
|
|
func NewCronManager(repo repos.AllRepos, log *slog.Logger) *CronManager {
|
|
return &CronManager{
|
|
repo: repo,
|
|
log: log,
|
|
}
|
|
}
|
|
|
|
func (cm *CronManager) Start() {
|
|
ticker := time.NewTicker(30 * time.Second)
|
|
go func() {
|
|
for range ticker.C {
|
|
cm.CleanupRooms()
|
|
cm.CleanupActions()
|
|
cm.CleanupPlayersRoom()
|
|
ticker.Reset(30 * time.Second)
|
|
}
|
|
}()
|
|
}
|
|
|
|
func (cm *CronManager) CleanupRooms() {
|
|
ctx, tx, err := cm.repo.InitTx(context.Background())
|
|
if err != nil {
|
|
cm.log.Error("failed to init transaction", "err", err)
|
|
return
|
|
}
|
|
defer func() {
|
|
if r := recover(); r != nil {
|
|
if err := tx.Rollback(); err != nil {
|
|
cm.log.Error("failed to rollback transaction", "err", err)
|
|
}
|
|
panic(r)
|
|
}
|
|
}()
|
|
rooms, err := cm.repo.RoomList(ctx)
|
|
if err != nil {
|
|
cm.log.Error("failed to get rooms list", "err", err)
|
|
if err := tx.Rollback(); err != nil {
|
|
cm.log.Error("failed to rollback transaction", "err", err)
|
|
}
|
|
return
|
|
}
|
|
for _, room := range rooms {
|
|
players, err := cm.repo.PlayerListByRoom(ctx, room.ID)
|
|
if err != nil {
|
|
cm.log.Error("failed to get players for room", "room_id", room.ID, "err", err)
|
|
continue
|
|
}
|
|
|
|
if len(players) == 0 {
|
|
cm.log.Info("deleting empty room", "room_id", room.ID)
|
|
if err := cm.repo.RoomDeleteByID(ctx, room.ID); err != nil {
|
|
cm.log.Error("failed to delete empty room", "room_id", room.ID, "err", err)
|
|
}
|
|
if err := cm.repo.SettingsDeleteByRoomID(ctx, room.ID); err != nil {
|
|
cm.log.Error("failed to delete settings for empty room", "room_id", room.ID, "err", err)
|
|
}
|
|
continue
|
|
}
|
|
|
|
creatorInRoom := false
|
|
for _, player := range players {
|
|
if player.Username == room.CreatorName {
|
|
creatorInRoom = true
|
|
break
|
|
}
|
|
}
|
|
|
|
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); err != nil {
|
|
cm.log.Error("failed to delete bot player", "room_id", room.ID, "username", player.Username, "err", err)
|
|
}
|
|
} else {
|
|
if err := cm.repo.PlayerExitRoom(ctx, player.Username); err != nil {
|
|
cm.log.Error("failed to update player room", "room_id", room.ID, "username", player.Username, "err", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
if err := cm.repo.RoomDeleteByID(ctx, room.ID); err != nil {
|
|
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 for room", "room_id", room.ID, "reason", reason, "err", err)
|
|
}
|
|
|
|
// Move to the next room
|
|
continue
|
|
}
|
|
}
|
|
if err := tx.Commit(); err != nil {
|
|
cm.log.Error("failed to commit transaction", "err", err)
|
|
}
|
|
}
|
|
|
|
func (cm *CronManager) CleanupActions() {
|
|
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)
|
|
}
|
|
}()
|
|
if err := cm.repo.ActionDeleteOrphaned(ctx); err != nil {
|
|
cm.log.Error("failed to delete orphaned actions", "err", err)
|
|
if err := tx.Rollback(); err != nil {
|
|
cm.log.Error("failed to rollback transaction for actions cleanup", "err", err)
|
|
}
|
|
return
|
|
}
|
|
if err := tx.Commit(); err != nil {
|
|
cm.log.Error("failed to commit transaction for actions cleanup", "err", err)
|
|
}
|
|
}
|