Enha: tx for cron

This commit is contained in:
Grail Finder
2025-07-04 12:25:20 +03:00
parent 71a2d9d747
commit c2d6812230
5 changed files with 38 additions and 41 deletions

View File

@ -29,18 +29,36 @@ func (cm *CronManager) Start() {
}
func (cm *CronManager) CleanupRooms() {
ctx := context.Background()
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 {
@ -48,6 +66,7 @@ func (cm *CronManager) CleanupRooms() {
}
continue
}
creatorInRoom := false
for _, player := range players {
if player.Username == room.CreatorName {
@ -55,6 +74,7 @@ func (cm *CronManager) CleanupRooms() {
break
}
}
if !creatorInRoom {
cm.log.Info("deleting room because creator left", "room_id", room.ID)
for _, player := range players {
@ -73,4 +93,9 @@ func (cm *CronManager) CleanupRooms() {
}
}
}
if err := tx.Commit(); err != nil {
cm.log.Error("failed to commit transaction", "err", err)
}
}

View File

@ -47,41 +47,9 @@ func notifyBotIfNeeded(room *models.Room) {
}
}
// cache
// func saveState(username string, state *models.UserState) error {
// key := models.CacheStatePrefix + username
// data, err := json.Marshal(state)
// if err != nil {
// return err
// }
// memcache.Set(key, data)
// return nil
// }
// func getAllNames() []string {
// names := []string{}
// // will not scale
// session := &models.Session{}
// // filter by key size only sessions
// for _, name := range wholeMemStore {
// // xid is 20 in len
// if len(k) != 20 {
// continue
// }
// if err := json.Unmarshal(v, &session); err != nil {
// log.Error("failed to unmarshal", "error", err)
// continue
// }
// names = append(names, session.Username)
// }
// return names
// }
// can room exists without state? I think no
func getFullInfoByCtx(ctx context.Context) (*models.FullInfo, error) {
resp := &models.FullInfo{}
// state, err := getStateByCtx(ctx)
state, err := getPlayerByCtx(ctx)
if err != nil {
return nil, err

View File

@ -251,7 +251,7 @@ func HandleStartGame(w http.ResponseWriter, r *http.Request) {
func HandleJoinRoom(w http.ResponseWriter, r *http.Request) {
roomID := r.URL.Query().Get("id")
room, err := repo.RoomGetByID(r.Context(), roomID)
room, err := repo.RoomGetExtended(r.Context(), roomID)
if err != nil {
abortWithError(w, err.Error())
return

View File

@ -62,20 +62,16 @@ func main() {
// Setup graceful shutdown
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 {
panic(err)
}
}()
<-stop
slog.Info("Shutting down server...")
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)

View File

@ -2,6 +2,7 @@ package repos
import (
"context"
"fmt"
"gralias/models"
"github.com/jmoiron/sqlx"
@ -60,10 +61,17 @@ func (p *RepoProvider) PlayerDelete(ctx context.Context, roomID, username string
return err
}
func (p *RepoProvider) PlayerSetRoomID(ctx context.Context, username, roomID string) error {
func (p *RepoProvider) PlayerSetRoomID(ctx context.Context, roomID, username string) error {
db := getDB(ctx, p.DB)
_, err := db.ExecContext(ctx, "UPDATE players SET room_id = ? WHERE username = ?", roomID, username)
return err
res, err := db.ExecContext(ctx, "UPDATE players SET room_id = ? WHERE username = ?", roomID, username)
if err != nil {
return err
}
affected, _ := res.RowsAffected()
if affected == 0 {
return fmt.Errorf("failed to set room_id (%s) for player (%s)", roomID, username)
}
return nil
}
func (p *RepoProvider) PlayerExitRoom(ctx context.Context, username string) error {