Files
Denozordec dc803bcb34
quality / commitlint (push) Skipped
quality / changes (push) Successful in 9s
quality / docker-check (push) Skipped
quality / openapi (push) Successful in 46s
quality / web (push) Successful in 1m16s
quality / go (push) Successful in 2m42s
quality / bird2 (push) Successful in 16s
CD / quality (push) Successful in 5m19s
CD / publish (push) Successful in 7m19s
refactor(web): remove deprecated dashboard components and enhance KPI grid
- Deleted unused components: `DashboardActivityTimeline`, `DashboardFramePanel`, `DashboardModulesGrid`, `DashboardRecentJobsGrid`, and `DashboardRecentRevisionsGrid` to streamline the dashboard.
- Updated `DashboardKpiGrid` to improve KPI display logic, including progress indicators and enhanced badge functionality.
- Refactored `DashboardNetworkHealth` to provide better status representation based on loading states and network conditions.
- Introduced new properties for KPI cards to support progress tracking and improved visual feedback.

This cleanup aims to enhance performance and maintainability of the dashboard while providing a better user experience.
2026-08-31 10:15:59 +07:00

149 lines
4.2 KiB
Go

package pipeline
import (
"context"
"fmt"
"net/http"
"net/netip"
"strings"
"sync"
"time"
"evobgp/internal/store"
"github.com/miekg/dns"
)
func loadModuleDohProfiles(st store.Backend, tenantID string, mod *store.Module) ([]*store.DohProfile, string, error) {
if mod == nil {
return nil, store.DohPolicyPrimaryOnly, nil
}
policy := store.NormalizeDohResolverPolicy(mod.DohResolverPolicy)
var profiles []*store.DohProfile
for _, id := range mod.EffectiveDohProfileIDs() {
prof, err := st.GetDohProfile(tenantID, id)
if err != nil {
return nil, "", fmt.Errorf("get doh profile %s: %w", id, err)
}
profiles = append(profiles, prof)
}
return profiles, policy, nil
}
func resolveDomainIPsWithPolicy(ctx context.Context, hc *http.Client, profiles []*store.DohProfile, policy, fqdn string) ([]netip.Addr, error) {
policy = store.NormalizeDohResolverPolicy(policy)
if len(profiles) == 0 {
return resolveDomainIPs(ctx, hc, nil, fqdn)
}
if len(profiles) == 1 {
return resolveDomainIPs(ctx, hc, profiles[0], fqdn)
}
switch policy {
case store.DohPolicyUnion:
return resolveDomainIPsUnion(ctx, hc, profiles, fqdn)
case store.DohPolicyFailover:
return resolveDomainIPsFailover(ctx, hc, profiles, fqdn)
default:
return resolveDomainIPs(ctx, hc, profiles[0], fqdn)
}
}
func resolveDomainIPsUnion(ctx context.Context, hc *http.Client, profiles []*store.DohProfile, fqdn string) ([]netip.Addr, error) {
var merged []netip.Addr
var errs []error
for _, prof := range profiles {
if prof == nil {
continue
}
ips, err := resolveDomainIPsNoSystemFallback(ctx, hc, prof, fqdn)
if err != nil {
errs = append(errs, fmt.Errorf("%s: %w", strings.TrimSpace(prof.URL), err))
continue
}
merged = append(merged, ips...)
}
merged = uniqAddrs(merged)
if len(merged) > 0 {
return merged, nil
}
if len(errs) > 0 {
return nil, fmt.Errorf("doh union failed: %v", errs)
}
return nil, nil
}
func resolveDomainIPsFailover(ctx context.Context, hc *http.Client, profiles []*store.DohProfile, fqdn string) ([]netip.Addr, error) {
var lastErr error
for _, prof := range profiles {
if prof == nil {
continue
}
ips, err := resolveDomainIPsNoSystemFallback(ctx, hc, prof, fqdn)
if err != nil {
lastErr = err
continue
}
if len(ips) > 0 {
return ips, nil
}
}
if lastErr != nil {
return nil, lastErr
}
return resolveDomainIPs(ctx, hc, nil, fqdn)
}
// resolveDomainIPsNoSystemFallback queries one DoH profile without falling back to OS resolver.
func resolveDomainIPsNoSystemFallback(ctx context.Context, hc *http.Client, profile *store.DohProfile, fqdn string) ([]netip.Addr, error) {
host := strings.TrimSpace(strings.TrimSuffix(fqdn, "."))
if host == "" {
return nil, nil
}
if profile == nil || strings.TrimSpace(profile.URL) == "" {
return nil, fmt.Errorf("empty doh profile")
}
timeout := dohProfileTimeout(profile)
dctx, cancel := context.WithTimeout(ctx, timeout)
defer cancel()
baseURL := strings.TrimSpace(profile.URL)
v4, v6, err4, err6 := resolveDOHMessagePair(dctx, hc, baseURL, host)
if err4 != nil {
v4, err4 = resolveDomainWithDOHJSON(dctx, hc, baseURL, host, "A")
}
if err6 != nil {
v6, err6 = resolveDomainWithDOHJSON(dctx, hc, baseURL, host, "AAAA")
}
if err4 != nil && err6 != nil {
return nil, fmt.Errorf("doh failed for A and AAAA: %v; %v", err4, err6)
}
return uniqAddrs(append(v4, v6...)), nil
}
// resolveDOHMessagePair issues RFC8484 dns-message A and AAAA queries concurrently
// and waits for both (fallbacks are handled by the caller).
func resolveDOHMessagePair(ctx context.Context, hc *http.Client, baseURL, host string) (v4, v6 []netip.Addr, err4, err6 error) {
var wg sync.WaitGroup
wg.Add(2)
go func() {
defer wg.Done()
v4, err4 = resolveDomainWithDOHMessage(ctx, hc, baseURL, host, dns.TypeA)
}()
go func() {
defer wg.Done()
v6, err6 = resolveDomainWithDOHMessage(ctx, hc, baseURL, host, dns.TypeAAAA)
}()
wg.Wait()
return v4, v6, err4, err6
}
func dohProfileTimeout(profile *store.DohProfile) time.Duration {
timeout := 10 * time.Second
if profile != nil && profile.TimeoutMs != nil && *profile.TimeoutMs > 0 {
timeout = time.Duration(*profile.TimeoutMs) * time.Millisecond
}
return timeout
}