mirror of
https://github.com/MeshCore-Beacon/beacon-server.git
synced 2026-10-20 11:01:56 +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
76 lines
2.5 KiB
Go
76 lines
2.5 KiB
Go
// Copyright 2026 Beacon Contributors
|
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
package meshmapper
|
|
|
|
import (
|
|
"encoding/json"
|
|
"time"
|
|
|
|
"github.com/MeshCore-Beacon/beacon-server/internal/scopestore"
|
|
)
|
|
|
|
// CatalogueScope is regional source metadata, not per-node forwarding evidence.
|
|
type CatalogueScope struct {
|
|
Name string `json:"name"`
|
|
Repeaters int `json:"repeaters"`
|
|
Default int `json:"default"`
|
|
Monitored bool `json:"monitored"`
|
|
Wardriving bool `json:"wardriving"`
|
|
}
|
|
|
|
type PublicScopeCatalogue struct {
|
|
IATA string `json:"iata"`
|
|
URL string `json:"url"`
|
|
GeneratedAt int64 `json:"generatedAt"`
|
|
CheckedAt int64 `json:"checkedAt"`
|
|
FreshUntil int64 `json:"freshUntil"`
|
|
LastError string `json:"lastError,omitempty"`
|
|
Repeaters int `json:"repeaters"`
|
|
Scoped int `json:"scoped"`
|
|
Scopes []CatalogueScope `json:"scopes"`
|
|
}
|
|
|
|
// Catalogues returns an immutable snapshot of discovered sources. No request
|
|
// triggers an upstream fetch or reads ingestion tables. Callers must not mutate it.
|
|
func (i *Importer) Catalogues() []PublicScopeCatalogue {
|
|
if i != nil {
|
|
if snapshot := i.catalogues.Load(); snapshot != nil {
|
|
return snapshot.([]PublicScopeCatalogue)
|
|
}
|
|
}
|
|
return []PublicScopeCatalogue{}
|
|
}
|
|
|
|
func (i *Importer) publishCatalogues() {
|
|
result := make([]PublicScopeCatalogue, 0, len(i.sources))
|
|
for _, s := range i.sources {
|
|
c := PublicScopeCatalogue{IATA: s.iata, URL: s.url, LastError: s.cache.LastError, Scopes: []CatalogueScope{}}
|
|
if !s.cache.CheckedAt.IsZero() {
|
|
c.CheckedAt = s.cache.CheckedAt.UnixMilli()
|
|
c.FreshUntil = s.cache.CheckedAt.Add(i.interval + 5*time.Minute).UnixMilli()
|
|
}
|
|
if len(s.cache.Payload) > 0 {
|
|
// Reuse the importer validation before exposing saved metadata. Invalid
|
|
// saved catalogues are omitted just as they are from the scope matcher.
|
|
if _, generated, err := decode(s.cache.Payload, s.iata); err == nil {
|
|
var payload struct {
|
|
Repeaters int
|
|
Scoped int
|
|
Scopes []CatalogueScope
|
|
}
|
|
if json.Unmarshal(s.cache.Payload, &payload) == nil {
|
|
c.GeneratedAt = generated.UnixMilli()
|
|
c.Repeaters, c.Scoped = payload.Repeaters, payload.Scoped
|
|
for _, scope := range payload.Scopes {
|
|
scope.Name = scopestore.FromName(scope.Name).Name
|
|
c.Scopes = append(c.Scopes, scope)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
result = append(result, c)
|
|
}
|
|
i.catalogues.Store(result)
|
|
}
|