fix(#3025): scope frontend neighbor-info fetch to current source + defensive lastHeard refresh#3049
Conversation
…igComplete Refs #3025. PR #3026 addressed one cause of NeighborInfo links not appearing in the UI — the read-side filter dropped rows whose `neighbor.lastHeard` was NULL (intentional state for indirect neighbors per #2615). The reporter has since confirmed the bug persists in v4.5.1, including for the local node's own NeighborInfo. This commit closes a second gap: between MeshMonitor startup and the first self-originated broadcast that echoes back through `processMeshPacket`, the local node's row has `lastHeard=NULL` (or whatever value was last persisted). When the filter at `sourceRoutes.ts:712` evaluates `!ni.node?.lastHeard || ni.node.lastHeard < cutoffTime`, every NeighborInfo row where the local node is the reporter gets silently dropped. The fix stamps `lastHeard = Date.now() / 1000` at every site where we have direct evidence the local device is alive: 1. `processMyNodeInfo` reboot-merge upsert (was missing lastHeard entirely) 2. `processMyNodeInfo` security-flag-clear upsert (same) 3. `processMyNodeInfo` rebootCount/hasRemoteAdmin update on existing node (same — receiving MyNodeInfo is itself liveness evidence) 4. `configComplete` handler — added a best-effort lastHeard refresh on the local node, since configComplete is a separate top-level protobuf type that doesn't flow through `processMeshPacket`. The bug reporter (#3025 / @SyselMitY) also describes remote-node scenarios where both endpoints have fresh `lastHeard` but rows are still dropped. That points at a different mechanism (sourceId scoping, units mismatch, or something else) which cannot be pinned down without the DB inspection they were asked to provide. This commit is intentionally scoped to the local-node liveness gap and does not attempt to address the remote-node case. Tests: - `npm run typecheck` clean - `npx vitest run` — full suite 4959/4959 passing No new dedicated unit test added — the existing `meshtasticManager.test.ts` exercises `processMyNodeInfo` via a simulated helper rather than the real method, and adding a meaningful DB-mock harness for this specific assertion would dwarf the four-line code change. Will revisit once the reporter confirms whether this defensive fix improves their scenario. Authored by Merlin 🪄 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The Messages-tab Neighbor Info block hits `fetchNeighborInfo` in App.tsx, which still pointed at the legacy non-source-scoped `/api/neighbor-info`. That route is mounted under `apiRouter` but in 4.x its handler returns [] for non-default sources because rows are partitioned by `sourceId`, so the UI silently rendered an empty list (HTTP 200, 0 entries) — exactly the symptom reported in #3025. Switch the call to `/api/sources/:sourceId/neighbor-info` (matching the pattern already used by `useDashboardData`) and gate the effect on `sourceId` so it refetches when the active source changes. Refs #3025 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Claude finished @Yeraze's task —— View job Code Review Completed ✅I've thoroughly reviewed PR #3049 that fixes issue #3025 regarding Meshtastic NeighborInfo packets not displaying in the Messages tab UI. Review Checklist:
✅ Overall Assessment: ApprovedThis is a well-executed fix that addresses two related issues causing the neighbor info display problem. The changes are minimal, targeted, and follow project conventions. 📋 Code Quality & Best Practices✅ Excellent:
✅ TypeScript & React:
🔍 Changes AnalysisFrontend Fix (
|
System Test ResultsMeshMonitor System Test ResultsTest Run: 2026-05-16 16:51:48 EDT Test Summary
❌ Overall Result: FAILEDSome tests failed. Please review the failures above and fix before creating/updating PR. Failed Tests
|
System Test ResultsMeshMonitor System Test ResultsTest Run: 2026-05-16 17:36:25 EDT Test Summary
❌ Overall Result: FAILEDSome tests failed. Please review the failures above and fix before creating/updating PR. Failed Tests
|
If test-api-exercise-all-backends.sh is killed before its EXIT trap can run `docker compose down -v` (e.g., CI step timeout, SIGKILL, daemon restart), its named test containers — `meshmonitor-api-exercise-*-test` — linger on the self-hosted hardware runner. On the next CI cycle the "Database Backing Consistency" pre-check trips on the orphan and bails out before any test code runs, and the api-exercise step itself can't bind its port. This poisons every subsequent system-test run until someone SSHs in and removes the container by hand (e.g., PR #3049 hit this exact state). Both scripts now remove their own — and known sibling — test-scoped container names at script start, before any pre-check or compose-up. The names hard-coded here belong exclusively to test scripts, so the removal can never touch a developer's running dev stack.
|
Claude finished @Yeraze's task —— View job Code Review Completed ✅I've thoroughly reviewed PR #3049 that fixes issue #3025 regarding Meshtastic NeighborInfo packets not displaying in the Messages tab UI. Review Checklist:
✅ Overall Assessment: ApprovedThis is a well-executed fix that addresses two related issues causing the neighbor info display problem. The changes are minimal, targeted, and follow project conventions. 📋 Code Quality & Best Practices✅ Excellent:
✅ TypeScript & React:
🔍 Changes AnalysisFrontend Fix (
|
System Test ResultsMeshMonitor System Test ResultsTest Run: 2026-05-16 18:15:29 EDT Test Summary
✅ Overall Result: PASSEDAll deployment configurations are working correctly! Test DetailsConfiguration Import:
Quick Start Test:
Security Test:
V1 API Test:
Reverse Proxy Test:
Reverse Proxy + OIDC Test:
Virtual Node CLI Test:
Backup & Restore Test:
Database Migration Test:
DB Backing Consistency Test:
|
Summary
Fixes #3025 — Meshtastic NeighborInfo packets are received and stored, but the Messages-tab UI shows nothing.
Two distinct bugs combined to produce the reported symptom; this branch addresses both:
Frontend was calling the wrong endpoint (root cause, surfaced by SyselMitY in the latest issue comment).
App.tsx#fetchNeighborInfostill pointed at the legacy/api/neighbor-inforoute. In 4.x that handler returns[]for non-default sources becauseneighbor_inforows are partitioned bysourceId, so the UI silently rendered an empty list (HTTP 200, 0 entries). Switched to/api/sources/:sourceId/neighbor-info— matching the pattern already used byuseDashboardData— and addedsourceIdto the effect's dep array so it refetches on source switch.Defensive
lastHeardrefresh on the local node (commitda1223b1, already on this branch). Between MeshMonitor start and the first self-originated broadcast that echoes through the packet pipeline, the local node row can havelastHeard=NULL. ThesourceRoutes.ts:712filter treats NULL as "stale reporter" and drops every NeighborInfo row sourced from the local node. We now refreshlastHeardwhenever we receiveMyNodeInfoorconfigComplete— both are direct evidence the local device just talked to us.Test plan
npx eslint src/App.tsx— no new errors/warnings introducednpx vitest run src/server/routes/sourceRoutes.neighbor-info.test.ts src/hooks/useDashboardData.test.ts— 29/29 pass🤖 Generated with Claude Code