mirror of
https://github.com/therootcompany/golib.git
synced 2026-04-24 20:58:00 +00:00
feat(geoip): Open falls back to lex-latest <edition>_*.tar.gz
Prefer <edition>_LATEST.tar.gz (what httpcache writes), but fall back to the lexicographically greatest <edition>_*.tar.gz — MaxMind's dated Content-Disposition names sort chronologically, so this picks the most recent archive when the cache was populated by hand or by another tool. Exposes FindTarGz for callers that need the resolved path.
This commit is contained in:
parent
e594f2503c
commit
8f40bbf110
@ -9,6 +9,7 @@ import (
|
|||||||
"net/netip"
|
"net/netip"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/oschwald/geoip2-golang"
|
"github.com/oschwald/geoip2-golang"
|
||||||
@ -20,15 +21,26 @@ type Databases struct {
|
|||||||
ASN *geoip2.Reader
|
ASN *geoip2.Reader
|
||||||
}
|
}
|
||||||
|
|
||||||
// Open reads <dir>/<edition>_LATEST.tar.gz for City and ASN editions,
|
// Open loads the City and ASN editions from dir. For each edition it
|
||||||
// extracts the .mmdb entry from each archive in memory, and returns open
|
// prefers <edition>_LATEST.tar.gz and falls back to the
|
||||||
// readers. No .mmdb files are written to disk.
|
// lexicographically greatest <edition>_*.tar.gz match (MaxMind's
|
||||||
|
// Content-Disposition names sort chronologically by release date).
|
||||||
|
// Archives are extracted in memory — 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, TarGzName(CityEdition)))
|
cityPath, err := FindTarGz(dir, 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, TarGzName(ASNEdition)))
|
city, err := openMMDBTarGz(cityPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("city: %w", err)
|
||||||
|
}
|
||||||
|
asnPath, err := FindTarGz(dir, ASNEdition)
|
||||||
|
if err != nil {
|
||||||
|
_ = city.Close()
|
||||||
|
return nil, fmt.Errorf("asn: %w", err)
|
||||||
|
}
|
||||||
|
asn, err := openMMDBTarGz(asnPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_ = city.Close()
|
_ = city.Close()
|
||||||
return nil, fmt.Errorf("asn: %w", err)
|
return nil, fmt.Errorf("asn: %w", err)
|
||||||
@ -36,6 +48,25 @@ func Open(dir string) (*Databases, error) {
|
|||||||
return &Databases{City: city, ASN: asn}, nil
|
return &Databases{City: city, ASN: asn}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FindTarGz resolves the cached tarball path for edition inside dir,
|
||||||
|
// preferring <edition>_LATEST.tar.gz and falling back to the
|
||||||
|
// lexicographically greatest <edition>_*.tar.gz match.
|
||||||
|
func FindTarGz(dir, edition string) (string, error) {
|
||||||
|
preferred := filepath.Join(dir, TarGzName(edition))
|
||||||
|
if _, err := os.Stat(preferred); err == nil {
|
||||||
|
return preferred, nil
|
||||||
|
}
|
||||||
|
matches, err := filepath.Glob(filepath.Join(dir, edition+"_*.tar.gz"))
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
if len(matches) == 0 {
|
||||||
|
return "", fmt.Errorf("no %s_*.tar.gz in %s", edition, dir)
|
||||||
|
}
|
||||||
|
slices.Sort(matches)
|
||||||
|
return matches[len(matches)-1], nil
|
||||||
|
}
|
||||||
|
|
||||||
func openMMDBTarGz(path string) (*geoip2.Reader, error) {
|
func openMMDBTarGz(path string) (*geoip2.Reader, error) {
|
||||||
f, err := os.Open(path)
|
f, err := os.Open(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user