#!/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) # 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 # 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() { complete=0 if ! mkdir -p next; then echo "/tiles/next can't be made; the tiles stay as they are." >&2 return 0 fi 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." complete=1 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)." complete=1 else rm -f next/europe.pmtiles echo "The cut of $build failed; the tiles stay as they are." >&2 fi } # 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 while :; do refresh 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 done