Commit Graph

7 Commits

Author SHA1 Message Date
Kpa-clawbot
df63efa78d fix: poll new observations for existing transmissions (fixes #174)
The poller only queried WHERE t.id > sinceID, which missed new
observations added to transmissions already in the store. The trace
page was correct because it always queries the DB directly.

Add IngestNewObservations() that polls observations by o.id watermark,
adds them to existing StoreTx entries, re-picks best observation, and
invalidates analytics caches. The Poller now tracks both lastTxID and
lastObsID watermarks.

Includes tests for v3, v2, dedup, best-path re-pick, and
GetMaxObservationID.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-27 17:26:26 -07:00
Kpa-clawbot
f55a3454aa feat(go): replace map[string]interface{} with typed Go structs in route handlers
Phase 1: Create cmd/server/types.go with ~80 typed response structs
matching all proto definitions. Every API response shape is now a
compile-time checked struct.

Phase 2: Rewire all route handlers in routes.go to construct typed
structs instead of map[string]interface{} for response building:
- /api/stats -> StatsResponse
- /api/health -> HealthResponse
- /api/perf -> PerfResponse
- /api/config/* -> typed config responses
- /api/nodes/* -> NodeListResponse, NodeDetailResponse, etc.
- /api/packets/* -> PacketListResponse, PacketDetailResponse
- /api/analytics/* -> RFAnalyticsResponse, TopologyResponse, etc.
- /api/observers/* -> ObserverListResponse, ObserverResp
- /api/channels/* -> ChannelListResponse, ChannelMessagesResponse
- /api/traces/* -> TraceResponse
- /api/resolve-hops -> ResolveHopsResponse
- /api/iata-coords -> IataCoordsResponse (typed IataCoord)
- /api/audio-lab/buckets -> AudioLabBucketsResponse
- WebSocket broadcast -> WSMessage struct
- SlowQuery tracking -> SlowQuery struct (was map)

Phase 3 (partial): Add typed store/db methods:
- PacketStore.GetCacheStatsTyped() -> CacheStats
- PacketStore.GetPerfStoreStatsTyped() -> PerfPacketStoreStats
- DB.GetDBSizeStatsTyped() -> SqliteStats

Remaining map usage is in store/db data flow (PacketResult.Packets
still uses maps) — these will be addressed in a follow-up.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-27 15:17:21 -07:00
Kpa-clawbot
fc494962d1 fix(go): add broadcast diagnostic logging, rebuild fixes stale deployment
The Go staging packets page wasn't live-updating because the deployed
binary was stale (built before the #162 fix). Rebuilding from current
source fixed the issue — broadcasts now fire correctly.

Added two permanent diagnostic log lines:
- [poller] IngestNewFromDB: logs when new transmissions are found
- [broadcast] sending N packets to M clients: logs each broadcast batch

These log lines make it easy to verify the broadcast pipeline is working
and would have caught this stale-deployment issue immediately.

Verified on VM: WS clients receive packets with nested 'packet' field,
all Go tests pass.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-27 14:15:19 -07:00
Kpa-clawbot
95afaf2f0d fix(go): add nested packet field to WS broadcast, fixes #162
The frontend packets.js filters WS messages with m.data?.packet and
extracts m.data.packet for live rendering. Node's server.js includes
a packet sub-object (packet: fullPacket) in the broadcast data, but
Go's IngestNewFromDB built the data flat without a nested packet field.

This caused the Go staging packets page to never live-update via WS
even though messages were being sent — they were silently filtered out
by packets.js.

Fix: build the packet fields map separately, then create the broadcast
map with both top-level fields (for live.js) and nested packet (for
packets.js). Also fixes the fallback DB-direct poller path.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-27 13:31:37 -07:00
Kpa-clawbot
afe16db960 feat(go-server): in-memory packet store — port of packet-store.js
Streams transmissions + observations from SQLite at startup into
5 indexed in-memory structures. QueryPackets and QueryGroupedPackets
now serve from RAM (<10ms) instead of hitting SQLite (2.3s).

- store.go: PacketStore with byHash, byTxID, byObsID, byObserver, byNode indexes
- main.go: create + load store at startup
- routes.go: dispatch to store for packet/stats endpoints
- websocket.go: poller ingests new transmissions into store

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-27 08:52:07 -07:00
Kpa-clawbot
b2e6c8105b fix: handle WebSocket upgrade at root path (client connects to ws://host/)
Node.js upgrades WS at /, Go was only at /ws. Now the static file
handler checks for Upgrade header first and routes to WebSocket.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-27 01:25:35 -07:00
Kpa-clawbot
742ed86596 feat: add Go web server (cmd/server/) — full API + WebSocket + static files
35+ REST endpoints matching Node.js server, WebSocket broadcast,
static file serving with SPA fallback, config.json support.
Uses modernc.org/sqlite (pure Go, no CGO required).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-27 01:16:59 -07:00