Store a new row's earliest timestamp as first_seen (closes #112)
check / check (push) Canceled after 0s
check / check (push) Canceled after 0s
Each handler took the latest time per key in a batch and inserted it as a new row's first_seen, so a key updated twice in one batch, seconds apart, was stored first seen at the later time, and the IP lookup could answer with a prefix first_seen after the route's last_seen. The prefix handler now keeps the earliest time of all of the batch's updates for each prefix. The AS, peer and peering handlers keep the earliest and the latest time per key in database.SeenTimes, and GetOrCreateASNBatch, UpdatePeerBatch and RecordPeering store a new row first seen at the earliest and last seen at the latest. A stored row still has only its last_seen set, to the latest. Model: opus-5-5
This commit was merged in pull request #137.
This commit is contained in:
@@ -42,10 +42,11 @@ type PeeringHandler struct {
|
||||
db database.Store
|
||||
logger *logger.Logger
|
||||
|
||||
// In-memory AS path tracking
|
||||
// In-memory AS path tracking: each path, JSON-encoded, with the earliest
|
||||
// and the latest time an update carried it.
|
||||
mu sync.Mutex
|
||||
asPaths map[string]time.Time // key is JSON-encoded AS path
|
||||
droppedPaths int // paths dropped because the map was full
|
||||
asPaths map[string]database.SeenTimes
|
||||
droppedPaths int // paths dropped because the map was full
|
||||
// writing is how many paths processPeerings took from asPaths and has
|
||||
// not finished writing the peerings of.
|
||||
writing int
|
||||
@@ -64,7 +65,7 @@ func NewPeeringHandler(db database.Store, logger *logger.Logger) *PeeringHandler
|
||||
h := &PeeringHandler{
|
||||
db: db,
|
||||
logger: logger,
|
||||
asPaths: make(map[string]time.Time),
|
||||
asPaths: make(map[string]database.SeenTimes),
|
||||
stopCh: make(chan context.Context, 1),
|
||||
done: make(chan struct{}),
|
||||
}
|
||||
@@ -118,16 +119,18 @@ func (h *PeeringHandler) HandleMessage(msg *ristypes.RISMessage) {
|
||||
key := string(pathJSON)
|
||||
|
||||
h.mu.Lock()
|
||||
if _, exists := h.asPaths[key]; exists {
|
||||
// Already tracked: refresh its timestamp.
|
||||
h.asPaths[key] = timestamp
|
||||
} else if len(h.asPaths) >= maxTrackedPaths {
|
||||
defer h.mu.Unlock()
|
||||
|
||||
seen, exists := h.asPaths[key]
|
||||
if !exists && len(h.asPaths) >= maxTrackedPaths {
|
||||
// Map is full; drop this new path and count it.
|
||||
h.droppedPaths++
|
||||
} else {
|
||||
h.asPaths[key] = timestamp
|
||||
|
||||
return
|
||||
}
|
||||
h.mu.Unlock()
|
||||
|
||||
seen.Add(timestamp)
|
||||
h.asPaths[key] = seen
|
||||
}
|
||||
|
||||
// ProcessPeeringsNow triggers immediate processing of all accumulated AS
|
||||
@@ -190,7 +193,7 @@ func (h *PeeringHandler) processPeerings() {
|
||||
// released, so the map never grows past a single interval's traffic.
|
||||
h.mu.Lock()
|
||||
paths := h.asPaths
|
||||
h.asPaths = make(map[string]time.Time)
|
||||
h.asPaths = make(map[string]database.SeenTimes)
|
||||
h.writing = len(paths)
|
||||
dropped := h.droppedPaths
|
||||
h.mu.Unlock()
|
||||
@@ -204,9 +207,13 @@ func (h *PeeringHandler) processPeerings() {
|
||||
low, high int
|
||||
}
|
||||
|
||||
peerings := make(map[peeringKey]time.Time)
|
||||
// The earliest and the latest time an update carried each peering. Several
|
||||
// paths, each carried at several times, can hold a peering, so a new
|
||||
// peering is stored first seen at the earliest of them and last seen at the
|
||||
// latest.
|
||||
peerings := make(map[peeringKey]database.SeenTimes)
|
||||
|
||||
for pathJSON, timestamp := range paths {
|
||||
for pathJSON, pathSeen := range paths {
|
||||
var path []int
|
||||
|
||||
err := json.Unmarshal([]byte(pathJSON), &path)
|
||||
@@ -233,10 +240,11 @@ func (h *PeeringHandler) processPeerings() {
|
||||
}
|
||||
|
||||
key := peeringKey{low: low, high: high}
|
||||
// Update timestamp if this is newer
|
||||
if existing, ok := peerings[key]; !ok || timestamp.After(existing) {
|
||||
peerings[key] = timestamp
|
||||
}
|
||||
|
||||
seen := peerings[key]
|
||||
seen.Add(pathSeen.First)
|
||||
seen.Add(pathSeen.Last)
|
||||
peerings[key] = seen
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,8 +252,8 @@ func (h *PeeringHandler) processPeerings() {
|
||||
start := time.Now()
|
||||
successCount := 0
|
||||
|
||||
for key, ts := range peerings {
|
||||
err := h.db.RecordPeering(key.low, key.high, ts)
|
||||
for key, seen := range peerings {
|
||||
err := h.db.RecordPeering(key.low, key.high, seen)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to record peering",
|
||||
"as_a", key.low,
|
||||
|
||||
Reference in New Issue
Block a user