Cache parsed GPX/FIT GeoJSON to fix large POI-export loads
A several-thousand-waypoint park4night area export re-parses the whole file with REXML on every toggle — ~2.4s for a 5k-waypoint/3.6MB sample, so tens of seconds for a 50k-waypoint one, likely the actual cause behind a "Could not load" report on a 41.5MB export. MapLibre already clusters the waypoint layer client-side, so the bottleneck was never rendering — cache the GeoJSON conversion alongside the source file (invalidated by mtime) instead of a bigger bbox/tiling rework.
This commit is contained in:
1 parent
b6a9c1546e
commit
ddf2ee4990
4 files changed
+94
-9
No files matched your search
@@ -67,4 +67,59 @@ class GpxStoreTest < Minitest::Test
|
||||
assert_equal "archive/ride-1.gpx", new_path
|
||||
assert_empty @store.tree["children"].reject { |c| c["name"] == "archive" }
|
||||
end
|
||||
|
||||
def test_geojson_is_cached_alongside_the_source_file
|
||||
path = @store.save(folder: "", filename: "ride.gpx", io: StringIO.new(sample_gpx))
|
||||
cache_path = @store.resolve_file(path) + ".geojson"
|
||||
refute File.file?(cache_path)
|
||||
|
||||
first = @store.geojson(path)
|
||||
assert File.file?(cache_path)
|
||||
|
||||
# Corrupt the cache directly to prove the second call reused it instead
|
||||
# of re-parsing the (still-valid) source file.
|
||||
File.write(cache_path, first.sub("waypoint", "cached-waypoint"))
|
||||
assert_includes @store.geojson(path), "cached-waypoint"
|
||||
end
|
||||
|
||||
def test_geojson_cache_is_invalidated_when_the_file_is_resaved
|
||||
path = @store.save(folder: "", filename: "ride.gpx", io: StringIO.new(sample_gpx))
|
||||
@store.geojson(path)
|
||||
|
||||
File.write(@store.resolve_file(path), sample_gpx.sub("Waypoint", "Renamed"))
|
||||
FileUtils.touch(@store.resolve_file(path), mtime: Time.now + 1)
|
||||
|
||||
assert_includes @store.geojson(path), "Renamed"
|
||||
end
|
||||
|
||||
def test_delete_file_removes_the_geojson_cache_too
|
||||
path = @store.save(folder: "", filename: "ride.gpx", io: StringIO.new(sample_gpx))
|
||||
@store.geojson(path)
|
||||
cache_path = @store.resolve_file(path) + ".geojson"
|
||||
|
||||
@store.delete_file(path)
|
||||
|
||||
refute File.file?(cache_path)
|
||||
end
|
||||
|
||||
def test_move_relocates_the_geojson_cache_too
|
||||
path = @store.save(folder: "", filename: "ride.gpx", io: StringIO.new(sample_gpx))
|
||||
@store.geojson(path)
|
||||
|
||||
new_path = @store.move(from: path, to_folder: "archive")
|
||||
|
||||
assert File.file?(@store.resolve_file(new_path) + ".geojson")
|
||||
end
|
||||
|
||||
def test_geojson_raises_enoent_for_a_missing_file
|
||||
assert_raises(Errno::ENOENT) { @store.geojson("nope.gpx") }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def sample_gpx
|
||||
<<~GPX
|
||||
<gpx><wpt lat="48.1" lon="17.1"><name>Waypoint</name></wpt></gpx>
|
||||
GPX
|
||||
end
|
||||
end
|
||||
Reference in new issue
Block a user