Fix Planetiler tmp-file format detection, add build progress and delete
CI / check (push) Successful in 19s
CI / deploy (push) Successful in 13s

Root cause of "planetiler exited with status 1: ... Unsupported format
tmp" (and likely the earlier unexplained "pmtiles exited with status
1"): Planetiler/go-pmtiles pick their output archive format from the
file extension, and the atomic-rename tmp files were named
"offline.pmtiles.tmp"/"terrain.pmtiles.tmp" — ".tmp" as the extension,
not ".pmtiles". Renamed to "offline.tmp.pmtiles"/"terrain.tmp.pmtiles".

Also, since build-status only ever said "running since X" with no way
to tell what it was actually doing:
- GET .../build-status now includes a `step` string ("fetching PL
  (3/4) — done: SK, CZ — pending: HU", "tiling with planetiler", ...)
  while a build is in progress.
- DELETE /api/offline-tiles / /api/terrain-tiles clear a built file,
  its sidecar meta, and (for offline) the whole per-country download
  cache — a manual "reclaim space" / "start over" action the region
  picker's Apply never did on its own. DELETE
  /api/offline-tiles/cache/:code clears just one country's cached
  extract. All three are 409 while that kind's build is running, and
  surfaced as a small "Delete" button on each row in the Offline data
  panel.
This commit is contained in:
randy committed 2026-09-11 23:23:46 +02:00
1 parent 2878270187
commit b54020e23b
7 files changed
+327 -23

No files matched your search

+79 -1
View File
@@ -171,7 +171,7 @@ class PmtilesBuilderTest < Minitest::Test
thread.join
assert_path_exists File.join(@data_dir, "offline.pmtiles")
refute_path_exists File.join(@data_dir, "offline.pmtiles.tmp")
refute_path_exists File.join(@data_dir, "offline.tmp.pmtiles")
assert_equal "done", Maptool::PmtilesBuilder.offline_status[:state]
assert_equal ["planetiler --osm-path"], log_lines
assert_equal(
@@ -260,6 +260,84 @@ class PmtilesBuilderTest < Minitest::Test
assert_equal 1, calls.count { |url| url.include?("austria") }
end
# offline_status[:step] should say which country is in flight right now
# and which of the current build's selection are already done/still
# pending — not just "running since X".
def test_build_offline_reports_progress_step_while_running
select_regions("SK", "AT")
started = Queue.new
gate = Queue.new
download_extract = ->(url, dest) {
started.push(url)
gate.pop
File.write(dest, "fake")
"Wed, 10 Sep 2026 08:00:01 GMT"
}
thread = Maptool::PmtilesBuilder.build_offline(data_dir: @data_dir, download_extract: download_extract)
started.pop
assert_equal "fetching SK (1/2) — pending: AT", Maptool::PmtilesBuilder.offline_status[:step]
gate.push(:go)
started.pop
assert_equal "fetching AT (2/2) — done: SK", Maptool::PmtilesBuilder.offline_status[:step]
gate.push(:go)
thread.join
assert_nil Maptool::PmtilesBuilder.offline_status[:step]
end
def test_delete_offline_data_removes_the_file_meta_and_cache
select_regions("SK")
Maptool::PmtilesBuilder.build_offline(data_dir: @data_dir, download_extract: fake_download).join
assert_path_exists File.join(@data_dir, "offline.pmtiles")
assert_path_exists File.join(@data_dir, "geofabrik_cache", "SK.osm.pbf")
Maptool::PmtilesBuilder.delete_offline_data(@data_dir)
refute_path_exists File.join(@data_dir, "offline.pmtiles")
refute_path_exists File.join(@data_dir, "geofabrik_cache")
assert_nil Maptool::PmtilesBuilder.offline_meta(@data_dir)
end
def test_delete_offline_data_is_a_noop_when_nothing_was_built
Maptool::PmtilesBuilder.delete_offline_data(@data_dir) # should not raise
end
def test_delete_offline_data_raises_while_a_build_is_running
select_regions("SK")
gate = Queue.new
thread = Maptool::PmtilesBuilder.build_offline(data_dir: @data_dir, download_extract: ->(_url, _dest) { gate.pop })
assert_raises(Maptool::PmtilesBuilder::BuildError) { Maptool::PmtilesBuilder.delete_offline_data(@data_dir) }
ensure
gate.push("unused")
thread&.join
end
def test_delete_cached_extract_removes_only_that_country
select_regions("SK", "AT")
Maptool::PmtilesBuilder.build_offline(data_dir: @data_dir, download_extract: fake_download).join
Maptool::PmtilesBuilder.delete_cached_extract(@data_dir, "SK")
refute_path_exists File.join(@data_dir, "geofabrik_cache", "SK.osm.pbf")
assert_path_exists File.join(@data_dir, "geofabrik_cache", "AT.osm.pbf")
end
def test_delete_terrain_data_removes_the_file_and_meta
select_regions("ES")
ENV["PMTILES_BIN"] = @pmtiles_ok
thread = Maptool::PmtilesBuilder.build_terrain(data_dir: @data_dir, fetch_manifest: -> { fake_manifest })
thread.join
assert_path_exists File.join(@data_dir, "terrain.pmtiles")
Maptool::PmtilesBuilder.delete_terrain_data(@data_dir)
refute_path_exists File.join(@data_dir, "terrain.pmtiles")
assert_nil Maptool::PmtilesBuilder.terrain_meta(@data_dir)
end
def test_offline_meta_is_nil_before_any_build
assert_nil Maptool::PmtilesBuilder.offline_meta(@data_dir)
end