forked from MapComplete/MapComplete
Performance: don't do an overpass request on every map pan if zoomed out too much
This commit is contained in:
parent
91a7957b85
commit
417bee2ee8
2 changed files with 21 additions and 28 deletions
|
@ -1,4 +1,4 @@
|
||||||
import { Feature } from "geojson"
|
import { Feature, Geometry } from "geojson"
|
||||||
import { UpdatableFeatureSource } from "../FeatureSource"
|
import { UpdatableFeatureSource } from "../FeatureSource"
|
||||||
import { ImmutableStore, Store, UIEventSource } from "../../UIEventSource"
|
import { ImmutableStore, Store, UIEventSource } from "../../UIEventSource"
|
||||||
import LayerConfig from "../../../Models/ThemeConfig/LayerConfig"
|
import LayerConfig from "../../../Models/ThemeConfig/LayerConfig"
|
||||||
|
@ -7,6 +7,9 @@ import { Overpass } from "../../Osm/Overpass"
|
||||||
import { Utils } from "../../../Utils"
|
import { Utils } from "../../../Utils"
|
||||||
import { TagsFilter } from "../../Tags/TagsFilter"
|
import { TagsFilter } from "../../Tags/TagsFilter"
|
||||||
import { BBox } from "../../BBox"
|
import { BBox } from "../../BBox"
|
||||||
|
import { FeatureCollection } from "@turf/turf"
|
||||||
|
import { OsmTags } from "../../../Models/OsmFeature"
|
||||||
|
"use strict";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A wrapper around the 'Overpass'-object.
|
* A wrapper around the 'Overpass'-object.
|
||||||
|
@ -56,14 +59,13 @@ export default class OverpassFeatureSource implements UpdatableFeatureSource {
|
||||||
this.state = state
|
this.state = state
|
||||||
this._isActive = options?.isActive ?? new ImmutableStore(true)
|
this._isActive = options?.isActive ?? new ImmutableStore(true)
|
||||||
this.padToZoomLevel = options?.padToTiles
|
this.padToZoomLevel = options?.padToTiles
|
||||||
const self = this
|
|
||||||
this._layersToDownload = options?.ignoreZoom
|
this._layersToDownload = options?.ignoreZoom
|
||||||
? new ImmutableStore(state.layers)
|
? new ImmutableStore(state.layers)
|
||||||
: state.zoom.map((zoom) => this.layersToDownload(zoom))
|
: state.zoom.map((zoom) => this.layersToDownload(zoom))
|
||||||
|
|
||||||
state.bounds.mapD(
|
state.bounds.mapD(
|
||||||
(_) => {
|
() => {
|
||||||
self.updateAsyncIfNeeded()
|
this.updateAsyncIfNeeded()
|
||||||
},
|
},
|
||||||
[this._layersToDownload]
|
[this._layersToDownload]
|
||||||
)
|
)
|
||||||
|
@ -104,10 +106,11 @@ export default class OverpassFeatureSource implements UpdatableFeatureSource {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Download the relevant data from overpass. Attempt to use a different server if one fails; only downloads the relevant layers
|
* Download the relevant data from overpass. Attempt to use a different server if one fails; only downloads the relevant layers
|
||||||
|
* Will always attempt to download, even is 'options.isActive.data' is 'false', the zoom level is incorrect, ...
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
public async updateAsync(overrideBounds?: BBox): Promise<void> {
|
public async updateAsync(overrideBounds?: BBox): Promise<void> {
|
||||||
let data: any = undefined
|
let data: FeatureCollection<Geometry, OsmTags> = undefined
|
||||||
let lastUsed = 0
|
let lastUsed = 0
|
||||||
const start = new Date()
|
const start = new Date()
|
||||||
const layersToDownload = this._layersToDownload.data
|
const layersToDownload = this._layersToDownload.data
|
||||||
|
@ -116,8 +119,7 @@ export default class OverpassFeatureSource implements UpdatableFeatureSource {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const self = this
|
const overpassUrls = this.state.overpassUrl.data
|
||||||
const overpassUrls = self.state.overpassUrl.data
|
|
||||||
if (overpassUrls === undefined || overpassUrls.length === 0) {
|
if (overpassUrls === undefined || overpassUrls.length === 0) {
|
||||||
throw "Panic: overpassFeatureSource didn't receive any overpassUrls"
|
throw "Panic: overpassFeatureSource didn't receive any overpassUrls"
|
||||||
}
|
}
|
||||||
|
@ -140,10 +142,11 @@ export default class OverpassFeatureSource implements UpdatableFeatureSource {
|
||||||
return undefined
|
return undefined
|
||||||
}
|
}
|
||||||
this.runningQuery.setData(true)
|
this.runningQuery.setData(true)
|
||||||
|
console.trace("Overpass feature source: querying geojson")
|
||||||
data = (await overpass.queryGeoJson(bounds))[0]
|
data = (await overpass.queryGeoJson(bounds))[0]
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
self.retries.data++
|
this.retries.data++
|
||||||
self.retries.ping()
|
this.retries.ping()
|
||||||
console.error(`QUERY FAILED due to`, e)
|
console.error(`QUERY FAILED due to`, e)
|
||||||
|
|
||||||
await Utils.waitFor(1000)
|
await Utils.waitFor(1000)
|
||||||
|
@ -153,12 +156,12 @@ export default class OverpassFeatureSource implements UpdatableFeatureSource {
|
||||||
console.log("Trying next time with", overpassUrls[lastUsed])
|
console.log("Trying next time with", overpassUrls[lastUsed])
|
||||||
} else {
|
} else {
|
||||||
lastUsed = 0
|
lastUsed = 0
|
||||||
self.timeout.setData(self.retries.data * 5)
|
this.timeout.setData(this.retries.data * 5)
|
||||||
|
|
||||||
while (self.timeout.data > 0) {
|
while (this.timeout.data > 0) {
|
||||||
await Utils.waitFor(1000)
|
await Utils.waitFor(1000)
|
||||||
self.timeout.data--
|
this.timeout.data--
|
||||||
self.timeout.ping()
|
this.timeout.ping()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -180,14 +183,14 @@ export default class OverpassFeatureSource implements UpdatableFeatureSource {
|
||||||
timeNeeded,
|
timeNeeded,
|
||||||
"seconds"
|
"seconds"
|
||||||
)
|
)
|
||||||
self.features.setData(data.features)
|
this.features.setData(data.features)
|
||||||
this._lastQueryBBox = bounds
|
this._lastQueryBBox = bounds
|
||||||
this._lastRequestedLayers = layersToDownload
|
this._lastRequestedLayers = layersToDownload
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("Got the overpass response, but could not process it: ", e, e.stack)
|
console.error("Got the overpass response, but could not process it: ", e, e.stack)
|
||||||
} finally {
|
} finally {
|
||||||
self.retries.setData(0)
|
this.retries.setData(0)
|
||||||
self.runningQuery.setData(false)
|
this.runningQuery.setData(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,6 @@ export default class ThemeSource extends FeatureSourceMerger {
|
||||||
*/
|
*/
|
||||||
public readonly isLoading: Store<boolean>
|
public readonly isLoading: Store<boolean>
|
||||||
|
|
||||||
private readonly supportsForceDownload: UpdatableFeatureSource[]
|
|
||||||
|
|
||||||
public static readonly fromCacheZoomLevel = 15
|
public static readonly fromCacheZoomLevel = 15
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -44,8 +42,6 @@ export default class ThemeSource extends FeatureSourceMerger {
|
||||||
mvtAvailableLayers: Set<string>,
|
mvtAvailableLayers: Set<string>,
|
||||||
fullNodeDatabaseSource?: FullNodeDatabaseSource
|
fullNodeDatabaseSource?: FullNodeDatabaseSource
|
||||||
) {
|
) {
|
||||||
const supportsForceDownload: UpdatableFeatureSource[] = []
|
|
||||||
|
|
||||||
const { bounds, zoom } = mapProperties
|
const { bounds, zoom } = mapProperties
|
||||||
// remove all 'special' layers
|
// remove all 'special' layers
|
||||||
layers = layers.filter((layer) => layer.source !== null && layer.source !== undefined)
|
layers = layers.filter((layer) => layer.source !== null && layer.source !== undefined)
|
||||||
|
@ -95,7 +91,6 @@ export default class ThemeSource extends FeatureSourceMerger {
|
||||||
)
|
)
|
||||||
overpassSource = ThemeSource.setupOverpass(osmLayers, bounds, zoom, featureSwitches)
|
overpassSource = ThemeSource.setupOverpass(osmLayers, bounds, zoom, featureSwitches)
|
||||||
nonMvtSources.push(overpassSource)
|
nonMvtSources.push(overpassSource)
|
||||||
supportsForceDownload.push(overpassSource)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function setIsLoading() {
|
function setIsLoading() {
|
||||||
|
@ -110,7 +105,6 @@ export default class ThemeSource extends FeatureSourceMerger {
|
||||||
ThemeSource.setupGeojsonSource(l, mapProperties, isDisplayed(l.id))
|
ThemeSource.setupGeojsonSource(l, mapProperties, isDisplayed(l.id))
|
||||||
)
|
)
|
||||||
|
|
||||||
const downloadAllBounds: UIEventSource<BBox> = new UIEventSource<BBox>(undefined)
|
|
||||||
const downloadAll = new OverpassFeatureSource(
|
const downloadAll = new OverpassFeatureSource(
|
||||||
{
|
{
|
||||||
layers: layers.filter((l) => l.isNormal()),
|
layers: layers.filter((l) => l.isNormal()),
|
||||||
|
@ -123,6 +117,7 @@ export default class ThemeSource extends FeatureSourceMerger {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ignoreZoom: true,
|
ignoreZoom: true,
|
||||||
|
isActive: new ImmutableStore(false)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -135,13 +130,8 @@ export default class ThemeSource extends FeatureSourceMerger {
|
||||||
)
|
)
|
||||||
|
|
||||||
this.isLoading = isLoading
|
this.isLoading = isLoading
|
||||||
supportsForceDownload.push(...geojsonSources)
|
|
||||||
supportsForceDownload.push(...mvtSources) // Non-mvt sources are handled by overpass
|
|
||||||
|
|
||||||
this._mapBounds = mapProperties.bounds
|
|
||||||
this._downloadAll = downloadAll
|
this._downloadAll = downloadAll
|
||||||
|
this._mapBounds = mapProperties.bounds
|
||||||
this.supportsForceDownload = supportsForceDownload
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static setupMvtSource(
|
private static setupMvtSource(
|
||||||
|
|
Loading…
Reference in a new issue