From 01158aee5510ecdf4d4de754039c829f85401f0a Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Mon, 20 Apr 2026 16:43:38 -0600 Subject: [PATCH] revert: inline geoip sync instead of IPCheck.Sync method Keep fetch+open+swap inline at both call sites (initial load in main, background tick in the serve branch). No helper. --- cmd/check-ip/main.go | 60 +++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 31 deletions(-) diff --git a/cmd/check-ip/main.go b/cmd/check-ip/main.go index 9482590..6c5dfa3 100644 --- a/cmd/check-ip/main.go +++ b/cmd/check-ip/main.go @@ -42,31 +42,9 @@ type IPCheck struct { // the .tar.gz archives must already exist in /maxmind/. GeoIPBasicAuth string - inbound *dataset.View[ipcohort.Cohort] - outbound *dataset.View[ipcohort.Cohort] - geoFetcher dataset.Fetcher - geo atomic.Pointer[geoip.Databases] -} - -// Sync fetches the GeoIP archives (via httpcache when basic auth is set, -// otherwise by polling their mtime) and, when the fetcher reports a change, -// re-opens the databases and atomically swaps the active snapshot. -func (c *IPCheck) Sync() (bool, error) { - updated, err := c.geoFetcher.Fetch() - if err != nil { - return false, err - } - if c.geo.Load() != nil && !updated { - return false, nil - } - db, err := geoip.Open(filepath.Join(c.CacheDir, "maxmind")) - if err != nil { - return false, err - } - if old := c.geo.Swap(db); old != nil { - _ = old.Close() - } - return true, nil + inbound *dataset.View[ipcohort.Cohort] + outbound *dataset.View[ipcohort.Cohort] + geo atomic.Pointer[geoip.Databases] } func main() { @@ -157,8 +135,10 @@ func main() { // httpcache conditional GETs. Without them, poll the existing tar.gz // files in maxmindDir. geoip.Open extracts in-memory — no .mmdb files // are written to disk. - cityTarPath := filepath.Join(cfg.CacheDir, "maxmind", "GeoLite2-City.tar.gz") - asnTarPath := filepath.Join(cfg.CacheDir, "maxmind", "GeoLite2-ASN.tar.gz") + maxmindDir := filepath.Join(cfg.CacheDir, "maxmind") + cityTarPath := filepath.Join(maxmindDir, "GeoLite2-City.tar.gz") + asnTarPath := filepath.Join(maxmindDir, "GeoLite2-ASN.tar.gz") + var geoFetcher dataset.Fetcher if cfg.GeoIPBasicAuth != "" { city := &httpcache.Cacher{ URL: geoip.DownloadBase + "/GeoLite2-City/download?suffix=tar.gz", @@ -174,7 +154,7 @@ func main() { AuthHeader: "Authorization", AuthValue: cfg.GeoIPBasicAuth, } - cfg.geoFetcher = dataset.FetcherFunc(func() (bool, error) { + geoFetcher = dataset.FetcherFunc(func() (bool, error) { cityUpdated, err := city.Fetch() if err != nil { return false, fmt.Errorf("fetch GeoLite2-City: %w", err) @@ -186,11 +166,16 @@ func main() { return cityUpdated || asnUpdated, nil }) } else { - cfg.geoFetcher = dataset.PollFiles(cityTarPath, asnTarPath) + geoFetcher = dataset.PollFiles(cityTarPath, asnTarPath) } - if _, err := cfg.Sync(); err != nil { + if _, err := geoFetcher.Fetch(); err != nil { log.Fatalf("geoip: %v", err) } + geoDB, err := geoip.Open(maxmindDir) + if err != nil { + log.Fatalf("geoip: %v", err) + } + cfg.geo.Store(geoDB) defer func() { _ = cfg.geo.Load().Close() }() for _, ip := range ips { @@ -213,8 +198,21 @@ func main() { case <-ctx.Done(): return case <-t.C: - if _, err := cfg.Sync(); err != nil { + updated, err := geoFetcher.Fetch() + if err != nil { log.Printf("geoip refresh: %v", err) + continue + } + if !updated { + continue + } + db, err := geoip.Open(maxmindDir) + if err != nil { + log.Printf("geoip refresh: %v", err) + continue + } + if old := cfg.geo.Swap(db); old != nil { + _ = old.Close() } } }