mirror of
https://github.com/Kpa-clawbot/meshcore-analyzer.git
synced 2026-10-11 20:37:38 +00:00
Each entry in the comma-separated `nodes=` list on `GET /api/packets` costs one SQLite lookup (`resolveNodePubkey`) while the packet store's read lock is held. A 1 MB URL fits about 15,000 entries. On a test instance 12,000 entries took 1.3 s per request, against 0.9 ms for one entry, and the lock stalls the poller's writes for that long. A few parallel clients can keep the site busy and the live feed stale. **Fix:** lists longer than 50 entries get HTTP 400 with a clear message. No UI page sends more than a handful. **Tests:** `multi_node_cap_test.go` — 50 entries return 200, 51 return 400. Full `go test ./...` in `cmd/server` passes. Running in production on our instance since 2026-10-07. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Mythos 5.1 <noreply@anthropic.com>
39 lines
1.1 KiB
Go
39 lines
1.1 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// GET /api/packets?nodes=... resolves every entry with a SQLite lookup while
|
|
// holding the packet store's read lock, so the list must be capped.
|
|
func TestMultiNodePacketsListCap(t *testing.T) {
|
|
_, router := setupTestServerWithAPIKey(t, "")
|
|
|
|
get := func(n int) *httptest.ResponseRecorder {
|
|
keys := make([]string, n)
|
|
for i := range keys {
|
|
keys[i] = fmt.Sprintf("%064x", i+1)
|
|
}
|
|
req := httptest.NewRequest("GET", "/api/packets?nodes="+strings.Join(keys, ",")+"&limit=1", nil)
|
|
w := httptest.NewRecorder()
|
|
router.ServeHTTP(w, req)
|
|
return w
|
|
}
|
|
|
|
t.Run("at the cap is accepted", func(t *testing.T) {
|
|
if w := get(maxMultiNodePubkeys); w.Code != http.StatusOK {
|
|
t.Fatalf("expected 200 for %d nodes, got %d (body: %s)", maxMultiNodePubkeys, w.Code, w.Body.String())
|
|
}
|
|
})
|
|
|
|
t.Run("one over the cap is rejected with 400", func(t *testing.T) {
|
|
if w := get(maxMultiNodePubkeys + 1); w.Code != http.StatusBadRequest {
|
|
t.Fatalf("expected 400 for %d nodes, got %d (body: %s)", maxMultiNodePubkeys+1, w.Code, w.Body.String())
|
|
}
|
|
})
|
|
}
|