forked from MapComplete/MapComplete
		
	The overpassfeaturesource now only fetches layers that must be updated, fix #599
This commit is contained in:
		
							parent
							
								
									9b88478804
								
							
						
					
					
						commit
						00e5ce0b02
					
				
					 7 changed files with 56 additions and 10 deletions
				
			
		|  | @ -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<number>; | ||||
|         readonly currentBounds: UIEventSource<BBox> | ||||
|     } | ||||
|     private readonly _isActive: UIEventSource<boolean>; | ||||
|     private readonly _isActive: UIEventSource<boolean> | ||||
|     /** | ||||
|      * 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<string, TileFreshnessCalculator>; | ||||
| 
 | ||||
|     constructor( | ||||
|         state: { | ||||
|             readonly locationControl: UIEventSource<Loc>, | ||||
|  | @ -54,13 +65,15 @@ export default class OverpassFeatureSource implements FeatureSource { | |||
|             padToTiles: UIEventSource<number>, | ||||
|             isActive?: UIEventSource<boolean>, | ||||
|             relationTracker: RelationsTracker, | ||||
|             onBboxLoaded?: (bbox: BBox, date: Date, layers: LayerConfig[], zoomlevel: number) => void | ||||
|             onBboxLoaded?: (bbox: BBox, date: Date, layers: LayerConfig[], zoomlevel: number) => void, | ||||
|             freshnesses?: Map<string, TileFreshnessCalculator> | ||||
|         }) { | ||||
| 
 | ||||
|         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 | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
|  | @ -40,18 +40,23 @@ import {ElementStorage} from "../ElementStorage"; | |||
| export default class FeaturePipeline { | ||||
| 
 | ||||
|     public readonly sufficientlyZoomed: UIEventSource<boolean>; | ||||
| 
 | ||||
|     public readonly runningQuery: UIEventSource<boolean>; | ||||
|     public readonly timeout: UIEventSource<number>; | ||||
| 
 | ||||
|     public readonly somethingLoaded: UIEventSource<boolean> = new UIEventSource<boolean>(false) | ||||
|     public readonly newDataLoadedSignal: UIEventSource<FeatureSource> = new UIEventSource<FeatureSource>(undefined) | ||||
| 
 | ||||
|      | ||||
|      | ||||
|     private readonly overpassUpdater: OverpassFeatureSource | ||||
|     private state: MapState; | ||||
|     private readonly relationTracker: RelationsTracker | ||||
|     private readonly perLayerHierarchy: Map<string, TileHierarchyMerger>; | ||||
| 
 | ||||
|     /** | ||||
|      * Keeps track of the age of the loaded data. | ||||
|      * Has one freshness-Calculator for every layer | ||||
|      * @private | ||||
|      */ | ||||
|     private readonly freshnesses = new Map<string, TileFreshnessCalculator>(); | ||||
| 
 | ||||
|     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) | ||||
|  |  | |||
|  | @ -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<boolean> = new UIEventSource<boolean>(false) | ||||
|     public readonly downloadedTiles = new Set<number>() | ||||
|  |  | |||
|  | @ -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]; | ||||
|  |  | |||
|  | @ -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" | ||||
| 
 | ||||
|  |  | |||
|  | @ -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 | ||||
| 
 | ||||
|     } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue