Part of #203, from item 5 and "The two caches" of the proposal sneak agreed to (#203 (comment), #203 (comment)); he chose "city lite download ok". Depends on the PTR issue, which creates cache.db, linked from the plan on that issue.
Falls back on a timeout or an error to DB-IP City Lite, read with github.com/oschwald/maxminddb-golang/v2.
Keeps the geojs answers in a new table in cache.db (internal/cachedb) and in memory, loaded at startup, at most 250,000 entries in memory, least recently used dropped first. An entry expires 7 days after its fetch. A sweep every 10 minutes deletes expired rows. A memory miss reads the table before asking geojs.
It downloads the database from https://download.db-ip.com/free/dbip-city-lite-YYYY-MM.mmdb.gz, once a month, into the state directory, at most 200 MiB, replacing the old file only once the new one opens. Check the current URL first.
Every result gains geo. A part the source does not know is null; geo is null only when neither source answers. Before the first download finishes, only geojs answers.
The home page footer carries "IP Geolocation by DB-IP" with a link to https://db-ip.com, as the licence requires.
before:(nothing)after:"geo":{"country_code":"DE","country":"Germany","continent_code":"EU","region":"Brandenburg","city":"Brandenburg an der Havel","latitude":52.6171,"longitude":13.1207,"accuracy_radius_km":20,"time_zone":"Europe/Berlin","source":"geojs","updated":"2026-10-27T20:37:28Z"}
The image does not pre-fetch the database: a pre-fetch needs a pinned hash and the file changes every month, so the first start downloads it.
Tests. A fake geojs over httptest: a batch, "nil" coordinates, a timeout falling back; a small database built with github.com/maxmind/mmdbwriter; the cache surviving a restart; expiry and the memory limit. Addresses from documentation ranges.
Done when. A real lookup returns geo from geojs, and from the database with geojs unreachable (one line on the PR); the README describes the sources, the cache, what is sent outside and the database's memory use.
Model: opus-5-5
Part of https://git.eeqj.de/sneak/routewatch/issues/203, from item 5 and "The two caches" of the proposal sneak agreed to (https://git.eeqj.de/sneak/routewatch/issues/203#issuecomment-159864, https://git.eeqj.de/sneak/routewatch/issues/203#issuecomment-165190); he chose "city lite download ok". Depends on the PTR issue, which creates `cache.db`, linked from the plan on that issue.
**Change.**
1. New package `internal/geo`, doing all of this:
- Asks https://get.geojs.io/v1/ip/geo.json?ip=a,b,c, one batch for all addresses of a lookup, 1 second in all. `latitude` and `longitude` come as strings and are `"nil"` when unknown.
- Falls back on a timeout or an error to DB-IP City Lite, read with `github.com/oschwald/maxminddb-golang/v2`.
- Keeps the geojs answers in a new table in `cache.db` (`internal/cachedb`) and in memory, loaded at startup, at most 250,000 entries in memory, least recently used dropped first. An entry expires 7 days after its fetch. A sweep every 10 minutes deletes expired rows. A memory miss reads the table before asking geojs.
2. It downloads the database from `https://download.db-ip.com/free/dbip-city-lite-YYYY-MM.mmdb.gz`, once a month, into the state directory, at most 200 MiB, replacing the old file only once the new one opens. Check the current URL first.
3. Every result gains `geo`. A part the source does not know is null; `geo` is null only when neither source answers. Before the first download finishes, only geojs answers.
4. The home page footer carries "IP Geolocation by DB-IP" with a link to https://db-ip.com, as the licence requires.
```json
before: (nothing)
after: "geo": {"country_code": "DE", "country": "Germany", "continent_code": "EU", "region": "Brandenburg", "city": "Brandenburg an der Havel", "latitude": 52.6171, "longitude": 13.1207, "accuracy_radius_km": 20, "time_zone": "Europe/Berlin", "source": "geojs", "updated": "2026-10-27T20:37:28Z"}
```
The image does not pre-fetch the database: a pre-fetch needs a pinned hash and the file changes every month, so the first start downloads it.
**Tests.** A fake geojs over `httptest`: a batch, `"nil"` coordinates, a timeout falling back; a small database built with `github.com/maxmind/mmdbwriter`; the cache surviving a restart; expiry and the memory limit. Addresses from documentation ranges.
**Done when.** A real lookup returns `geo` from geojs, and from the database with geojs unreachable (one line on the PR); the README describes the sources, the cache, what is sent outside and the database's memory use.
Model: opus-5-5
clawbot
self-assigned this 2026-11-10 10:15:09 +01:00
Built in #249: internal/geo adds geo to every IP lookup result, from geojs with DB-IP City Lite as the fallback, cached in memory and in cache.db for 7 days. The PR body lists the judgement calls.Model: opus-5-5
Built in https://git.eeqj.de/sneak/routewatch/pulls/249: `internal/geo` adds `geo` to every IP lookup result, from geojs with DB-IP City Lite as the fallback, cached in memory and in `cache.db` for 7 days. The PR body lists the judgement calls.Model: opus-5-5
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Part of #203, from item 5 and "The two caches" of the proposal sneak agreed to (#203 (comment), #203 (comment)); he chose "city lite download ok". Depends on the PTR issue, which creates
cache.db, linked from the plan on that issue.Change.
internal/geo, doing all of this:latitudeandlongitudecome as strings and are"nil"when unknown.github.com/oschwald/maxminddb-golang/v2.cache.db(internal/cachedb) and in memory, loaded at startup, at most 250,000 entries in memory, least recently used dropped first. An entry expires 7 days after its fetch. A sweep every 10 minutes deletes expired rows. A memory miss reads the table before asking geojs.https://download.db-ip.com/free/dbip-city-lite-YYYY-MM.mmdb.gz, once a month, into the state directory, at most 200 MiB, replacing the old file only once the new one opens. Check the current URL first.geo. A part the source does not know is null;geois null only when neither source answers. Before the first download finishes, only geojs answers.The image does not pre-fetch the database: a pre-fetch needs a pinned hash and the file changes every month, so the first start downloads it.
Tests. A fake geojs over
httptest: a batch,"nil"coordinates, a timeout falling back; a small database built withgithub.com/maxmind/mmdbwriter; the cache surviving a restart; expiry and the memory limit. Addresses from documentation ranges.Done when. A real lookup returns
geofrom geojs, and from the database with geojs unreachable (one line on the PR); the README describes the sources, the cache, what is sent outside and the database's memory use.Model: opus-5-5
Built in #249:
internal/geoaddsgeoto every IP lookup result, from geojs with DB-IP City Lite as the fallback, cached in memory and incache.dbfor 7 days. The PR body lists the judgement calls.Model: opus-5-5clawbot referenced this issue2026-11-10 15:48:16 +01:00