Fix Planetiler tmp-file format detection, add build progress and delete
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:
1 parent
2878270187
commit
b54020e23b
7 files changed
+327
-23
No files matched your search
@@ -72,6 +72,9 @@ class AppTest < Minitest::Test
|
||||
assert_equal 401, request.post("/api/plugins/test-plugin/run").status
|
||||
assert_equal 401, request.post("/api/offline-tiles/build").status
|
||||
assert_equal 401, request.post("/api/terrain-tiles/build").status
|
||||
assert_equal 401, request.delete("/api/offline-tiles").status
|
||||
assert_equal 401, request.delete("/api/offline-tiles/cache/SK").status
|
||||
assert_equal 401, request.delete("/api/terrain-tiles").status
|
||||
end
|
||||
|
||||
# --- GPX/FIT upload and the tree ---
|
||||
@@ -417,6 +420,35 @@ class AppTest < Minitest::Test
|
||||
thread&.join
|
||||
end
|
||||
|
||||
def test_offline_tiles_delete_is_ok_when_nothing_was_built
|
||||
assert_equal 200, request.delete("/api/offline-tiles", **logged_in_env).status
|
||||
end
|
||||
|
||||
def test_offline_tiles_delete_removes_the_file_and_cache
|
||||
path = File.join(Maptool::App::DATA_DIR, "offline.pmtiles")
|
||||
cache_dir = File.join(Maptool::App::DATA_DIR, "geofabrik_cache")
|
||||
File.write(path, "fake")
|
||||
FileUtils.mkdir_p(cache_dir)
|
||||
File.write(File.join(cache_dir, "SK.osm.pbf"), "fake")
|
||||
|
||||
response = request.delete("/api/offline-tiles", **logged_in_env)
|
||||
|
||||
assert_equal 200, response.status
|
||||
refute_path_exists path
|
||||
refute_path_exists cache_dir
|
||||
end
|
||||
|
||||
def test_offline_tiles_delete_is_409_when_a_build_is_running
|
||||
Maptool::PmtilesBuilder.set_selected_regions(Maptool::App::DATA_DIR, ["SK"])
|
||||
gate = Queue.new
|
||||
thread = Maptool::PmtilesBuilder.build_offline(data_dir: Maptool::App::DATA_DIR, download_extract: ->(_url, _dest) { gate.pop })
|
||||
|
||||
assert_equal 409, request.delete("/api/offline-tiles", **logged_in_env).status
|
||||
ensure
|
||||
gate.push("unused")
|
||||
thread&.join
|
||||
end
|
||||
|
||||
# --- LiveTrack webhook ---
|
||||
|
||||
def test_livetrack_webhook_requires_the_configured_secret
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user