mirror of
https://github.com/nolen777/eagle0.git
synced 2026-07-28 22:55:41 +00:00
Auto-invalidate game cache when flush marker is updated (#5273)
During warmup, the staging server may cache stale game data that was loaded before the active server flushed. Instead of exposing an RPC for cache invalidation (which leaks internal state), the server now automatically detects when the flush marker is updated and invalidates any cached games. Changes: - GamesManager: Added `invalidateCacheIfFlushMarkerUpdated()` that checks the flush marker's modification time and clears the cache if it's been updated since the last check - Called before checking if a game is in cache, so stale data is cleared before any attempt to use it - Removed the InvalidateGameCache RPC (no longer needed) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -304,9 +304,10 @@ main() {
|
||||
|
||||
# Step 6: Create flush marker - signals that disk state is fresh
|
||||
# Any waiting lazy-loads on staging will now proceed with fresh data.
|
||||
# The Eagle server automatically detects the flush marker update and invalidates any stale cached games.
|
||||
log_info "[DEPLOY:${deploy_id}] Step 6: Creating flush marker..."
|
||||
create_flush_marker "${deploy_id}" "eagle-${staging}"
|
||||
log_info "[DEPLOY:${deploy_id}] Flush marker created - waiting lazy-loads can now proceed"
|
||||
log_info "[DEPLOY:${deploy_id}] Flush marker created - server will auto-invalidate stale cache"
|
||||
|
||||
# Update .env for admin service
|
||||
local env_file="${APP_DIR}/.env"
|
||||
|
||||
@@ -261,6 +261,45 @@ class GamesManager(
|
||||
shardokClient.connect()
|
||||
}
|
||||
|
||||
// Track the flush marker mod time to detect when it's been updated
|
||||
@volatile private var lastFlushMarkerCheck: Long = 0L
|
||||
@volatile private var flushMarkerModTime: Long = 0L
|
||||
|
||||
/**
|
||||
* Checks if the flush marker has been updated since we last loaded games. If so, invalidates the cache so games
|
||||
* reload from fresh disk state.
|
||||
*
|
||||
* This handles blue-green deployments automatically: if games were cached during warmup (before the active server
|
||||
* flushed), we detect the new flush marker and clear the cache. No external RPC needed.
|
||||
*/
|
||||
private def invalidateCacheIfFlushMarkerUpdated(): Unit = {
|
||||
val now = System.currentTimeMillis()
|
||||
// Only check every 100ms to avoid excessive file system access
|
||||
if now - lastFlushMarkerCheck < 100 then return
|
||||
lastFlushMarkerCheck = now
|
||||
|
||||
val flushMarker = java.nio.file.Paths.get(SaveDirectory.saveDirectory, ".flush_complete")
|
||||
if !java.nio.file.Files.exists(flushMarker) then return
|
||||
|
||||
try {
|
||||
val currentModTime = java.nio.file.Files.getLastModifiedTime(flushMarker).toMillis
|
||||
if currentModTime > flushMarkerModTime then {
|
||||
val cachedCount = gameControllerInfos.size
|
||||
if cachedCount > 0 then {
|
||||
SimpleTimedLogger.printLogger.logLine(
|
||||
s"[DEPLOY] Flush marker updated, invalidating $cachedCount cached games"
|
||||
)
|
||||
gameControllerInfos = Map.empty
|
||||
gamesAwaitingPlayers = Vector.empty
|
||||
removedGameIds = Set.empty
|
||||
}
|
||||
flushMarkerModTime = currentModTime
|
||||
}
|
||||
} catch {
|
||||
case _: Exception => // Ignore errors checking marker
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the current games.e0es file from disk to get metadata about running games. Called fresh each time to handle
|
||||
* race conditions during blue-green deployment (e.g., a game created on the old server after the new server started).
|
||||
@@ -370,6 +409,10 @@ class GamesManager(
|
||||
* true if game is now loaded (or was already loaded), false if game doesn't exist
|
||||
*/
|
||||
private def ensureGameLoaded(gameId: GameId): Boolean = {
|
||||
// Check if flush marker was updated - if so, invalidate any stale cached games
|
||||
// This handles the case where games were cached during warmup before the active server flushed
|
||||
invalidateCacheIfFlushMarkerUpdated()
|
||||
|
||||
if gameControllerInfos.contains(gameId) then return true
|
||||
|
||||
// Wait for flush marker before loading from disk to ensure we get fresh data
|
||||
|
||||
Reference in New Issue
Block a user