Skip to content

Commit ecfd41e

Browse files
mikhail-dclclaude
andcommitted
feat: predownload geo CSVs at local build time (M4)
Local (non-Docker) runs had no geodb/ and resolved every peer to region="unknown". Add a FetchGeoDb MSBuild target that caches the two CSVs in packages/geodb and copies them next to the build output. Docker builds/containers (FetchGeoDb=false) and CI (CI=true) skip it, so the images' build-time ADD stays authoritative. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 86dcfca commit ecfd41e

5 files changed

Lines changed: 40 additions & 1 deletion

File tree

Dockerfile.debug

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,8 @@ COPY . .
99
ADD https://cdn.jsdelivr.net/npm/@ip-location-db/geo-whois-asn-country/geo-whois-asn-country-ipv4-num.csv \
1010
https://cdn.jsdelivr.net/npm/@ip-location-db/geo-whois-asn-country/geo-whois-asn-country-ipv6-num.csv \
1111
/app/geodb/
12+
# The image already has fresh geo CSVs from the ADD above; the entrypoint's `dotnet run`
13+
# would otherwise trigger the csproj predownload at container start, so disable it.
14+
ENV FetchGeoDb=false
1215
EXPOSE 7777/udp
1316
ENTRYPOINT ["dotnet", "run", "--project", "src/DCLPulse/DCLPulse.csproj", "--configuration", "Debug", "--property:GenerateProto=false"]

docs/metrics.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,12 @@ histogram_quantile(0.5, sum by (le) (rate(dcl_pulse_peer_rtt_ms_bucket{region="a
281281
| `unknown` dominating with a real player population | Geo database missing from the image, or peers behind private/CGNAT egress the DB can't place |
282282
| Everything near 500 ms right after a connect burst | The ENet seed showing through before ACK samples arrive — transient, ignore |
283283

284-
**Data source**: [geo-whois-asn-country](https://github.com/sapics/ip-location-db) (CC0, public domain), the `-num` CSV variants. Each of the three Dockerfiles fetches the IPv4 and IPv6 CSVs into the image's `geodb/` directory at build time via a single `ADD` — no runtime download. `ContinentResolver` loads them once at startup from `Transport:GeoDbDirectory` (default `geodb`, resolved against the app base directory; absolute paths are used as-is). Missing files are tolerated — every peer then reports under `region="unknown"`.
284+
**Data source**: [geo-whois-asn-country](https://github.com/sapics/ip-location-db) (CC0, public domain), the `-num` CSV variants. `ContinentResolver` loads them once at startup from `Transport:GeoDbDirectory` (default `geodb`, resolved against the app base directory; absolute paths are used as-is). Missing files are tolerated — every peer then reports under `region="unknown"`.
285+
286+
Two ways the CSVs get to that directory:
287+
288+
- **Docker**: each of the three Dockerfiles fetches fresh IPv4 and IPv6 CSVs into the image's `geodb/` directory at build time via a single `ADD` — no runtime download. These freshly-fetched copies are authoritative for images.
289+
- **Local (non-Docker) builds**: the `DCLPulse.csproj` `FetchGeoDb` target predownloads the two CSVs into the gitignored `packages/geodb/` cache (once) and copies them next to the build output, so local runs resolve regions without a Docker image. Delete `packages/geodb` to force a refresh. Offline builds warn and continue — the app then degrades to `region="unknown"`. The download is skipped in Docker builds and containers (`FetchGeoDb=false`) and on CI (`CI=true`), so it never runs where the `ADD`-provided or in-memory test copies already apply.
285290

286291
---
287292

src/DCLPulse/DCLPulse.csproj

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,29 @@
4949
<TargetPath>libenet.dylib</TargetPath>
5050
</None>
5151
</ItemGroup>
52+
53+
<!-- Geo database predownload for local runs. Docker images fetch their own fresh
54+
copies via ADD (which take precedence at runtime); Docker builds and CI set
55+
FetchGeoDb=false / CI=true so this never runs there. Delete packages/geodb
56+
to force a re-download. -->
57+
<PropertyGroup>
58+
<GeoDbCacheDir>$(MSBuildThisFileDirectory)..\..\packages\geodb\</GeoDbCacheDir>
59+
</PropertyGroup>
60+
61+
<Target Name="FetchGeoDb" BeforeTargets="Build"
62+
Condition="'$(FetchGeoDb)' != 'false' and '$(CI)' == ''">
63+
<DownloadFile SourceUrl="https://cdn.jsdelivr.net/npm/@ip-location-db/geo-whois-asn-country/geo-whois-asn-country-ipv4-num.csv"
64+
DestinationFolder="$(GeoDbCacheDir)"
65+
Condition="!Exists('$(GeoDbCacheDir)geo-whois-asn-country-ipv4-num.csv')"
66+
ContinueOnError="WarnAndContinue" />
67+
<DownloadFile SourceUrl="https://cdn.jsdelivr.net/npm/@ip-location-db/geo-whois-asn-country/geo-whois-asn-country-ipv6-num.csv"
68+
DestinationFolder="$(GeoDbCacheDir)"
69+
Condition="!Exists('$(GeoDbCacheDir)geo-whois-asn-country-ipv6-num.csv')"
70+
ContinueOnError="WarnAndContinue" />
71+
<ItemGroup>
72+
<GeoDbFiles Include="$(GeoDbCacheDir)*.csv" />
73+
</ItemGroup>
74+
<Copy SourceFiles="@(GeoDbFiles)" DestinationFolder="$(OutDir)geodb"
75+
SkipUnchangedFiles="true" Condition="'@(GeoDbFiles)' != ''" />
76+
</Target>
5277
</Project>

src/DCLPulse/Dockerfile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
22
ARG BUILD_CONFIGURATION=Release
3+
# The image fetches its own fresh geo CSVs via ADD in the final stage; disable the
4+
# csproj's local predownload so the build/publish steps never hit the network for them.
5+
ENV FetchGeoDb=false
36
WORKDIR /build
47
COPY ["src/DCLPulse/DCLPulse.csproj", "src/DCLPulse/"]
58
COPY ["src/DCLPulse/global.json", "src/DCLPulse/"]

src/DCLPulse/Dockerfile.dev-debug

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
FROM mcr.microsoft.com/dotnet/sdk:10.0 AS build
2+
# The image fetches its own fresh geo CSVs via ADD in the final stage; disable the
3+
# csproj's local predownload so the build/publish steps never hit the network for them.
4+
ENV FetchGeoDb=false
25
WORKDIR /build
36
COPY ["src/DCLPulse/DCLPulse.csproj", "src/DCLPulse/"]
47
COPY ["src/DCLPulse/global.json", "src/DCLPulse/"]

0 commit comments

Comments
 (0)