CI / changes (push) Successful in 7s
CI / openapi (push) Has been skipped
CI / go (push) Successful in 1m56s
CI / docker-web (deploy/docker/evobgp-web/Dockerfile, , evobgp-web) (push) Has been skipped
CI / docker-web (deploy/docker/evobgp-web/Dockerfile, evobgp-all, evobgp-web-all) (push) Has been skipped
CI / docker-bird (push) Has been skipped
CI / bird2 (push) Successful in 15s
CI / docker-go-prime (push) Successful in 26s
CI / docker-go (deploy/docker/evobgp-agent/Dockerfile, , evobgp-agent) (push) Successful in 1m0s
CI / docker-go (evobgp-all, 1, deploy/docker/gobinary/Dockerfile, , evobgp-all) (push) Successful in 2m15s
CI / docker-go (evobgp-api, 1, deploy/docker/gobinary/Dockerfile, , evobgp-api) (push) Successful in 1m31s
CI / docker-go (evobgp-deploy, 0, deploy/docker/gobinary/Dockerfile, , evobgp-deploy) (push) Successful in 1m32s
CI / docker-go (evobgp-ingest, 0, deploy/docker/gobinary/Dockerfile, , evobgp-ingest) (push) Successful in 1m40s
CI / docker-go (evobgp-node, 0, deploy/docker/gobinary/Dockerfile, , evobgp-node) (push) Successful in 1m23s
CI / docker-go (evobgp-render, 0, deploy/docker/gobinary/Dockerfile, , evobgp-render) (push) Successful in 1m23s
CI / docker-go (evobgp-scheduler, 0, deploy/docker/gobinary/Dockerfile, , evobgp-scheduler) (push) Successful in 1m20s
Modified the collectModulePrefixRows function to accept an optional priorSnapshot parameter, allowing for more efficient data retrieval by skipping unnecessary CDN fetches. Refactored the logic for collecting prefix rows from AS, CDN, and domain sources to utilize dedicated functions, improving code organization and maintainability. Additionally, introduced caching for module prefix snapshots to optimize performance during refresh operations.
124 lines
3.6 KiB
Go
124 lines
3.6 KiB
Go
package pipeline
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"sort"
|
|
"strings"
|
|
|
|
"evobgp/internal/store"
|
|
)
|
|
|
|
// moduleIngestInputHash fingerprints module config and child entries so snapshots invalidate on CRUD.
|
|
func moduleIngestInputHash(st store.Backend, tenantID string, mod *store.Module) (string, error) {
|
|
if st == nil || mod == nil {
|
|
return "", fmt.Errorf("module hash: missing store or module")
|
|
}
|
|
h := sha256.New()
|
|
_, _ = fmt.Fprintf(h, "type=%s\n", strings.TrimSpace(mod.Type))
|
|
_, _ = fmt.Fprintf(h, "enabled=%t\n", mod.Enabled)
|
|
if mod.DefaultCommunityID != nil {
|
|
_, _ = fmt.Fprintf(h, "default_community=%s\n", strings.TrimSpace(*mod.DefaultCommunityID))
|
|
}
|
|
if mod.DohProfileID != nil {
|
|
_, _ = fmt.Fprintf(h, "doh_profile=%s\n", strings.TrimSpace(*mod.DohProfileID))
|
|
if pid := strings.TrimSpace(*mod.DohProfileID); pid != "" {
|
|
if prof, err := st.GetDohProfile(tenantID, pid); err == nil && prof != nil {
|
|
_, _ = fmt.Fprintf(h, "doh_url=%s\n", strings.TrimSpace(prof.URL))
|
|
if prof.TimeoutMs != nil {
|
|
_, _ = fmt.Fprintf(h, "doh_timeout=%d\n", *prof.TimeoutMs)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
switch mod.Type {
|
|
case "IP_RANGES":
|
|
list, err := st.ListIPRangeEntries(tenantID, mod.ID)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
sort.Slice(list, func(i, j int) bool { return list[i].Prefix < list[j].Prefix })
|
|
for _, e := range list {
|
|
comm := ""
|
|
if e.CommunityID != nil {
|
|
comm = *e.CommunityID
|
|
}
|
|
_, _ = fmt.Fprintf(h, "ip=%s|c=%s\n", e.Prefix, comm)
|
|
}
|
|
case "AS_PREFIXES":
|
|
list, err := st.ListASEntries(tenantID, mod.ID)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
sort.Slice(list, func(i, j int) bool { return list[i].ASN < list[j].ASN })
|
|
for _, e := range list {
|
|
comm := ""
|
|
if e.CommunityID != nil {
|
|
comm = *e.CommunityID
|
|
}
|
|
_, _ = fmt.Fprintf(h, "as=%d|c=%s\n", e.ASN, comm)
|
|
}
|
|
case "CDN_CIDRS":
|
|
list, err := st.ListCDNSources(tenantID, mod.ID)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
sort.Slice(list, func(i, j int) bool { return list[i].ID < list[j].ID })
|
|
for _, s := range list {
|
|
comm := ""
|
|
if s.CommunityID != nil {
|
|
comm = *s.CommunityID
|
|
}
|
|
interval := 0
|
|
if s.RefreshIntervalSec != nil {
|
|
interval = *s.RefreshIntervalSec
|
|
}
|
|
_, _ = fmt.Fprintf(h, "cdn=%s|url=%s|kind=%s|path=%s|c=%s|etag=%s|interval=%d\n",
|
|
s.ID, strings.TrimSpace(s.URL), s.SourceKind, strings.TrimSpace(s.PrefixPath), comm,
|
|
strings.TrimSpace(s.Etag), interval)
|
|
}
|
|
case "DOMAINS":
|
|
list, err := st.ListDomainEntries(tenantID, mod.ID)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
sort.Slice(list, func(i, j int) bool { return list[i].FQDN < list[j].FQDN })
|
|
for _, e := range list {
|
|
comm := ""
|
|
if e.CommunityID != nil {
|
|
comm = *e.CommunityID
|
|
}
|
|
_, _ = fmt.Fprintf(h, "dom=%s|c=%s\n", strings.TrimSpace(e.FQDN), comm)
|
|
}
|
|
default:
|
|
_, _ = fmt.Fprintf(h, "unknown_type=%s\n", mod.Type)
|
|
}
|
|
return hex.EncodeToString(h.Sum(nil)), nil
|
|
}
|
|
|
|
func persistModuleSnapshot(st store.Backend, tenantID string, mod *store.Module, rows []store.PrefixRow) error {
|
|
if st == nil || mod == nil {
|
|
return nil
|
|
}
|
|
hash, err := moduleIngestInputHash(st, tenantID, mod)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return st.SetModulePrefixSnapshot(tenantID, mod.ID, hash, rows)
|
|
}
|
|
|
|
func moduleRowsFromSnapshot(st store.Backend, tenantID string, mod *store.Module) ([]store.PrefixRow, bool, error) {
|
|
hash, err := moduleIngestInputHash(st, tenantID, mod)
|
|
if err != nil {
|
|
return nil, false, err
|
|
}
|
|
snap, ok, err := st.GetModulePrefixSnapshot(tenantID, mod.ID)
|
|
if err != nil || !ok || snap == nil || snap.InputHash != hash {
|
|
return nil, false, err
|
|
}
|
|
cp := append([]store.PrefixRow(nil), snap.Prefixes...)
|
|
return cp, true, nil
|
|
}
|