mirror of
https://github.com/MeshCore-Beacon/beacon-server.git
synced 2026-10-22 13:02:26 +00:00
Port the qualified server preview at84ac3c8781onto org devc7209b7043. Preserve upstream changes and branch policies; keep the independent private Collector service separate. Preview-Version: 2.2.0-n30nex.1 Preview-Revision:84ac3c8781
45 lines
1.7 KiB
Go
45 lines
1.7 KiB
Go
// Copyright 2026 Beacon Contributors
|
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
package handlers
|
|
|
|
import (
|
|
"context"
|
|
"github.com/MeshCore-Beacon/beacon-server/internal/api"
|
|
"net/http"
|
|
"time"
|
|
)
|
|
|
|
// getTopologyLinks godoc
|
|
// @Summary Unique adjacent route links for a topology snapshot
|
|
// @Description Returns up to 100000 undirected node-ID pairs, deduplicated across known routes. Minute-aligned window includes the current minute. Existing rate limits apply; no per-node lookup or route pagination is needed. Capped is true when more links exist.
|
|
// @Tags Routes
|
|
// @Produce json
|
|
// @Param window query string false "History window: 15m (default), 1h, or 24h"
|
|
// @Param iatas query string false "Comma-separated reception IATA codes"
|
|
// @Success 200 {object} api.TopologyLinks
|
|
// @Failure 400 {object} handlers.APIError
|
|
// @Failure 503 {object} handlers.APIError
|
|
// @Router /routes/topology [get]
|
|
func getTopologyLinks(reader api.Reader) http.HandlerFunc {
|
|
return func(w http.ResponseWriter, r *http.Request) {
|
|
window := r.URL.Query().Get("window")
|
|
if window == "" {
|
|
window = "15m"
|
|
}
|
|
duration, ok := map[string]time.Duration{"15m": 15 * time.Minute, "1h": time.Hour, "24h": 24 * time.Hour}[window]
|
|
if !ok {
|
|
respondError(w, http.StatusBadRequest, "window must be 15m, 1h or 24h")
|
|
return
|
|
}
|
|
until := time.Now().UTC().Truncate(time.Minute).Add(time.Minute)
|
|
ctx, cancel := context.WithTimeout(r.Context(), 15*time.Second)
|
|
defer cancel()
|
|
links, err := reader.GetTopologyLinks(ctx, parseIATAs(r), until.Add(-duration), until)
|
|
if err != nil {
|
|
respondError(w, http.StatusServiceUnavailable, "route snapshot unavailable; try again shortly")
|
|
return
|
|
}
|
|
respond(w, http.StatusOK, links)
|
|
}
|
|
}
|