This is an automated email from the ASF dual-hosted git repository.
wu-sheng pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-horizon-ui.git
The following commit(s) were added to refs/heads/main by this push:
new bf5a64d skills(local-boot): document the stale-process trap
bf5a64d is described below
commit bf5a64d9c8476cf63da8b90998688eed0108e244
Author: Wu Sheng <[email protected]>
AuthorDate: Thu May 21 11:33:59 2026 +0800
skills(local-boot): document the stale-process trap
tsx watch keeps the old BFF alive, so a relaunch with a new config dies
on EADDRINUSE while the old process keeps serving the old OAP — a config
switch silently "doesn't take". Boot now kills both watcher patterns,
loops until :8081 is free, and verifies the live OAP target via
/api/oap/config adminUrl instead of trusting the relaunch.
---
.claude/skills/local-boot/SKILL.md | 27 ++++++++++++++++++++++-----
1 file changed, 22 insertions(+), 5 deletions(-)
diff --git a/.claude/skills/local-boot/SKILL.md
b/.claude/skills/local-boot/SKILL.md
index b3bb31b..62f528a 100644
--- a/.claude/skills/local-boot/SKILL.md
+++ b/.claude/skills/local-boot/SKILL.md
@@ -36,14 +36,29 @@ env | grep -iE '^(http_proxy|https_proxy|all_proxy)=' &&
echo "local proxy detec
The browser uses its OWN proxy settings (not the shell's), so the developer
must also let `127.0.0.1` / `localhost` go direct (ClashX "bypass localhost" /
system proxy no-proxy list). The env-level bypass below only fixes CLI tools
and Vite's own fetches.
+## The stale-process trap (why a config switch "didn't take")
+
+`tsx watch` keeps the old BFF alive, so a freshly launched BFF with a NEW
config silently dies on `EADDRINUSE: 127.0.0.1:8081` while the OLD process
keeps serving the OLD OAP. Symptom: you switch local↔demo, everything looks
fine, but the UI still shows the previous OAP's data.
+
+Killing matters in two ways:
+- `pkill -f "tsx watch src/server.ts"` may miss the actual listener — also
`pkill -f "tsx/dist/cli.mjs watch"`, and **verify the port is actually free
with `lsof` before relaunching** (loop until free; the watcher can respawn a
child).
+- After boot, **confirm which OAP the LIVE process is using** — don't trust
that your new process won the port. The authoritative check:
+ ```bash
+ curl -s --noproxy '*' -b /tmp/sw.cookies
http://127.0.0.1:8081/api/oap/config | grep -oE '"adminUrl":"[^"]*"'
+ # local => http://localhost:12800 ; demo =>
https://demo.skywalking.apache.org:17128
+ ```
+ Also grep the boot log for `EADDRINUSE` and the `configPath` line. If the
adminUrl is wrong, a stale BFF is still bound — kill it, confirm `:8081` is
free, relaunch.
+
## Boot against the local OAP
```bash
REPO="$(git rev-parse --show-toplevel)"
-# 1. Make sure nothing stale holds the BFF port (a wrong-config process
-# on :8081 makes a fresh one fail with EADDRINUSE and you keep hitting
-# the old one). Kill any prior dev servers first:
-pkill -f "tsx watch src/server.ts" 2>/dev/null; pkill -f vite 2>/dev/null;
sleep 1
+# 1. Kill prior dev servers AND confirm :8081 is actually free — a stale
+# BFF holding the port makes the new one die on EADDRINUSE while the
+# old config keeps serving (see "stale-process trap"):
+pkill -f "tsx watch src/server.ts" 2>/dev/null
+pkill -f "tsx/dist/cli.mjs watch" 2>/dev/null; pkill -f vite 2>/dev/null
+until ! lsof -nP -iTCP:8081 -sTCP:LISTEN >/dev/null 2>&1; do sleep 1; done
# 2. BFF — absolute config path is mandatory (see gotcha above):
HORIZON_CONFIG="$REPO/.claude/skills/local-boot/horizon.local.yaml" \
@@ -68,7 +83,9 @@ developer for it and export it before booting:
REPO="$(git rev-parse --show-toplevel)"
read -rsp "Demo OAP password: " OAP_PASSWORD && export OAP_PASSWORD && echo
-pkill -f "tsx watch src/server.ts" 2>/dev/null; pkill -f vite 2>/dev/null;
sleep 1
+pkill -f "tsx watch src/server.ts" 2>/dev/null
+pkill -f "tsx/dist/cli.mjs watch" 2>/dev/null; pkill -f vite 2>/dev/null
+until ! lsof -nP -iTCP:8081 -sTCP:LISTEN >/dev/null 2>&1; do sleep 1; done
HORIZON_CONFIG="$REPO/.claude/skills/local-boot/horizon.demo.yaml" \
pnpm --filter @skywalking-horizon-ui/bff run dev &
( cd "$REPO/apps/ui" && \