diff --git a/Logic/Actors/OverpassFeatureSource.ts b/Logic/Actors/OverpassFeatureSource.ts index 4510fd733..fbd4bd911 100644 --- a/Logic/Actors/OverpassFeatureSource.ts +++ b/Logic/Actors/OverpassFeatureSource.ts @@ -11,6 +11,8 @@ import {BBox} from "../BBox"; import Loc from "../../Models/Loc"; import LayerConfig from "../../Models/ThemeConfig/LayerConfig"; import Constants from "../../Models/Constants"; +import TileFreshnessCalculator from "../FeatureSource/TileFreshnessCalculator"; +import {Tiles} from "../../Models/TileRange"; export default class OverpassFeatureSource implements FeatureSource { @@ -38,9 +40,18 @@ export default class OverpassFeatureSource implements FeatureSource { readonly overpassTimeout: UIEventSource; readonly currentBounds: UIEventSource } - private readonly _isActive: UIEventSource; + private readonly _isActive: UIEventSource + /** + * Callback to handle all the data + */ private readonly onBboxLoaded: (bbox: BBox, date: Date, layers: LayerConfig[], zoomlevel: number) => void; + /** + * Keeps track of how fresh the data is + * @private + */ + private readonly freshnesses: Map; + constructor( state: { readonly locationControl: UIEventSource, @@ -54,13 +65,15 @@ export default class OverpassFeatureSource implements FeatureSource { padToTiles: UIEventSource, isActive?: UIEventSource, relationTracker: RelationsTracker, - onBboxLoaded?: (bbox: BBox, date: Date, layers: LayerConfig[], zoomlevel: number) => void + onBboxLoaded?: (bbox: BBox, date: Date, layers: LayerConfig[], zoomlevel: number) => void, + freshnesses?: Map }) { this.state = state this._isActive = options.isActive; this.onBboxLoaded = options.onBboxLoaded this.relationsTracker = options.relationTracker + this.freshnesses = options.freshnesses const self = this; state.currentBounds.addCallback(_ => { self.update(options.padToTiles.data) @@ -117,12 +130,13 @@ export default class OverpassFeatureSource implements FeatureSource { const layersToDownload = [] + const neededTiles = this.state.currentBounds.data.expandToTileBounds(padToZoomLevel).containingTileRange(padToZoomLevel) for (const layer of this.state.layoutToUse.layers) { if (typeof (layer) === "string") { throw "A layer was not expanded!" } - if(Constants.priviliged_layers.indexOf(layer.id) >= 0){ + if (Constants.priviliged_layers.indexOf(layer.id) >= 0) { continue } if (this.state.locationControl.data.zoom < layer.minzoom) { @@ -135,9 +149,32 @@ export default class OverpassFeatureSource implements FeatureSource { // Not our responsibility to download this layer! continue; } + const freshness = this.freshnesses?.get(layer.id) + if (freshness !== undefined) { + const oldestDataDate = Math.min(...Tiles.MapRange(neededTiles, (x, y) => { + const date = freshness.freshnessFor(padToZoomLevel, x, y); + if (date === undefined) { + return 0 + } + return date.getTime() + })) / 1000; + const now = new Date().getTime() + const minRequiredAge = (now / 1000) - layer.maxAgeOfCache + if (oldestDataDate >= minRequiredAge) { + // still fresh enough - not updating + continue + } + + } + layersToDownload.push(layer) } + if (layersToDownload.length == 0) { + console.debug("Not updating - no layers needed") + return; + } + const self = this; const overpassUrls = self.state.overpassUrl.data let bounds: BBox diff --git a/Logic/FeatureSource/Actors/RegisteringAllFromFeatureSourceActor.ts b/Logic/FeatureSource/Actors/RegisteringAllFromFeatureSourceActor.ts index 41c2e4bbb..7ee072d40 100644 --- a/Logic/FeatureSource/Actors/RegisteringAllFromFeatureSourceActor.ts +++ b/Logic/FeatureSource/Actors/RegisteringAllFromFeatureSourceActor.ts @@ -1,9 +1,10 @@ import FeatureSource from "../FeatureSource"; import {UIEventSource} from "../../UIEventSource"; -import State from "../../../State"; -import ElementsState from "../../State/ElementsState"; import {ElementStorage} from "../../ElementStorage"; +/** + * Makes sure that every feature is added to the ElementsStorage, so that the tags-eventsource can be retrieved + */ export default class RegisteringAllFromFeatureSourceActor { public readonly features: UIEventSource<{ feature: any; freshness: Date }[]>; public readonly name; diff --git a/Logic/FeatureSource/FeaturePipeline.ts b/Logic/FeatureSource/FeaturePipeline.ts index 125428296..9a32ba25f 100644 --- a/Logic/FeatureSource/FeaturePipeline.ts +++ b/Logic/FeatureSource/FeaturePipeline.ts @@ -40,18 +40,23 @@ import {ElementStorage} from "../ElementStorage"; export default class FeaturePipeline { public readonly sufficientlyZoomed: UIEventSource; - public readonly runningQuery: UIEventSource; public readonly timeout: UIEventSource; - public readonly somethingLoaded: UIEventSource = new UIEventSource(false) public readonly newDataLoadedSignal: UIEventSource = new UIEventSource(undefined) + + private readonly overpassUpdater: OverpassFeatureSource private state: MapState; private readonly relationTracker: RelationsTracker private readonly perLayerHierarchy: Map; + /** + * Keeps track of the age of the loaded data. + * Has one freshness-Calculator for every layer + * @private + */ private readonly freshnesses = new Map(); private readonly oldestAllowedDate: Date; @@ -468,6 +473,7 @@ export default class FeaturePipeline { padToTiles: state.locationControl.map(l => Math.min(15, l.zoom + 1)), relationTracker: this.relationTracker, isActive: useOsmApi.map(b => !b && overpassIsActive.data, [overpassIsActive]), + freshnesses: this.freshnesses, onBboxLoaded: (bbox, date, downloadedLayers, paddedToZoomLevel) => { Tiles.MapRange(bbox.containingTileRange(paddedToZoomLevel), (x, y) => { const tileIndex = Tiles.tile_index(paddedToZoomLevel, x, y) diff --git a/Logic/FeatureSource/TiledFeatureSource/OsmFeatureSource.ts b/Logic/FeatureSource/TiledFeatureSource/OsmFeatureSource.ts index 3c31ff63e..11b6f986f 100644 --- a/Logic/FeatureSource/TiledFeatureSource/OsmFeatureSource.ts +++ b/Logic/FeatureSource/TiledFeatureSource/OsmFeatureSource.ts @@ -12,6 +12,9 @@ import LayoutConfig from "../../../Models/ThemeConfig/LayoutConfig"; import {Or} from "../../Tags/Or"; import {TagsFilter} from "../../Tags/TagsFilter"; +/** + * If a tile is needed (requested via the UIEventSource in the constructor), will download the appropriate tile and pass it via 'handleTile' + */ export default class OsmFeatureSource { public readonly isRunning: UIEventSource = new UIEventSource(false) public readonly downloadedTiles = new Set() diff --git a/Logic/Osm/Overpass.ts b/Logic/Osm/Overpass.ts index e9546566d..df7fe5619 100644 --- a/Logic/Osm/Overpass.ts +++ b/Logic/Osm/Overpass.ts @@ -52,7 +52,6 @@ export class Overpass { } self._relationTracker.RegisterRelations(json) - console.warn("OSMTOGEOJSON:", osmtogeojson) const geojson = osmtogeojson.default(json); const osmTime = new Date(json.osm3s.timestamp_osm_base); return [geojson, osmTime]; diff --git a/Models/Constants.ts b/Models/Constants.ts index 59608abcb..67b06f13e 100644 --- a/Models/Constants.ts +++ b/Models/Constants.ts @@ -2,7 +2,7 @@ import {Utils} from "../Utils"; export default class Constants { - public static vNumber = "0.14.0-alpha-4"; + public static vNumber = "0.14.0-alpha-5"; public static ImgurApiKey = '7070e7167f0a25a' public static readonly mapillary_client_token_v4 = "MLY|4441509239301885|b40ad2d3ea105435bd40c7e76993ae85" diff --git a/Models/ThemeConfig/LayoutConfig.ts b/Models/ThemeConfig/LayoutConfig.ts index 62d71e1fb..7e7fe1e0e 100644 --- a/Models/ThemeConfig/LayoutConfig.ts +++ b/Models/ThemeConfig/LayoutConfig.ts @@ -153,7 +153,7 @@ export default class LayoutConfig { } } this.overpassTimeout = json.overpassTimeout ?? 30 - this.overpassMaxZoom = json.overpassMaxZoom ?? 17 + this.overpassMaxZoom = json.overpassMaxZoom ?? 16 this.osmApiTileSize = json.osmApiTileSize ?? this.overpassMaxZoom + 1 }