Files
beacon-server/internal/meshmapper/catalogues.go
n30nex a9b8c60a97 feat: stage current preview on dev for dev1 evaluation
Port the qualified server preview at 84ac3c8781 onto
org dev c7209b7043. Preserve upstream changes and
branch policies; keep the independent private Collector service separate.

Preview-Version: 2.2.0-n30nex.1
Preview-Revision: 84ac3c8781
2026-10-04 16:31:48 -04:00

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)
}