Server: If-Modified-Since, block bis Änderung; Client: sofortiger Re-Poll
This commit is contained in:
11
app.js
11
app.js
@@ -440,13 +440,12 @@ function startAutoRefresh() {
|
|||||||
document.getElementById('refresh-timer').textContent = '● Live';
|
document.getElementById('refresh-timer').textContent = '● Live';
|
||||||
document.getElementById('refresh-timer').style.color = '#4ade80';
|
document.getElementById('refresh-timer').style.color = '#4ade80';
|
||||||
|
|
||||||
async function poll() {
|
const myId = ++pollId;
|
||||||
while (true) {
|
(async function poll() {
|
||||||
|
while (pollId === myId) {
|
||||||
await loadPGN(false);
|
await loadPGN(false);
|
||||||
await new Promise(r => setTimeout(r, 30000));
|
|
||||||
}
|
}
|
||||||
}
|
})();
|
||||||
poll();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -470,7 +469,7 @@ function hideError() {
|
|||||||
*/
|
*/
|
||||||
document.getElementById('refresh-btn').addEventListener('click', () => {
|
document.getElementById('refresh-btn').addEventListener('click', () => {
|
||||||
pollId++;
|
pollId++;
|
||||||
loadPGN(true);
|
loadPGN(true).then(() => startAutoRefresh());
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
45
server.py
45
server.py
@@ -8,6 +8,7 @@ import http.server
|
|||||||
import socketserver
|
import socketserver
|
||||||
import urllib.request
|
import urllib.request
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
|
import urllib.error
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import threading
|
import threading
|
||||||
@@ -31,28 +32,33 @@ last_standings_fetch_time = None
|
|||||||
|
|
||||||
|
|
||||||
def fetch_pgn():
|
def fetch_pgn():
|
||||||
"""Lädt die PGN-Datei von der URL als Bytes."""
|
"""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
|
global last_fetch_time
|
||||||
try:
|
try:
|
||||||
headers = {"User-Agent": "Mozilla/5.0"}
|
headers = {"User-Agent": "Mozilla/5.0"}
|
||||||
if last_fetch_time:
|
if last_fetch_time:
|
||||||
headers["modified_since"] = str(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(PGN_URL, headers=headers)
|
req = urllib.request.Request(PGN_URL, headers=headers)
|
||||||
with urllib.request.urlopen(req, timeout=31) as response:
|
with urllib.request.urlopen(req, timeout=31) as response:
|
||||||
data = response.read()
|
data = response.read()
|
||||||
last_fetch_time = time.time()
|
last_fetch_time = time.time()
|
||||||
return data
|
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}")
|
||||||
|
return None, False
|
||||||
except Exception as e:
|
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: {e}")
|
||||||
return None
|
return None, False
|
||||||
|
|
||||||
|
|
||||||
def get_pgn_content_longpoll(since=0):
|
def get_pgn_content_longpoll(since=0):
|
||||||
"""Long-Poll: Gibt PGN-Inhalt + mtime zurück.
|
"""Long-Poll: Blockiert, bis sich die PGN-Datei tatsächlich ändert.
|
||||||
Wenn Cache seit `since` unverändert ist, wird bis zu 31s gewartet."""
|
Antwortet nur bei neuen Daten, nie mit unverändertem Stand."""
|
||||||
deadline = time.time() + 31
|
while True:
|
||||||
|
|
||||||
while time.time() < deadline:
|
|
||||||
if os.path.exists(CACHE_FILE):
|
if os.path.exists(CACHE_FILE):
|
||||||
mtime = os.path.getmtime(CACHE_FILE)
|
mtime = os.path.getmtime(CACHE_FILE)
|
||||||
if mtime > since:
|
if mtime > since:
|
||||||
@@ -60,28 +66,21 @@ def get_pgn_content_longpoll(since=0):
|
|||||||
return f.read(), mtime
|
return f.read(), mtime
|
||||||
age = time.time() - mtime
|
age = time.time() - mtime
|
||||||
if age >= CACHE_TTL:
|
if age >= CACHE_TTL:
|
||||||
content = fetch_pgn()
|
content, changed = fetch_pgn()
|
||||||
if content:
|
if changed and content is not None:
|
||||||
with open(CACHE_FILE, "wb") as f:
|
with open(CACHE_FILE, "wb") as f:
|
||||||
f.write(content)
|
f.write(content)
|
||||||
new_mtime = os.path.getmtime(CACHE_FILE)
|
new_mtime = os.path.getmtime(CACHE_FILE)
|
||||||
if new_mtime > since:
|
print(f"[{datetime.now().strftime('%H:%M:%S')}] PGN via Long-Poll aktualisiert ({len(content)} Bytes)")
|
||||||
print(f"[{datetime.now().strftime('%H:%M:%S')}] PGN via Long-Poll aktualisiert ({len(content)} Bytes)")
|
return content, new_mtime
|
||||||
return content, new_mtime
|
|
||||||
else:
|
else:
|
||||||
content = fetch_pgn()
|
content, changed = fetch_pgn()
|
||||||
if content:
|
if changed and content is not None:
|
||||||
with open(CACHE_FILE, "wb") as f:
|
with open(CACHE_FILE, "wb") as f:
|
||||||
f.write(content)
|
f.write(content)
|
||||||
return content, os.path.getmtime(CACHE_FILE)
|
return content, os.path.getmtime(CACHE_FILE)
|
||||||
|
|
||||||
time.sleep(2)
|
time.sleep(5)
|
||||||
|
|
||||||
# Timeout – aktuellen Stand zurückgeben
|
|
||||||
if os.path.exists(CACHE_FILE):
|
|
||||||
with open(CACHE_FILE, "rb") as f:
|
|
||||||
return f.read(), os.path.getmtime(CACHE_FILE)
|
|
||||||
return None, 0
|
|
||||||
|
|
||||||
|
|
||||||
def fetch_standings():
|
def fetch_standings():
|
||||||
|
|||||||
Reference in New Issue
Block a user