otel: real auto-refresh dashboard + HTTP self-warm (kills cold p99)
Dashboard: drop the non-functional data-on-load SSE attr; add <meta refresh 3s> so it genuinely live-updates (the host serves single-body responses, no server-push SSE). /otel/stream stays a snapshot for pollers. serve.sh: replace the ineffective boot-time make-app warmup (wrong JIT context) with a backgrounded self-warmer that GETs the hot pages over real HTTP (bash /dev/tcp — no curl in the image) once /health is up, so the first real visitor after a restart gets ~78ms instead of the one-time ~2.5s serving-JIT compile.
This commit is contained in:
@@ -28,6 +28,28 @@ fi
|
||||
|
||||
PORT="${HOST_PORT:-8910}"
|
||||
|
||||
# Self-warm the SERVING JIT. The FIRST HTTP request after a restart pays a one-time
|
||||
# ~2.5s cost: the shared request path (session middleware + router + instrumented
|
||||
# handlers + blog render) JIT-compiles under the http-listen resolver, a context a
|
||||
# boot-time render can't reach. So once the server is answering, we GET the hot
|
||||
# pages ONCE over real HTTP to absorb that compile before a visitor does (~2.5s ->
|
||||
# ~78ms warm). The container image has no curl/wget, so we speak HTTP over bash's
|
||||
# /dev/tcp. Runs detached (survives the exec below); exits after warming.
|
||||
_warm_serving_jit() {
|
||||
local path
|
||||
# wait until /health answers 200 (the port opens only after all modules load)
|
||||
for _ in $(seq 1 180); do
|
||||
case "$( { exec 3<>/dev/tcp/127.0.0.1/"$PORT" && printf 'GET /health HTTP/1.0\r\nHost: x\r\n\r\n' >&3 && head -1 <&3; exec 3>&- 3<&-; } 2>/dev/null )" in
|
||||
*200*) break ;;
|
||||
esac
|
||||
sleep 0.5
|
||||
done
|
||||
for path in / /welcome /nt-live-encore /otel; do
|
||||
{ exec 3<>/dev/tcp/127.0.0.1/"$PORT" && printf 'GET %s HTTP/1.0\r\nHost: x\r\n\r\n' "$path" >&3 && cat <&3 >/dev/null; exec 3>&- 3<&-; } 2>/dev/null
|
||||
done
|
||||
}
|
||||
_warm_serving_jit &
|
||||
|
||||
# Modules: every load line from conformance.sh's MODULES list, minus the ledger
|
||||
# (not needed to serve). server.sx supplies host/serve.
|
||||
MODULES=(
|
||||
@@ -195,14 +217,6 @@ EPOCH=1
|
||||
echo "(epoch $EPOCH)"
|
||||
echo "(eval \"(define host/-serve-groups (list host/static-routes otel/routes host/feed-routes host/relations-routes (host/blog-write-routes (fn (tok) nil)) host/blog-routes))\")"
|
||||
EPOCH=$((EPOCH+1))
|
||||
# JIT warmup: render the hot pages once through a throwaway app so the FIRST real
|
||||
# visitor after a restart doesn't eat the cold-compile cost. The blog render path
|
||||
# (comp-fold + relations + typed-block) JIT-compiles on first call — that was the
|
||||
# ~2.5s p99 on /:slug, vs ~78ms warm. Reset the otel ring after so warmup spans
|
||||
# don't skew the live metrics.
|
||||
echo "(epoch $EPOCH)"
|
||||
echo "(eval \"(let ((warm (host/make-app host/-serve-groups))) (begin (warm (dream-request \\\"GET\\\" \\\"/\\\" {} \\\"\\\")) (warm (dream-request \\\"GET\\\" \\\"/welcome\\\" {} \\\"\\\")) (warm (dream-request \\\"GET\\\" \\\"/nt-live-encore\\\" {} \\\"\\\")) (warm (dream-request \\\"GET\\\" \\\"/otel\\\" {} \\\"\\\")) (otel/reset!) nil))\")"
|
||||
EPOCH=$((EPOCH+1))
|
||||
echo "(epoch $EPOCH)"
|
||||
echo "(eval \"(host/serve $PORT host/-serve-groups)\")"
|
||||
} | exec "$SX_SERVER"
|
||||
|
||||
Reference in New Issue
Block a user