- TOURNAMENT_SERVICE_URL was 8086 but K8s service and app both use 8088
- TOURNAMENT_SELF_URL on htwg-1 should be base ingress URL (port 80),
not a direct service port — ingress routes /api/tournament to tournament service
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Was pointing at third-party server (141.37.123.132). Should be htwg-1's
own tournament service IP so remote clusters can proxy mutations back here.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Official-bots now targets local tournament service (TOURNAMENT_SERVICE_URL)
instead of calling remote cluster directly
- TOURNAMENT_SELF_URL tells each cluster's tournament and official-bots
services their own public URL for cross-cluster replication
- htwg-1-prod: remove TOURNAMENT_SERVER_URL, add both new vars with correct
values (tournament active service + node IP for self-announcement)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Service is named nowchess-account-active, not nowchess-account. DNS resolution
failed on startup causing official bots to never sync and appear unavailable.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
70B model at 30-50 tok/s was exceeding the 30s urllib timeout for larger
outputs. Raise server timeout to 60s, add browser AbortController at 65s
so the UI fails gracefully. Trim max_tokens (row: 300, dataset: 512) to
keep generation well inside the window.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Single-threaded HTTPServer blocked readiness probes during long NIM API
calls (~30s), causing Kubernetes to flip the pod unhealthy until the
request completed. ThreadingHTTPServer handles each request in its own
thread so probes are never starved.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add ⚡ button on each row (first 200) — clicking analyses that specific
row with a chess-expert prompt tailored to the entry type (opening,
player, etc.)
- Cache results per row so already-analysed rows skip re-requests
- Serialise all NIM requests through a promise queue to avoid bursting
- Pass 429 + Retry-After through from NIM to the browser; JS surfaces
"Rate limited — retry in Ns" error and re-enables the button for retry
- Dataset-level "Analyse top 10 rows" now sends a per-row numbered prompt
asking for chess-specific analysis of each entry rather than a vague
dataset summary
- Store first 200 rows in window.DATASET.rows for client-side row access
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Browser cannot call integrate.api.nvidia.com directly — no CORS headers.
Add POST /explain endpoint: browser sends key + dataset, server calls NIM
with urllib, returns JSON. Key is never logged or stored server-side.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Python triple-quoted string interprets \n as literal newlines,
producing invalid JS string literals and a SyntaxError that
killed the entire script block.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Each dataset page now has an "Explain this dataset" button that calls the
NVIDIA NIM chat completions API (meta/llama-3.3-70b-instruct) directly from
the browser with headers + first 10 rows as context. API key is entered via
a settings modal and stored in localStorage only — never sent to the server.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Points to /spark-output/.pgn-cache so the decompressed Lichess PGN file
is written to the shared PVC, accessible by both driver and executor pods.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
do-block-storage only supports ReadWriteOnce. Executor tasks failed with
`Mkdirs failed` because the executor ran on the spark-worker node which
had no mount of the spark-analytics-output PVC.
- Mount spark-analytics-output PVC on spark-worker pod at /spark-output
- Add podAffinity to all 11 analytics CronJob driver pods to schedule on
the same node as spark-worker, ensuring the RWO PVC is accessible by
both driver and executor
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
13 separate DB connections on index page caused readiness probe timeout.
Now all counts share one connection. BrokenPipeError on probe disconnect silenced.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Handle URLs without explicit port, show DB_HOST:PORT/DB_NAME in error messages
and startup log to simplify connection debugging.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Rewrite webview serve.py to query PostgreSQL analytics tables via psycopg2
instead of reading CSV files from PVC; PVC mount removed from Deployment
- Remove isPgnMode guard from all 4 original jobs so results always write to DB
regardless of whether input comes from game_records or a Lichess PGN dump
- Add JDBC write-back to all 7 new analytics jobs (game_length_distribution,
game_length_by_result, color_advantage, elo_distribution, time_control_stats,
hourly_activity, weekly_activity, rating_mismatch, termination_stats)
- Add analytics_component_sizes JDBC write to PlayerGraphJob
- Add NOWCHESS_PGN_PATH staging patches for the 7 new CronJobs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds CronJobs and headless driver Services for GameLengthJob, ColorAdvantageJob,
EloDistributionJob, TimeControlJob, DailyActivityJob, RatingMismatchJob, and
TerminationStatsJob. All suspended by default; scheduled Saturday mornings.
Adds spark-analytics-webview: a stdlib Python HTTP server (ConfigMap + Deployment
+ Service) that reads CSV output from the spark-analytics-output PVC and renders
13 datasets as browsable HTML tables. Disabled (replicas=0) in base.
Staging overlay enables the webview (replicas=1), exposes it via Ingress at
spark-results-st.nowchess.janis-eccarius.de, and sets NOWCHESS_PGN_PATH on all
CronJobs to the Lichess Jan-2013 rated standard PGN dump for demo runs without
a NowChess database.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add proxy-read-timeout and proxy-send-timeout (3600s) so nginx does not
drop long-lived WebSocket connections at the default 60s idle timeout.
Add use-regex: "true" to staging to match production — without it, the
ImplementationSpecific path for the game WebSocket
(/api/board/game/[A-Za-z0-9]{8}/ws) is treated as a literal string
instead of a regex and never matches real game IDs.
---------
Co-authored-by: LQ63 <lkhermann@web.de>
Reviewed-on: #419
Co-authored-by: Leon Hermann <lq@blackhole.local>
Co-committed-by: Leon Hermann <lq@blackhole.local>
Add /api/analysis → nowchess-analysis-active:8087 path rule to
eu-central-1-staging, eu-central-1-prod, and htwg-1-prod ingresses.
Rule placed before the /api catch-all so nginx routes correctly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The merged rollout set JWT_PUBLIC_KEY_PATH, but the running image's
config never references it, so mp.jwt.verify.publickey.location stayed
null and every token failed with "Verification key is unresolvable".
Replace it with the MicroProfile properties the runtime reads directly
(MP_JWT_VERIFY_PUBLICKEY_LOCATION, MP_JWT_VERIFY_ISSUER), pointing at the
already-mounted ncs-jwt-keys public key. No image rebuild needed.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reviewed-on: #416
The official-bots rollout never mounted the ncs-jwt-keys secret nor set
JWT_PUBLIC_KEY_PATH, so the service fell back to the image-baked
public.pem, which does not match the deployed signing key. Every token
failed RS256 verification -> 401.
Mount ncs-jwt-keys at /secrets/jwt and point JWT_PUBLIC_KEY_PATH there,
mirroring account/core/tournament. Verify-only, no private key.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Reviewed-on: #413