Fix caching issue - load fresh PGN for current round
This commit is contained in:
106
server.py
106
server.py
@@ -25,73 +25,70 @@ CACHE_TTL = int(os.environ.get("CACHE_TTL", 31))
|
||||
|
||||
os.makedirs(CACHE_DIR, exist_ok=True)
|
||||
|
||||
last_fetch_time = None
|
||||
last_standings_fetch_time = None
|
||||
current_round = 0 # wird aus der Tabelle ermittelt
|
||||
|
||||
|
||||
def get_pgn_url():
|
||||
return f"https://www.deutsche-schachjugend.de/2026/odjm-d/partien/{current_round}.pgn"
|
||||
def get_pgn_url(round_num=None):
|
||||
if round_num is None:
|
||||
round_num = current_round
|
||||
return f"https://www.deutsche-schachjugend.de/2026/odjm-d/partien/{round_num}.pgn"
|
||||
|
||||
|
||||
def get_cache_file():
|
||||
return os.path.join(CACHE_DIR, f"runde-{current_round}.pgn")
|
||||
def get_cache_file(round_num=None):
|
||||
if round_num is None:
|
||||
round_num = current_round
|
||||
return os.path.join(CACHE_DIR, f"runde-{round_num}.pgn")
|
||||
|
||||
|
||||
def fetch_pgn():
|
||||
def fetch_pgn(round_num=None):
|
||||
"""Lädt die PGN-Datei von der URL als Bytes.
|
||||
Nutzt If-Modified-Since – gibt (data, changed) zurück.
|
||||
changed=False bedeutet 304 Not Modified (keine neuen Daten)."""
|
||||
global last_fetch_time
|
||||
if current_round == 0:
|
||||
Gibt (data, True) bei Erfolg oder (None, False) bei Fehler zurück."""
|
||||
if round_num is None:
|
||||
round_num = current_round
|
||||
if round_num == 0:
|
||||
return None, False
|
||||
url = get_pgn_url()
|
||||
url = get_pgn_url(round_num)
|
||||
try:
|
||||
headers = {"User-Agent": "Mozilla/5.0"}
|
||||
if last_fetch_time:
|
||||
headers["If-Modified-Since"] = datetime.utcfromtimestamp(last_fetch_time).strftime("%a, %d %b %Y %H:%M:%S GMT")
|
||||
req = urllib.request.Request(url, headers=headers)
|
||||
with urllib.request.urlopen(req, timeout=31) as response:
|
||||
data = response.read()
|
||||
last_fetch_time = time.time()
|
||||
return data, True
|
||||
except urllib.error.HTTPError as e:
|
||||
if e.code == 304:
|
||||
return None, False
|
||||
print(f"[{datetime.now().strftime('%H:%M:%S')}] HTTP-Fehler: {e}")
|
||||
print(f"[{datetime.now().strftime('%H:%M:%S')}] HTTP-Fehler (Runde {round_num}): {e}")
|
||||
return None, False
|
||||
except Exception as e:
|
||||
print(f"[{datetime.now().strftime('%H:%M:%S')}] Fehler beim Laden: {e}")
|
||||
print(f"[{datetime.now().strftime('%H:%M:%S')}] Fehler beim Laden (Runde {round_num}): {e}")
|
||||
return None, False
|
||||
|
||||
|
||||
def get_pgn_content_longpoll(since=0):
|
||||
"""Long-Poll: Blockiert, bis sich die PGN-Datei tatsächlich ändert.
|
||||
Antwortet nur bei neuen Daten, nie mit unverändertem Stand."""
|
||||
while True:
|
||||
cache_file = get_cache_file()
|
||||
if os.path.exists(cache_file):
|
||||
mtime = os.path.getmtime(cache_file)
|
||||
if mtime > since:
|
||||
with open(cache_file, "rb") as f:
|
||||
return f.read(), mtime
|
||||
age = time.time() - mtime
|
||||
if age >= CACHE_TTL:
|
||||
content, changed = fetch_pgn()
|
||||
if changed and content is not None:
|
||||
with open(cache_file, "wb") as f:
|
||||
f.write(content)
|
||||
new_mtime = os.path.getmtime(cache_file)
|
||||
print(f"[{datetime.now().strftime('%H:%M:%S')}] PGN via Long-Poll aktualisiert ({len(content)} Bytes)")
|
||||
return content, new_mtime
|
||||
else:
|
||||
content, changed = fetch_pgn()
|
||||
if changed and content is not None:
|
||||
with open(cache_file, "wb") as f:
|
||||
f.write(content)
|
||||
return content, os.path.getmtime(cache_file)
|
||||
def get_round_pgn(round_num):
|
||||
"""Gibt PGN-Daten für eine Runde zurück.
|
||||
Bei der aktuellen Runde wird immer live von der DSJ geholt."""
|
||||
cache_file = get_cache_file(round_num)
|
||||
|
||||
time.sleep(5)
|
||||
if round_num == current_round:
|
||||
content, changed = fetch_pgn(round_num)
|
||||
if changed and content is not None:
|
||||
with open(cache_file, "wb") as f:
|
||||
f.write(content)
|
||||
return content, os.path.getmtime(cache_file)
|
||||
if os.path.exists(cache_file):
|
||||
with open(cache_file, "rb") as f:
|
||||
return f.read(), os.path.getmtime(cache_file)
|
||||
return None, 0
|
||||
|
||||
if os.path.exists(cache_file):
|
||||
with open(cache_file, "rb") as f:
|
||||
return f.read(), os.path.getmtime(cache_file)
|
||||
|
||||
content, changed = fetch_pgn(round_num)
|
||||
if changed and content is not None:
|
||||
with open(cache_file, "wb") as f:
|
||||
f.write(content)
|
||||
return content, os.path.getmtime(cache_file)
|
||||
return None, 0
|
||||
|
||||
|
||||
def fetch_standings():
|
||||
@@ -165,19 +162,27 @@ class PGNHandler(http.server.BaseHTTPRequestHandler):
|
||||
|
||||
parts = parsed_path.path.strip("/").split("/")
|
||||
if len(parts) == 2 and parts[0] == "pgn" and parts[1].isdigit():
|
||||
params = urllib.parse.parse_qs(parsed_path.query)
|
||||
since = float(params.get("since", [0])[0])
|
||||
content, mtime = get_pgn_content_longpoll(since)
|
||||
round_num = int(parts[1])
|
||||
|
||||
if round_num <= 0 or round_num > current_round + 1:
|
||||
self.send_response(404)
|
||||
self.send_header("Content-Type", "application/json")
|
||||
self.send_header("Access-Control-Allow-Origin", "*")
|
||||
self.end_headers()
|
||||
self.wfile.write(json.dumps({"error": "Runde nicht verf\u00fcgbar"}).encode())
|
||||
return
|
||||
|
||||
content, mtime = get_round_pgn(round_num)
|
||||
|
||||
if content:
|
||||
self.send_response(200)
|
||||
self.send_header("Content-Type", "text/plain; charset=utf-8")
|
||||
self.send_header("Access-Control-Allow-Origin", "*")
|
||||
self.send_header("Cache-Control", "no-cache")
|
||||
self.send_header("X-Cache-Mtime", str(mtime))
|
||||
self.end_headers()
|
||||
self.wfile.write(content)
|
||||
else:
|
||||
self.send_response(502)
|
||||
self.send_response(404)
|
||||
self.send_header("Content-Type", "application/json")
|
||||
self.send_header("Access-Control-Allow-Origin", "*")
|
||||
self.end_headers()
|
||||
@@ -191,8 +196,6 @@ class PGNHandler(http.server.BaseHTTPRequestHandler):
|
||||
self.end_headers()
|
||||
status = {
|
||||
"status": "ok",
|
||||
"last_fetch": last_fetch_time,
|
||||
"cache_ttl": CACHE_TTL,
|
||||
"server_time": time.time()
|
||||
}
|
||||
self.wfile.write(json.dumps(status).encode())
|
||||
@@ -259,6 +262,7 @@ def background_refresh():
|
||||
cache_file = get_cache_file()
|
||||
with open(cache_file, "wb") as f:
|
||||
f.write(content)
|
||||
print(f"[{datetime.now().strftime('%H:%M:%S')}] Hintergrund-Refresh: PGN aktualisiert ({len(content)} Bytes)")
|
||||
except Exception as e:
|
||||
print(f"[{datetime.now().strftime('%H:%M:%S')}] Hintergrund-Refresh Fehler: {e}")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user