Replace live_routes database table with in-memory routing table
- Remove live_routes table from SQL schema and all related indexes - Create new internal/routingtable package with thread-safe RoutingTable - Implement RouteKey-based indexing with secondary indexes for efficient lookups - Add RoutingTableHandler to manage in-memory routes separately from database - Update DatabaseHandler to only handle persistent database operations - Wire up RoutingTable through fx dependency injection - Update server to get live route count from routing table instead of database - Remove LiveRoutes field from database.Stats struct - Update tests to work with new architecture
This commit is contained in:
@@ -340,75 +340,6 @@ func (d *Database) RecordPeering(fromASNID, toASNID string, timestamp time.Time)
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpdateLiveRoute updates the live routing table for an announcement
|
||||
func (d *Database) UpdateLiveRoute(
|
||||
prefixID, originASNID uuid.UUID,
|
||||
peerASN int,
|
||||
nextHop string,
|
||||
timestamp time.Time,
|
||||
) error {
|
||||
// Use SQLite's UPSERT capability to avoid the SELECT+UPDATE/INSERT pattern
|
||||
// This reduces the number of queries and improves performance
|
||||
// Note: We removed the WHERE clause from ON CONFLICT UPDATE because
|
||||
// if we're updating, we want to update regardless of withdrawn_at status
|
||||
err := d.exec(`
|
||||
INSERT INTO live_routes (id, prefix_id, origin_asn_id, peer_asn, next_hop, announced_at, withdrawn_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, NULL)
|
||||
ON CONFLICT(prefix_id, origin_asn_id, peer_asn) DO UPDATE SET
|
||||
next_hop = excluded.next_hop,
|
||||
announced_at = excluded.announced_at,
|
||||
withdrawn_at = NULL`,
|
||||
generateUUID().String(), prefixID.String(), originASNID.String(),
|
||||
peerASN, nextHop, timestamp)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// WithdrawLiveRoute marks a route as withdrawn in the live routing table
|
||||
func (d *Database) WithdrawLiveRoute(prefixID uuid.UUID, peerASN int, timestamp time.Time) error {
|
||||
err := d.exec(`
|
||||
UPDATE live_routes
|
||||
SET withdrawn_at = ?
|
||||
WHERE prefix_id = ? AND peer_asn = ? AND withdrawn_at IS NULL`,
|
||||
timestamp, prefixID.String(), peerASN)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// GetActiveLiveRoutes returns all currently active routes (not withdrawn)
|
||||
func (d *Database) GetActiveLiveRoutes() ([]LiveRoute, error) {
|
||||
rows, err := d.query(`
|
||||
SELECT id, prefix_id, origin_asn_id, peer_asn, next_hop, announced_at
|
||||
FROM live_routes
|
||||
WHERE withdrawn_at IS NULL
|
||||
ORDER BY announced_at DESC`)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
_ = rows.Close()
|
||||
}()
|
||||
|
||||
var routes []LiveRoute
|
||||
for rows.Next() {
|
||||
var route LiveRoute
|
||||
var idStr, prefixIDStr, originASNIDStr string
|
||||
err := rows.Scan(&idStr, &prefixIDStr, &originASNIDStr,
|
||||
&route.PeerASN, &route.NextHop, &route.AnnouncedAt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
route.ID, _ = uuid.Parse(idStr)
|
||||
route.PrefixID, _ = uuid.Parse(prefixIDStr)
|
||||
route.OriginASNID, _ = uuid.Parse(originASNIDStr)
|
||||
|
||||
routes = append(routes, route)
|
||||
}
|
||||
|
||||
return routes, rows.Err()
|
||||
}
|
||||
|
||||
// UpdatePeer updates or creates a BGP peer record
|
||||
func (d *Database) UpdatePeer(peerIP string, peerASN int, messageType string, timestamp time.Time) error {
|
||||
tx, err := d.beginTx()
|
||||
@@ -495,13 +426,6 @@ func (d *Database) GetStats() (Stats, error) {
|
||||
return stats, err
|
||||
}
|
||||
|
||||
// Count live routes
|
||||
d.logger.Info("Counting live routes")
|
||||
err = d.queryRow("SELECT COUNT(*) FROM live_routes WHERE withdrawn_at IS NULL").Scan(&stats.LiveRoutes)
|
||||
if err != nil {
|
||||
return stats, err
|
||||
}
|
||||
|
||||
d.logger.Info("Stats collection complete")
|
||||
|
||||
return stats, nil
|
||||
|
||||
Reference in New Issue
Block a user