refactor(geoip): cache tarballs as <edition>_LATEST.tar.gz

Adds geoip.TarGzName(edition) as the single source of truth for the
cache filename. The _LATEST suffix signals that the file is whatever
MaxMind served most recently (versus the dated Content-Disposition
name) and keeps httpcache's ETag sidecar tied to a stable path across
releases.
This commit is contained in:
AJ ONeal 2026-04-20 17:13:41 -06:00
parent 5fc032dc56
commit e594f2503c
No known key found for this signature in database
5 changed files with 16 additions and 8 deletions

View File

@ -155,13 +155,13 @@ func main() {
geoSet := dataset.NewSet( geoSet := dataset.NewSet(
&httpcache.Cacher{ &httpcache.Cacher{
URL: geoip.DownloadBase + "/GeoLite2-City/download?suffix=tar.gz", URL: geoip.DownloadBase + "/GeoLite2-City/download?suffix=tar.gz",
Path: filepath.Join(maxmindDir, "GeoLite2-City.tar.gz"), Path: filepath.Join(maxmindDir, geoip.TarGzName(geoip.CityEdition)),
MaxAge: 3 * 24 * time.Hour, MaxAge: 3 * 24 * time.Hour,
Header: authHeader, Header: authHeader,
}, },
&httpcache.Cacher{ &httpcache.Cacher{
URL: geoip.DownloadBase + "/GeoLite2-ASN/download?suffix=tar.gz", URL: geoip.DownloadBase + "/GeoLite2-ASN/download?suffix=tar.gz",
Path: filepath.Join(maxmindDir, "GeoLite2-ASN.tar.gz"), Path: filepath.Join(maxmindDir, geoip.TarGzName(geoip.ASNEdition)),
MaxAge: 3 * 24 * time.Hour, MaxAge: 3 * 24 * time.Hour,
Header: authHeader, Header: authHeader,
}, },

View File

@ -51,7 +51,7 @@ func main() {
exitCode := 0 exitCode := 0
for _, edition := range cfg.EditionIDs { for _, edition := range cfg.EditionIDs {
path := filepath.Join(outDir, edition+".tar.gz") path := filepath.Join(outDir, geoip.TarGzName(edition))
cacher := &httpcache.Cacher{ cacher := &httpcache.Cacher{
URL: geoip.DownloadBase + "/" + edition + "/download?suffix=tar.gz", URL: geoip.DownloadBase + "/" + edition + "/download?suffix=tar.gz",
Path: path, Path: path,

View File

@ -20,15 +20,15 @@ type Databases struct {
ASN *geoip2.Reader ASN *geoip2.Reader
} }
// Open reads <dir>/GeoLite2-City.tar.gz and <dir>/GeoLite2-ASN.tar.gz, // Open reads <dir>/<edition>_LATEST.tar.gz for City and ASN editions,
// extracts the .mmdb entry from each archive in memory, and returns open // extracts the .mmdb entry from each archive in memory, and returns open
// readers. No .mmdb files are written to disk. // readers. No .mmdb files are written to disk.
func Open(dir string) (*Databases, error) { func Open(dir string) (*Databases, error) {
city, err := openMMDBTarGz(filepath.Join(dir, "GeoLite2-City.tar.gz")) city, err := openMMDBTarGz(filepath.Join(dir, TarGzName(CityEdition)))
if err != nil { if err != nil {
return nil, fmt.Errorf("city: %w", err) return nil, fmt.Errorf("city: %w", err)
} }
asn, err := openMMDBTarGz(filepath.Join(dir, "GeoLite2-ASN.tar.gz")) asn, err := openMMDBTarGz(filepath.Join(dir, TarGzName(ASNEdition)))
if err != nil { if err != nil {
_ = city.Close() _ = city.Close()
return nil, fmt.Errorf("asn: %w", err) return nil, fmt.Errorf("asn: %w", err)

View File

@ -15,6 +15,14 @@ const (
DownloadBase = "https://download.maxmind.com/geoip/databases" DownloadBase = "https://download.maxmind.com/geoip/databases"
) )
// TarGzName returns the cache filename for edition's tar.gz archive.
// MaxMind's Content-Disposition names include a release date
// (e.g. GeoLite2-ASN_20260101.tar.gz); we use _LATEST so httpcache's
// ETag sidecar stays tied to a stable path across releases.
func TarGzName(edition string) string {
return edition + "_LATEST.tar.gz"
}
// DefaultConfPaths returns the standard locations where GeoIP.conf is looked // DefaultConfPaths returns the standard locations where GeoIP.conf is looked
// up: ./GeoIP.conf, then ~/.config/maxmind/GeoIP.conf. // up: ./GeoIP.conf, then ~/.config/maxmind/GeoIP.conf.
func DefaultConfPaths() []string { func DefaultConfPaths() []string {

View File

@ -64,7 +64,7 @@ func TestDownload_CityAndASN(t *testing.T) {
td := testdataDir(t) td := testdataDir(t)
for _, edition := range []string{geoip.CityEdition, geoip.ASNEdition} { for _, edition := range []string{geoip.CityEdition, geoip.ASNEdition} {
path := filepath.Join(td, edition+".tar.gz") path := filepath.Join(td, geoip.TarGzName(edition))
os.Remove(path) os.Remove(path)
os.Remove(path + ".meta") os.Remove(path + ".meta")
@ -96,7 +96,7 @@ func TestDownload_ConditionalGet_FreshCacher(t *testing.T) {
td := testdataDir(t) td := testdataDir(t)
for _, edition := range []string{geoip.CityEdition, geoip.ASNEdition} { for _, edition := range []string{geoip.CityEdition, geoip.ASNEdition} {
path := filepath.Join(td, edition+".tar.gz") path := filepath.Join(td, geoip.TarGzName(edition))
if _, err := newCacher(cfg, edition, path).Fetch(); err != nil { if _, err := newCacher(cfg, edition, path).Fetch(); err != nil {
t.Fatalf("%s initial Fetch: %v", edition, err) t.Fatalf("%s initial Fetch: %v", edition, err)