2026-10-29 16:04:05 +01:00
|
|
|
#!/bin/sh
|
|
|
|
|
# Keeps the instance's own map tiles current (Halkyon Train's ADR 0030, D50): the
|
|
|
|
|
# newest of Protomaps' daily builds of the planet, cut to MAP_REGION (`west,south,
|
|
|
|
|
# east,north` in degrees; by default Europe's, the box BRouter's segments cover) at
|
|
|
|
|
# zooms 0 to 15, into /tiles/europe.pmtiles; again every MAP_REFRESH_DAYS days (30)
|
2026-10-30 12:55:42 +01:00
|
|
|
# where a newer build has come; after a round where the builds' list or the cut
|
|
|
|
|
# failed, again in an hour, the wait doubling up to a day while rounds keep failing.
|
|
|
|
|
# The cut is written into /tiles/next/ and moved over
|
2026-10-29 16:04:05 +01:00
|
|
|
# the old one, so the server never reads half a file; until it is done, the old one
|
|
|
|
|
# serves. Both at once take twice a cut's room.
|
|
|
|
|
set -eu
|
|
|
|
|
|
|
|
|
|
builds=https://build-metadata.protomaps.dev/builds.json
|
|
|
|
|
region=${MAP_REGION:--25,35,45,75}
|
|
|
|
|
days=${MAP_REFRESH_DAYS:-30}
|
|
|
|
|
cd /tiles
|
|
|
|
|
|
|
|
|
|
refresh() {
|
2026-10-30 12:55:42 +01:00
|
|
|
complete=0
|
|
|
|
|
if ! mkdir -p next; then
|
|
|
|
|
echo "/tiles/next can't be made; the tiles stay as they are." >&2
|
|
|
|
|
return 0
|
|
|
|
|
fi
|
2026-10-29 16:04:05 +01:00
|
|
|
build=$(curl -fsS "$builds" | grep -o '"key": *"[0-9]\{8\}\.pmtiles"' |
|
|
|
|
|
grep -o '[0-9]\{8\}\.pmtiles' | sort | tail -n 1) || build=
|
|
|
|
|
if [ -z "$build" ]; then
|
|
|
|
|
echo "Protomaps' builds didn't come; the tiles stay as they are." >&2
|
|
|
|
|
return 0
|
|
|
|
|
fi
|
|
|
|
|
if [ -e europe.build ] && [ "$(cat europe.build)" = "$build" ]; then
|
|
|
|
|
echo "The tiles are $build's, the newest."
|
2026-10-30 12:55:42 +01:00
|
|
|
complete=1
|
2026-10-29 16:04:05 +01:00
|
|
|
return 0
|
|
|
|
|
fi
|
|
|
|
|
rm -f next/europe.pmtiles
|
|
|
|
|
if pmtiles extract "https://build.protomaps.com/$build" next/europe.pmtiles \
|
|
|
|
|
--bbox="$region" --maxzoom=15 --download-threads=4; then
|
|
|
|
|
mv next/europe.pmtiles europe.pmtiles
|
|
|
|
|
echo "$build" >europe.build
|
|
|
|
|
echo "The tiles are $build's now, $(du -h europe.pmtiles | cut -f1)."
|
2026-10-30 12:55:42 +01:00
|
|
|
complete=1
|
2026-10-29 16:04:05 +01:00
|
|
|
else
|
|
|
|
|
rm -f next/europe.pmtiles
|
|
|
|
|
echo "The cut of $build failed; the tiles stay as they are." >&2
|
|
|
|
|
fi
|
|
|
|
|
}
|
|
|
|
|
|
2026-10-30 12:55:42 +01:00
|
|
|
# Seconds to wait after the $1th incomplete round in a row: $2, doubling up to $3.
|
|
|
|
|
backoff() {
|
|
|
|
|
pause=$2 n=1
|
|
|
|
|
while [ "$n" -lt "$1" ] && [ "$pause" -lt "$3" ]; do
|
|
|
|
|
pause=$((pause * 2)) n=$((n + 1))
|
|
|
|
|
done
|
|
|
|
|
if [ "$pause" -gt "$3" ]; then pause=$3; fi
|
|
|
|
|
echo "$pause"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
failures=0
|
2026-10-29 16:04:05 +01:00
|
|
|
while :; do
|
|
|
|
|
refresh
|
2026-10-30 12:55:42 +01:00
|
|
|
if [ "$complete" -eq 1 ]; then
|
|
|
|
|
failures=0
|
|
|
|
|
sleep $((days * 86400))
|
|
|
|
|
else
|
|
|
|
|
failures=$((failures + 1))
|
|
|
|
|
pause=$(backoff "$failures" 3600 86400)
|
|
|
|
|
echo "The round wasn't complete; trying again in $((pause / 60)) minutes." >&2
|
|
|
|
|
sleep "$pause"
|
|
|
|
|
fi
|
2026-10-29 16:04:05 +01:00
|
|
|
done
|