Show build progress instead of a static "Building…"
terrain.pmtiles can take minutes (tiles fetched one at a time) with no way to tell a slow build from a stuck one. Now reports tiles_done/ tiles_total into the same status Hash the frontend already polls, and the panel shows elapsed time (both files) plus tile counts (terrain only) so the numbers visibly move every ~3s poll instead of sitting on one static string.
This commit is contained in:
1 parent
d72f8a3c94
commit
bbe9f38bda
3 files changed
+68
-8
No files matched your search
@@ -66,10 +66,14 @@ module Maptool
|
||||
|
||||
# fetch_tile: same injectable-seam reasoning as fetch_build_url above,
|
||||
# for the many individual Terrarium tile fetches this needs instead of
|
||||
# one index lookup.
|
||||
# one index lookup. This build can run for minutes with nothing else to
|
||||
# show for it, so write_terrarium_mbtiles reports tiles_done/tiles_total
|
||||
# into the status Hash as it goes — otherwise a poller sees "running"
|
||||
# the whole time with no way to tell it apart from stuck.
|
||||
def self.build_terrain(bounds, data_dir:, fetch_tile: method(:fetch_terrarium_tile))
|
||||
begin_run!(TERRAIN_MUTEX, TERRAIN_STATUS)
|
||||
Thread.new { run_job(TERRAIN_MUTEX, TERRAIN_STATUS) { build_terrain_pmtiles(bounds, data_dir, fetch_tile) } }
|
||||
progress = ->(done, total) { TERRAIN_MUTEX.synchronize { TERRAIN_STATUS.merge!(tiles_done: done, tiles_total: total) } }
|
||||
Thread.new { run_job(TERRAIN_MUTEX, TERRAIN_STATUS) { build_terrain_pmtiles(bounds, data_dir, fetch_tile, progress) } }
|
||||
end
|
||||
|
||||
def self.begin_run!(mutex, status)
|
||||
@@ -117,12 +121,12 @@ module Maptool
|
||||
|
||||
# --- terrain.pmtiles ---
|
||||
|
||||
def self.build_terrain_pmtiles(bounds, data_dir, fetch_tile)
|
||||
def self.build_terrain_pmtiles(bounds, data_dir, fetch_tile, progress)
|
||||
south, west, north, east = bounds
|
||||
tmp_mbtiles = File.join(Dir.tmpdir, "maptool-terrain-#{Process.pid}-#{Time.now.to_i}.mbtiles")
|
||||
tmp_path = File.join(data_dir, "terrain.pmtiles.tmp")
|
||||
|
||||
write_terrarium_mbtiles(tmp_mbtiles, south, west, north, east, fetch_tile)
|
||||
write_terrarium_mbtiles(tmp_mbtiles, south, west, north, east, fetch_tile, progress)
|
||||
run_pmtiles!("convert", tmp_mbtiles, tmp_path)
|
||||
File.rename(tmp_path, File.join(data_dir, "terrain.pmtiles"))
|
||||
ensure
|
||||
@@ -141,7 +145,7 @@ module Maptool
|
||||
# park-sized region, slow for a big one. Add a small bounded-concurrency
|
||||
# fetch pool if regenerating a large area turns out to matter in
|
||||
# practice.
|
||||
def self.write_terrarium_mbtiles(path, south, west, north, east, fetch_tile)
|
||||
def self.write_terrarium_mbtiles(path, south, west, north, east, fetch_tile, progress)
|
||||
db = SQLite3::Database.new(path)
|
||||
db.execute_batch(<<~SQL)
|
||||
CREATE TABLE metadata (name TEXT, value TEXT);
|
||||
@@ -152,9 +156,19 @@ module Maptool
|
||||
db.execute("INSERT INTO metadata (name, value) VALUES (?, ?)", [name, value])
|
||||
end
|
||||
|
||||
(0..TERRAIN_MAX_ZOOM).each do |z|
|
||||
tile_range(z, south, west, north, east).each do |x, y|
|
||||
# tile_range per zoom computed once upfront (cheap — no fetching, just
|
||||
# tile math) and reused below, so progress can report a real total
|
||||
# from the very first call instead of only once the run finishes.
|
||||
by_zoom = (0..TERRAIN_MAX_ZOOM).map { |z| [z, tile_range(z, south, west, north, east)] }
|
||||
total = by_zoom.sum { |_z, tiles| tiles.size }
|
||||
done = 0
|
||||
progress.call(done, total)
|
||||
|
||||
by_zoom.each do |z, tiles|
|
||||
tiles.each do |x, y|
|
||||
bytes = fetch_tile.call(z, x, y)
|
||||
done += 1
|
||||
progress.call(done, total)
|
||||
next unless bytes
|
||||
|
||||
# MBTiles uses TMS row numbering (0 at the south) — the opposite
|
||||
|
||||
Reference in new issue
Block a user