check / check (push) Successful in 1m3s
The routing table records a row each time a prefix and origin AS gets its first peer (announced) or loses its last (withdrawn), with the time and how many peers carry the prefix just after. The prefix handler writes the rows to a new origin_changes table, apart from routes. Every hour the database maintainer keeps each prefix's rows from the last 72 hours or its newest 500, whichever keeps more. The prefix page lists them newest first, at most 5,000. At most 100,000 rows wait in memory to be written; past that the oldest are dropped and logged. A stop loses the rows past its last write. Model: deepseek-v4-pro (implementation); opus-5-5 (commit message)
92 lines
3.1 KiB
Go
92 lines
3.1 KiB
Go
// Package database provides SQLite storage for BGP routing data: ASNs,
|
|
// prefixes, announcements, peerings, BGP peers and origin changes. Its routes
|
|
// table holds a copy of the whole routing table that internal/routetable
|
|
// keeps in memory.
|
|
package database
|
|
|
|
import (
|
|
"context"
|
|
"net/netip"
|
|
"time"
|
|
|
|
"git.eeqj.de/sneak/routewatch/internal/routetable"
|
|
)
|
|
|
|
// Stats contains database statistics: counts of ASNs, prefixes, peerings and
|
|
// peers, and the file size.
|
|
type Stats struct {
|
|
ASNs int
|
|
Prefixes int
|
|
IPv4Prefixes int
|
|
IPv6Prefixes int
|
|
Peerings int
|
|
Peers int
|
|
FileSizeBytes int64
|
|
}
|
|
|
|
// Store defines the interface for database operations. It provides methods for
|
|
// managing ASNs, prefixes, announcements, peerings, BGP peers, and the copy of
|
|
// the routing table. Implementations must be safe for concurrent use.
|
|
//
|
|
//nolint:interfacebloat // the one seam handlers and tests depend on
|
|
type Store interface {
|
|
// ASN operations
|
|
GetOrCreateASN(number int, timestamp time.Time) (*ASN, error)
|
|
GetOrCreateASNBatch(asns map[int]SeenTimes) error
|
|
|
|
// Prefix operations
|
|
GetOrCreatePrefix(prefix string, timestamp time.Time) (*Prefix, error)
|
|
UpdatePrefixesBatch(prefixes map[string]time.Time) error
|
|
|
|
// Announcement operations
|
|
RecordAnnouncement(announcement *Announcement) error
|
|
|
|
// Peering operations
|
|
RecordPeering(asA, asB int, seen SeenTimes) error
|
|
|
|
// Statistics
|
|
GetStats() (Stats, error)
|
|
GetStatsContext(ctx context.Context) (Stats, error)
|
|
|
|
// Peer operations
|
|
UpdatePeer(peerIP string, peerASN int, messageType string, timestamp time.Time) error
|
|
UpdatePeerBatch(peers map[string]PeerUpdate) error
|
|
|
|
// Routing table operations: the database's copy of the table in memory
|
|
WriteRouteChanges(changes []routetable.Change, newPeers map[string]uint) error
|
|
ReadRouteTable(ctx context.Context) (*routetable.Table, error)
|
|
|
|
// Origin change operations: the prefix and origin AS pairs' first and
|
|
// last peers, as the routing table records them.
|
|
WriteOriginChanges(changes []routetable.OriginChange) error
|
|
GetOriginChanges(
|
|
ctx context.Context, prefix netip.Prefix, limit int,
|
|
) ([]routetable.OriginChange, error)
|
|
PruneOriginChanges(ctx context.Context) error
|
|
|
|
// ASN WHOIS operations
|
|
GetNextStaleASN(ctx context.Context, staleThreshold time.Duration) (int, error)
|
|
UpdateASNWHOIS(ctx context.Context, update *ASNWHOISUpdate) error
|
|
GetWHOISStats(ctx context.Context, staleThreshold time.Duration) (*WHOISStats, error)
|
|
|
|
// AS and prefix detail operations
|
|
GetAS(ctx context.Context, asn int) (*ASN, bool, error)
|
|
GetLastSeenASes(ctx context.Context) (*ASN, *ASN, error)
|
|
GetASWHOIS(ctx context.Context, asn int) (*ASN, error)
|
|
GetPrefixFirstSeen(ctx context.Context, prefix netip.Prefix) (time.Time, error)
|
|
GetASPeers(asn int) ([]ASPeer, error)
|
|
GetASPeersContext(ctx context.Context, asn int) ([]ASPeer, error)
|
|
|
|
// Lifecycle
|
|
Close() error
|
|
|
|
// Maintenance operations
|
|
Vacuum(ctx context.Context) error
|
|
Analyze(ctx context.Context) error
|
|
Checkpoint(ctx context.Context) error
|
|
Ping(ctx context.Context) error
|
|
}
|
|
|
|
// Ensure Database implements Store
|
|
var _ Store = (*Database)(nil)
|