Re-vendor the shared files from sneak/prompts at 0653579 (closes #52)
check / check (push) Canceled after 0s
check / check (push) Canceled after 0s
Takes .golangci.yml, .dockerignore, .gitignore, .editorconfig, the workflow and REPO_POLICIES.md from sneak/prompts 0653579, with this repository's own entries after the shared content. Lint (golangci-lint v2.14.0) and test are Dockerfile phases that script/lint and script/test build alone with a new CACHEBUST value, keeping Go's and golangci-lint's caches; the image build depends on both. make fmt and make fmt-check also format the markdown with prettier, pinned in yarn.lock. The agent guidance moves to AGENTS.md. The Go code is fixed for what the new configuration finds, and the AS and prefix detail reads now return the rows' error after their loops. Model: opus-5-5
This commit was merged in pull request #85.
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
package routewatch
|
||||
|
||||
// peerhandler.go provides batched peer tracking functionality for BGP route monitoring.
|
||||
// It tracks BGP peers from incoming UPDATE messages and maintains peer state in the database.
|
||||
// peerhandler.go provides batched peer tracking functionality for BGP route
|
||||
// monitoring. It tracks BGP peers from incoming UPDATE messages and maintains
|
||||
// peer state in the database.
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
@@ -44,9 +45,11 @@ type PeerHandler struct {
|
||||
// Batching. mu guards peerBatch only: the flush goroutine takes the batch
|
||||
// under mu and writes it after releasing mu, so HandleMessage waits for
|
||||
// a database write only while peerBatch is at peerBatchMaxSize.
|
||||
mu sync.Mutex
|
||||
peerBatch []peerUpdate
|
||||
batchTaken sync.Cond // signalled when the flush goroutine takes peerBatch; its L is &mu
|
||||
mu sync.Mutex
|
||||
peerBatch []peerUpdate
|
||||
// batchTaken is signalled when the flush goroutine takes peerBatch; its L
|
||||
// is &mu.
|
||||
batchTaken sync.Cond
|
||||
batchFullCh chan struct{} // wakes the flush goroutine when peerBatch is full
|
||||
lastFlush time.Time // used only by the flush goroutine
|
||||
stopCh chan struct{}
|
||||
@@ -104,8 +107,10 @@ func (h *PeerHandler) QueueCapacity() int {
|
||||
func (h *PeerHandler) HandleMessage(msg *ristypes.RISMessage) {
|
||||
// Parse peer ASN from string
|
||||
peerASN := 0
|
||||
|
||||
if msg.PeerASN != "" {
|
||||
if asn, err := strconv.Atoi(msg.PeerASN); err == nil {
|
||||
asn, err := strconv.Atoi(msg.PeerASN)
|
||||
if err == nil {
|
||||
peerASN = asn
|
||||
}
|
||||
}
|
||||
@@ -139,10 +144,17 @@ func (h *PeerHandler) HandleMessage(msg *ristypes.RISMessage) {
|
||||
}
|
||||
}
|
||||
|
||||
// Stop gracefully stops the handler and flushes remaining batches
|
||||
func (h *PeerHandler) Stop() {
|
||||
close(h.stopCh)
|
||||
h.wg.Wait()
|
||||
}
|
||||
|
||||
// flushLoop runs in a goroutine, the only one that writes the batch: it
|
||||
// flushes when the batch is full, periodically, and once more on Stop.
|
||||
func (h *PeerHandler) flushLoop() {
|
||||
defer h.wg.Done()
|
||||
|
||||
ticker := time.NewTicker(peerBatchTimeout)
|
||||
defer ticker.Stop()
|
||||
|
||||
@@ -172,6 +184,7 @@ func (h *PeerHandler) takeBatch() []peerUpdate {
|
||||
if len(h.peerBatch) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
batch := h.peerBatch
|
||||
h.peerBatch = make([]peerUpdate, 0, peerBatchSize)
|
||||
h.batchTaken.Broadcast()
|
||||
@@ -190,7 +203,8 @@ func (h *PeerHandler) flushBatch() {
|
||||
// Deduplicate by peer IP, keeping the latest update for each peer
|
||||
peerMap := make(map[string]peerUpdate)
|
||||
for _, update := range batch {
|
||||
if existing, ok := peerMap[update.peerIP]; !ok || update.timestamp.After(existing.timestamp) {
|
||||
existing, ok := peerMap[update.peerIP]
|
||||
if !ok || update.timestamp.After(existing.timestamp) {
|
||||
peerMap[update.peerIP] = update
|
||||
}
|
||||
}
|
||||
@@ -207,15 +221,11 @@ func (h *PeerHandler) flushBatch() {
|
||||
}
|
||||
|
||||
// Process all peers in a single batch transaction
|
||||
if err := h.db.UpdatePeerBatch(dbPeerMap); err != nil {
|
||||
h.logger.Error("Failed to process peer batch", "error", err, "count", len(dbPeerMap))
|
||||
err := h.db.UpdatePeerBatch(dbPeerMap)
|
||||
if err != nil {
|
||||
h.logger.Error("Failed to process peer batch",
|
||||
"error", err, "count", len(dbPeerMap))
|
||||
}
|
||||
|
||||
h.lastFlush = time.Now()
|
||||
}
|
||||
|
||||
// Stop gracefully stops the handler and flushes remaining batches
|
||||
func (h *PeerHandler) Stop() {
|
||||
close(h.stopCh)
|
||||
h.wg.Wait()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user