Add ?bbox= viewport filtering to /api/v1/topology/edges #78
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Add viewport (?bbox=) filtering to GET /api/v1/topology/edges so the "Show all topology" client (see #72) can fetch only the edges visible in the current map view.
Why
Follow-up to #72. Without viewport filtering, the endpoint returns every edge in the mesh up to the soft cap (web.map.topology_max_edges, default 2000). For larger deployments the client either hits the cap and sees a misleading "(2000+)" count, or we raise the cap and inflate every payload. bbox is the obvious fix: only request edges whose
endpoints fall inside the current Leaflet viewport, then refetch on moveend (debounced). The user gets a complete local view cheaply.
Concerns
Filed as "design and measure before implementing" because the current SQLite schema and indexes are not obviously a good fit:
Open questions
Acceptance criteria
☐ ?bbox=lat1,lng1,lat2,lng2 query parameter supported on /api/v1/topology/edges.
☐ Invalid bbox values return 400 with a clear error.
☐ Endpoint still respects web.map.topology_cache_ttl and web.map.topology_max_edges.
☐ openapi.yaml documents the new parameter.
☐ httptest covers: valid bbox returns subset; bbox outside data range returns empty; malformed bbox returns 400.
☐ Benchmark or documented numbers showing the query is fast enough for a 5k-edge, 1k-node dataset.
Related
The issue is already well-shaped (acceptance criteria, related work, open questions). Concrete suggestions for the how, grounded in the existing Go/SQLite stack.
SQLite path (recommended for v1)
The body itself flags "SQLite + rtree or composite indexes" as the path. Two viable index strategies:
(lat, lng)with the bbox query rewritten to a pair oflat BETWEEN ? AND ?+lng BETWEEN ? AND ?rtreevirtual table, separate from the mainnodestable)rtreeback to the mainnodestableRecommendation: start with (A), but build the bbox query as a function so (B) is a drop-in if the planner complains. Something like:
Adding the
idx_nodes_lat_lngindex is one line in the migration; the query above is then index-friendly.The three open questions, one answer each
buffer = max(0.1, 0.05 / zoom)for example). Server stays dumb. This also matches the body: "long-range links" are a display concern, not a data concern.topology_evidence_max_ageserver-side? Worth verifying with a quick grep in the topology handler. If it's client-side, the bbox-filtered query should still respect it — add aWHERE evidence.created_at > ?clause and pass the cutoff as a parameter. One-line change.topology_max_edgescap on top of bbox? Yes, but the response should also include atruncated: trueflag with the visible-vs-total count, so the client can show "(N visible, M total in viewport)" rather than a misleading "(2000+)". One extra field in the response struct.Buffer expansion math (client-side)
These are starting numbers; tune from telemetry. The point is the buffer is in the client's code, so changing it doesn't touch the API.
httptest cases (mapped to the acceptance criteria)
These pin down the contract and the failure modes.
OpenAPI doc snippet
Suggested order of work
idx_nodes_lat_lngmigration (idempotent; one line).edgesInBboxas a separate function (no API change yet).moveend(debounced ~300ms).The "design and measure before implementing" note in the issue body is the right instinct — step 5 is the only place where the design choice between (A) and (B) gets settled. Until you've measured, (A) is the right default.