feat: add live replays and PostgreSQL maintenance tools
Build and Push Docker Container / build-and-push (push) Successful in 7m53s

- Stream compact live replay updates across local and clustered dashboards.
- Render responsive snake bodies as SVG paths with aligned custom icons.
- Add cache-busted assets, replay fallback routes, and live-follow playback.
- Support PostgreSQL benchmark sampling and idempotent SQLite migration.
- Add dry-run cleanup for old low-quality PostgreSQL replay payloads.
- Reward safe perimeter lanes and bump Prism to version 1.5.0.
- Add backend, migration, dashboard, and perimeter regression coverage.
This commit is contained in:
2026-08-02 00:50:46 +02:00
parent 9b99b526e4
commit f14d780f29
29 changed files with 1574 additions and 310 deletions
+17 -4
View File
@@ -13,8 +13,8 @@ from server.metrics import (
MetricsCollector,
)
import asyncio, signal, logging, os, re, time
from quart import Quart
import asyncio, signal, logging, time, os, re
from quart import Quart, url_for
from server.blueprints import (
create_battlesnake_blueprint,
@@ -110,6 +110,17 @@ class Server:
self.app.register_blueprint(create_metrics_blueprint(self))
self.app.register_blueprint(create_dashboard_blueprint(self))
@self.app.template_global()
def static_url(filename:str) -> str:
# Static assets are served with a long max-age, so the URL carries the
# file mtime to make browsers pick up dashboard changes immediately.
static_root = self.app.static_folder or ''
try:
version = int(os.path.getmtime(os.path.join(static_root, filename)))
except OSError:
version = 0
return f'{url_for("static", filename=filename)}?v={version}'
@self.app.after_request
async def identify_server(response):
response.headers.set('server', 'battlesnake/gitea/snake-python')
@@ -185,5 +196,7 @@ class Server:
storage = StorageLoader.build(self.storage_type)
return storage.cleanup()
async def _on_dashboard_games_update_notice(self, trigger:str) -> None:
await self.dashboard_query.on_dashboard_games_update_notice(trigger)
async def _on_dashboard_games_update_notice(
self, trigger:str, game_id:str|None=None,
) -> None:
await self.dashboard_query.on_dashboard_games_update_notice(trigger, game_id)