refactor: deduplicate persistence, add upsert queries, throttle snake saves
- Replace Create+Get+Update with UpsertGame/UpsertSnakeGame queries - Extract free functions (saveGame, loadGame, etc.) from duplicated receiver methods on Store and Instance types - Remove duplicate generateID from snake package, reuse game.GenerateID - Throttle snake game DB writes to every 2s instead of every tick - Fix double-lock in c4game chat handler - Update all code for sqlc pointer types (*string instead of sql.NullString)
This commit is contained in:
@@ -62,16 +62,14 @@ func (si *SnakeGameInstance) countdownPhase() {
|
||||
si.game.Status = StatusInProgress
|
||||
|
||||
if si.queries != nil {
|
||||
si.saveSnakeGame(si.game) //nolint:errcheck
|
||||
saveSnakeGame(si.queries, si.game) //nolint:errcheck
|
||||
}
|
||||
si.gameMu.Unlock()
|
||||
si.notify()
|
||||
return
|
||||
}
|
||||
|
||||
if si.queries != nil {
|
||||
si.saveSnakeGame(si.game) //nolint:errcheck
|
||||
}
|
||||
// No DB save during countdown ticks — state is transient
|
||||
si.gameMu.Unlock()
|
||||
si.notify()
|
||||
}
|
||||
@@ -98,6 +96,7 @@ func (si *SnakeGameInstance) gamePhase() {
|
||||
defer ticker.Stop()
|
||||
|
||||
lastInput := time.Now()
|
||||
lastSave := time.Now()
|
||||
var moveAccum time.Duration
|
||||
|
||||
for {
|
||||
@@ -124,7 +123,7 @@ func (si *SnakeGameInstance) gamePhase() {
|
||||
if time.Since(lastInput) > inactivityLimit {
|
||||
si.game.Status = StatusFinished
|
||||
if si.queries != nil {
|
||||
si.saveSnakeGame(si.game) //nolint:errcheck
|
||||
saveSnakeGame(si.queries, si.game) //nolint:errcheck
|
||||
}
|
||||
si.gameMu.Unlock()
|
||||
si.notify()
|
||||
@@ -175,13 +174,10 @@ func (si *SnakeGameInstance) gamePhase() {
|
||||
alive := AliveCount(state)
|
||||
gameOver := false
|
||||
if si.game.Mode == ModeSinglePlayer {
|
||||
// Single player ends when the player dies (alive == 0)
|
||||
if alive == 0 {
|
||||
gameOver = true
|
||||
// No winner in single player - just final score
|
||||
}
|
||||
} else {
|
||||
// Multiplayer ends when 1 or fewer alive
|
||||
if alive <= 1 {
|
||||
gameOver = true
|
||||
winnerIdx := LastAlive(state)
|
||||
@@ -195,8 +191,10 @@ func (si *SnakeGameInstance) gamePhase() {
|
||||
si.game.Status = StatusFinished
|
||||
}
|
||||
|
||||
if si.queries != nil {
|
||||
si.saveSnakeGame(si.game) //nolint:errcheck
|
||||
// Throttle DB saves: persist on game over or every 2 seconds
|
||||
if si.queries != nil && (gameOver || time.Since(lastSave) >= 2*time.Second) {
|
||||
saveSnakeGame(si.queries, si.game) //nolint:errcheck
|
||||
lastSave = time.Now()
|
||||
}
|
||||
|
||||
si.gameMu.Unlock()
|
||||
|
||||
Reference in New Issue
Block a user