Feat: add cleaner cron
This commit is contained in:
@ -1,6 +1,7 @@
|
||||
BASE_URL = "https://localhost:3000"
|
||||
SESSION_LIFETIME_SECONDS = 30000
|
||||
COOKIE_SECRET = "test"
|
||||
DB_PATH = "sqlite3://gralias.db"
|
||||
|
||||
[SERVICE]
|
||||
HOST = "localhost"
|
||||
|
@ -13,6 +13,7 @@ type Config struct {
|
||||
SessionLifetime int64 `toml:"SESSION_LIFETIME_SECONDS"`
|
||||
CookieSecret string `toml:"COOKIE_SECRET"`
|
||||
LLMConfig LLMConfig `toml:"LLM"`
|
||||
DBPath string `toml:"DB_PATH"`
|
||||
}
|
||||
|
||||
type ServerConfig struct {
|
||||
@ -38,6 +39,7 @@ func LoadConfigOrDefault(fn string) *Config {
|
||||
config.CookieSecret = "test"
|
||||
config.ServerConfig.Host = "localhost"
|
||||
config.ServerConfig.Port = "3000"
|
||||
config.DBPath = "sqlite3://gralias.db"
|
||||
}
|
||||
fmt.Printf("config debug; config.LLMConfig.URL: %s\n", config.LLMConfig.URL)
|
||||
return config
|
||||
|
76
crons/main.go
Normal file
76
crons/main.go
Normal file
@ -0,0 +1,76 @@
|
||||
package crons
|
||||
|
||||
import (
|
||||
"context"
|
||||
"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()
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (cm *CronManager) CleanupRooms() {
|
||||
ctx := context.Background()
|
||||
rooms, err := cm.repo.RoomList(ctx)
|
||||
if err != nil {
|
||||
cm.log.Error("failed to get rooms list", "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)
|
||||
}
|
||||
continue
|
||||
}
|
||||
creatorInRoom := false
|
||||
for _, player := range players {
|
||||
if player.Username == room.CreatorName {
|
||||
creatorInRoom = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !creatorInRoom {
|
||||
cm.log.Info("deleting room because creator left", "room_id", room.ID)
|
||||
for _, player := range players {
|
||||
if player.IsBot {
|
||||
if err := cm.repo.PlayerDelete(ctx, room.ID, player.Username); 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 after creator left", "room_id", room.ID, "err", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -168,7 +168,9 @@ func HandleStartGame(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
tx.Rollback()
|
||||
if err := tx.Rollback(); err != nil {
|
||||
log.Error("failed to rollback transaction", "error", err)
|
||||
}
|
||||
panic(r)
|
||||
}
|
||||
}()
|
||||
@ -189,7 +191,9 @@ func HandleStartGame(w http.ResponseWriter, r *http.Request) {
|
||||
fi.Room.ActionHistory = append(fi.Room.ActionHistory, action)
|
||||
// Use the new context with transaction
|
||||
if err := saveFullInfo(ctx, fi); err != nil {
|
||||
tx.Rollback()
|
||||
if err := tx.Rollback(); err != nil {
|
||||
log.Error("failed to rollback transaction", "error", err)
|
||||
}
|
||||
abortWithError(w, err.Error())
|
||||
return
|
||||
}
|
||||
@ -197,7 +201,9 @@ func HandleStartGame(w http.ResponseWriter, r *http.Request) {
|
||||
action.RoomID = fi.Room.ID
|
||||
action.CreatedAt = time.Now()
|
||||
if err := repo.CreateAction(ctx, fi.Room.ID, &action); err != nil {
|
||||
tx.Rollback()
|
||||
if err := tx.Rollback(); err != nil {
|
||||
log.Error("failed to rollback transaction", "error", err)
|
||||
}
|
||||
log.Error("failed to save action", "error", err)
|
||||
abortWithError(w, err.Error())
|
||||
return
|
||||
@ -206,7 +212,9 @@ func HandleStartGame(w http.ResponseWriter, r *http.Request) {
|
||||
for _, card := range fi.Room.Cards {
|
||||
card.RoomID = fi.Room.ID // Ensure RoomID is set for each card
|
||||
if err := repo.WordCardsCreate(ctx, &card); err != nil {
|
||||
tx.Rollback()
|
||||
if err := tx.Rollback(); err != nil {
|
||||
log.Error("failed to rollback transaction", "error", err)
|
||||
}
|
||||
log.Error("failed to save word card", "error", err)
|
||||
abortWithError(w, err.Error())
|
||||
return
|
||||
|
@ -70,7 +70,9 @@ func GetSession(next http.Handler) http.Handler {
|
||||
return
|
||||
}
|
||||
if userSession.IsExpired() {
|
||||
repo.SessionDelete(r.Context(), sessionToken)
|
||||
if err := repo.SessionDelete(r.Context(), sessionToken); err != nil {
|
||||
log.Error("failed to delete session", "error", err)
|
||||
}
|
||||
// cache.MemCache.RemoveKey(sessionToken)
|
||||
msg := "session is expired"
|
||||
log.Debug(msg, "error", err, "token", sessionToken)
|
||||
|
8
main.go
8
main.go
@ -3,7 +3,9 @@ package main
|
||||
import (
|
||||
"context"
|
||||
"gralias/config"
|
||||
"gralias/crons"
|
||||
"gralias/handlers"
|
||||
"gralias/repos"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"os"
|
||||
@ -61,6 +63,12 @@ func main() {
|
||||
stop := make(chan os.Signal, 1)
|
||||
signal.Notify(stop, os.Interrupt, syscall.SIGTERM)
|
||||
|
||||
repo := repos.NewRepoProvider(cfg.DBPath)
|
||||
defer repo.Close()
|
||||
|
||||
cm := crons.NewCronManager(repo, slog.Default())
|
||||
cm.Start()
|
||||
|
||||
server := ListenToRequests(cfg.ServerConfig.Port)
|
||||
go func() {
|
||||
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||||
|
@ -104,3 +104,7 @@ func (p *RepoProvider) InitTx(ctx context.Context) (context.Context, *sqlx.Tx, e
|
||||
}
|
||||
return context.WithValue(ctx, "tx", tx), tx, nil
|
||||
}
|
||||
|
||||
func (p *RepoProvider) Close() {
|
||||
p.DB.Close()
|
||||
}
|
||||
|
@ -16,6 +16,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)
|
||||
PlayerListByRoom(ctx context.Context, roomID string) ([]models.Player, error)
|
||||
}
|
||||
|
||||
func (p *RepoProvider) PlayerListNames(ctx context.Context) ([]string, error) {
|
||||
@ -85,3 +86,12 @@ func (p *RepoProvider) PlayerList(ctx context.Context, isBot bool) ([]models.Pla
|
||||
}
|
||||
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)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return players, nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user