- Убран latestCDNRowsBySource; expanded BIRD preview генерируется on-demand - Batch AS meta updates; миграция perf-индексов 000012 - VirtualPrefixList для preview префиксов; метрики pipeline refresh - PolitePause для RIPEstat после cache miss Co-authored-by: Cursor <cursoragent@cursor.com>
60 lines
1.5 KiB
Go
60 lines
1.5 KiB
Go
package pipeline
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"net/netip"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"evobgp/internal/asnresolve"
|
|
"evobgp/internal/store"
|
|
)
|
|
|
|
func asnCacheTTL() time.Duration {
|
|
sec := 1800
|
|
if s := strings.TrimSpace(os.Getenv("EVOBGP_ASN_CACHE_TTL_SEC")); s != "" {
|
|
if v, err := strconv.Atoi(s); err == nil && v > 0 {
|
|
sec = v
|
|
}
|
|
}
|
|
return time.Duration(sec) * time.Second
|
|
}
|
|
|
|
// resolveASNForEntry fetches prefixes and holder with shared TTL cache (asn_prefix_cache).
|
|
func resolveASNForEntry(ctx context.Context, st store.Backend, hc *http.Client, asn int64) ([]netip.Prefix, string, error) {
|
|
ttl := asnCacheTTL()
|
|
if st != nil {
|
|
if ent, ok, err := st.GetASNPrefixCache(asn); err == nil && ok && ent != nil && time.Since(ent.FetchedAt) < ttl {
|
|
out := make([]netip.Prefix, 0, len(ent.Prefixes))
|
|
for _, p := range ent.Prefixes {
|
|
pfx, perr := netip.ParsePrefix(strings.TrimSpace(p))
|
|
if perr != nil {
|
|
continue
|
|
}
|
|
out = append(out, pfx.Masked())
|
|
}
|
|
return out, ent.Holder, nil
|
|
}
|
|
}
|
|
pfxs, err := asnresolve.AnnouncedPrefixes(ctx, hc, asn)
|
|
if err != nil {
|
|
return nil, "", err
|
|
}
|
|
asnresolve.PolitePause()
|
|
holder, _ := asnresolve.ASHolderName(ctx, hc, asn)
|
|
if st != nil {
|
|
strs := make([]string, len(pfxs))
|
|
for i, p := range pfxs {
|
|
strs[i] = p.String()
|
|
}
|
|
if err := st.SetASNPrefixCache(asn, holder, strs); err != nil {
|
|
return nil, "", fmt.Errorf("asn cache AS%d: %w", asn, err)
|
|
}
|
|
}
|
|
return pfxs, holder, nil
|
|
}
|