mirror of
https://github.com/MeshCore-Beacon/beacon-server.git
synced 2026-10-23 01:51:27 +00:00
17 files changed
+332
-22
No files matched your search
@@ -48,6 +48,11 @@ type NodeSummary struct {
|
||||
DefaultScope *string `json:"defaultScope,omitempty"` // most recently matched transport scope name e.g. "#bc"
|
||||
KnownNeighborCount int64 `json:"knownNeighborCount"`
|
||||
NeighborIDs []uuid.UUID `json:"neighborIds,omitempty"` // only populated when the list request opts in; see ?neighbors=true
|
||||
// Stale is true when the node hasn't been seen (last_seen) within the configured
|
||||
// staleness window (default 24h; internal/config.ResolvedConfig.NodeStaleThreshold).
|
||||
// Applies to every node type, unlike ClockDriftSeconds/ClockOutOfSync on Node, which
|
||||
// are repeater/room-server only.
|
||||
Stale bool `json:"stale"`
|
||||
}
|
||||
|
||||
// Node is the full node representation including firmware capability flags,
|
||||
|
||||
@@ -44,8 +44,8 @@ func ViewRefreshTask(store *db.Store, interval time.Duration) Task {
|
||||
}
|
||||
}
|
||||
|
||||
// CleanupTask returns a Task that prunes old telemetry and packet rows.
|
||||
func CleanupTask(store *db.Store, telemetryRetention, packetRetention, interval time.Duration) Task {
|
||||
// CleanupTask returns a Task that prunes old telemetry, packet, and node rows.
|
||||
func CleanupTask(store *db.Store, telemetryRetention, packetRetention, nodeDeleteAfter, interval time.Duration) Task {
|
||||
return Task{
|
||||
Name: "cleanup",
|
||||
Interval: interval,
|
||||
@@ -65,6 +65,9 @@ func CleanupTask(store *db.Store, telemetryRetention, packetRetention, interval
|
||||
if err := store.DeleteOldTraceIATAs(ctx, cutoff); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := store.DeleteOldNodes(ctx, time.Now().Add(-nodeDeleteAfter)); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
@@ -48,6 +48,11 @@ type ResolvedConfig struct {
|
||||
// node's ADVERT timestamp, above which the node API reports clockOutOfSync=true for
|
||||
// that node. Only meaningful for repeaters/room servers (nodeType 2/3).
|
||||
ClockDriftThreshold time.Duration
|
||||
|
||||
// NodeStaleThreshold and NodeDeleteAfter mirror ClockDriftThreshold's "0 means unset,
|
||||
// resolve to a default" pattern -- see NodesConfig.
|
||||
NodeStaleThreshold time.Duration
|
||||
NodeDeleteAfter time.Duration
|
||||
}
|
||||
|
||||
// PresenceConfig controls coalescing of presence bookkeeping writes
|
||||
@@ -178,6 +183,13 @@ type NodesConfig struct {
|
||||
// repeater/room server's ADVERT timestamp, above which the node API reports
|
||||
// clockOutOfSync=true for that node. Defaults to 5m if not set.
|
||||
ClockDriftThreshold duration `yaml:"clock_drift_threshold"`
|
||||
// StaleThreshold is how long since a node's last_seen before the node API reports
|
||||
// stale=true for it. Defaults to 24h if not set.
|
||||
StaleThreshold duration `yaml:"stale_threshold"`
|
||||
// DeleteAfter is how long since a node's last_seen before the cleanup job deletes the
|
||||
// node entirely. Defaults to the same 30-day default as packets.retention if not set --
|
||||
// independently configurable from it, just the same starting point.
|
||||
DeleteAfter duration `yaml:"delete_after"`
|
||||
}
|
||||
|
||||
// duration is a wrapper around time.Duration that supports YAML unmarshalling
|
||||
@@ -299,6 +311,8 @@ func Resolve(cfg *Config) ResolvedConfig {
|
||||
PresencePacketTTL: cfg.Presence.PacketTTL.Duration,
|
||||
|
||||
ClockDriftThreshold: cfg.Nodes.ClockDriftThreshold.Duration,
|
||||
NodeStaleThreshold: cfg.Nodes.StaleThreshold.Duration,
|
||||
NodeDeleteAfter: cfg.Nodes.DeleteAfter.Duration,
|
||||
}
|
||||
if r.TelemetryResolution == 0 {
|
||||
r.TelemetryResolution = time.Hour
|
||||
@@ -330,14 +344,23 @@ func Resolve(cfg *Config) ResolvedConfig {
|
||||
if r.ClockDriftThreshold == 0 {
|
||||
r.ClockDriftThreshold = 5 * time.Minute
|
||||
}
|
||||
if r.NodeStaleThreshold == 0 {
|
||||
r.NodeStaleThreshold = 24 * time.Hour
|
||||
}
|
||||
if r.NodeDeleteAfter == 0 {
|
||||
// Same default as packets.retention (30 days) -- independently configurable, just
|
||||
// the same starting point, not tied to whatever PacketRetention resolves to.
|
||||
r.NodeDeleteAfter = 30 * 24 * time.Hour
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
func (r ResolvedConfig) String() string {
|
||||
return fmt.Sprintf(
|
||||
"telemetryResolution=%s telemetryRetention=%s packetRetention=%s maxConnsPerIP=%d viewRefresh=%s reconfirm=%s cleanup=%s presenceFlush=%s presencePacketTTL=%s clockDriftThreshold=%s",
|
||||
"telemetryResolution=%s telemetryRetention=%s packetRetention=%s maxConnsPerIP=%d viewRefresh=%s reconfirm=%s cleanup=%s presenceFlush=%s presencePacketTTL=%s clockDriftThreshold=%s nodeStaleThreshold=%s nodeDeleteAfter=%s",
|
||||
r.TelemetryResolution, r.TelemetryRetention, r.PacketRetention,
|
||||
r.MaxConnsPerIP, r.ViewRefreshInterval, r.ReconfirmInterval, r.CleanupInterval,
|
||||
r.PresenceFlushInterval, r.PresencePacketTTL, r.ClockDriftThreshold,
|
||||
r.NodeStaleThreshold, r.NodeDeleteAfter,
|
||||
)
|
||||
}
|
||||
@@ -98,6 +98,12 @@ func TestResolve_Defaults(t *testing.T) {
|
||||
if r.ClockDriftThreshold != 5*time.Minute {
|
||||
t.Errorf("expected ClockDriftThreshold 5m, got %v", r.ClockDriftThreshold)
|
||||
}
|
||||
if r.NodeStaleThreshold != 24*time.Hour {
|
||||
t.Errorf("expected NodeStaleThreshold 24h, got %v", r.NodeStaleThreshold)
|
||||
}
|
||||
if r.NodeDeleteAfter != 30*24*time.Hour {
|
||||
t.Errorf("expected NodeDeleteAfter 720h (same default as PacketRetention), got %v", r.NodeDeleteAfter)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResolve_ExplicitValues(t *testing.T) {
|
||||
|
||||
Reference in new issue
Block a user