Skip to content

Commit

Permalink
added(core): The ["ignoreTileQueryLimit"](https://heremaps.github.io/…
Browse files Browse the repository at this point in the history
…xyz-maps/docs/core.imlprovideroptions.html#ignoretilequerylimit) option has been introduced to mitigate an excessive number of tile requests.

Signed-off-by: Tim Deubler <tim.deubler@here.com>
  • Loading branch information
TerminalTim committed Nov 7, 2023
1 parent 9d6da71 commit 25b43f3
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ export abstract class EditableRemoteTileProvider extends EditableFeatureProvider
provider,
loader,
level: provider.level,
ignoreTileQueryLimit: options.ignoreTileQueryLimit,
preProcessor,
processTileResponse: (tile, data, onDone) => {
if (tile.error) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {Tile} from '../../tile/Tile';
import TileProvider from '../TileProvider/TileProvider';
import {TileLoadDelegator} from './TileLoadDelegator';
import {tileUtils} from '@here/xyz-maps-core';
import {add} from '@here/xyz-maps-common/src/Vec3';

let UNDEF;

Expand All @@ -32,21 +33,23 @@ type TileLoader = any;
export class FixedLevelTileLoadDelegator extends TileLoadDelegator {
private level: number;
private dep: { [quadkey: string]: Tile[] } = {};
private ignoreTileQueryLimit: boolean;

constructor(options: {
level: number,
provider: TileProvider,
loader: TileLoader,
preProcessor?: (input: {
data: any,
ready: (features: any) => void,
tile?: { x: number, y: number, z: number }
}) => (any | Promise<any>),
processTileResponse: (tile: Tile, data: any, onDone: (data: any) => void, xhr: XMLHttpRequest) => any
level: number,
ignoreTileQueryLimit?: boolean,
provider: TileProvider,
loader: TileLoader,
preProcessor?: (input: {
data: any,
ready: (features: any) => void,
tile?: { x: number, y: number, z: number }
}) => (any | Promise<any>),
processTileResponse: (tile: Tile, data: any, onDone: (data: any) => void, xhr: XMLHttpRequest) => any
}) {
super(options);

this.level = options.level;
this.ignoreTileQueryLimit = options.ignoreTileQueryLimit || false;
}

cancel(quadkey: string | Tile, cb?: () => void) {
Expand Down Expand Up @@ -146,6 +149,8 @@ export class FixedLevelTileLoadDelegator extends TileLoadDelegator {
return tile;
};

private blockedLevels: { [level: number]: number } = {};

getTile(quadkey: string, callback: (tile: Tile, error?: any) => void) {
const provider = this.provider;
const storage = provider.storage;
Expand Down Expand Up @@ -177,13 +182,35 @@ export class FixedLevelTileLoadDelegator extends TileLoadDelegator {
}
}

if (quadkey.length != storageLevel) {
const addSimpleOnLoadCallback = (tile, callback) => {
if (!callback) return;
if (tile.onLoaded.indexOf(callback) == -1) {
tile.onLoaded.push(callback);
}
};

const requestedLevel = quadkey.length;

if (requestedLevel != storageLevel) {
tile.loadStartTs = Date.now();

console.log('this.ignoreTileQueryLimit', this.ignoreTileQueryLimit);

if (!this.ignoreTileQueryLimit && storageLevel > requestedLevel) {
if (!this.blockedLevels[requestedLevel]) {
this.blockedLevels[requestedLevel] = 1;
console.warn(`The request for all tiles from level ${requestedLevel} was denied because the TileProvider is set to level ${storageLevel}, leading to an excessive number of tile requests.`);
}

addSimpleOnLoadCallback(tile, callback);
setTimeout(() => this.completeTile(tile, []), 0);
return tile;
}

const loaderTiles = tileUtils.getTilesOfLevel(quadkey, storageLevel);
let loaderTile;
let receiver;

tile.loadStartTs = Date.now();

if (!tile.onLoaded.length) {
receiver = new TileReceiver(tile, loaderTiles);

Expand All @@ -197,7 +224,6 @@ export class FixedLevelTileLoadDelegator extends TileLoadDelegator {
for (let l = 0; l < loaderTiles.length; l++) {
loaderTile = storage.get(loaderTiles[l]);


if (loaderTile == UNDEF) {
loaderTile = provider.getTile(loaderTiles[l], receiver);
} else {// if( loaderTile.onLoaded.indexOf(receiver) == -1 )
Expand All @@ -210,11 +236,7 @@ export class FixedLevelTileLoadDelegator extends TileLoadDelegator {
}
} else {
// attach the callback
if (callback) {
if (tile.onLoaded.indexOf(callback) == -1) {
tile.onLoaded.push(callback);
}
}
addSimpleOnLoadCallback(tile, callback);

if (!tile.loadStartTs) {
tile.loadStartTs = Date.now();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ export class RemoteTileProvider extends FeatureProvider {
provider,
loader,
level: provider.level,
ignoreTileQueryLimit: options.ignoreTileQueryLimit,
preProcessor,
processTileResponse: (tile, data, onDone) => {
if (tile.error) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,5 +77,13 @@ export interface RemoteTileProviderOptions extends TileProviderOptions {
ready: (data) => void
}): { put: GeoJSONFeature[], remove: GeoJSONFeature[] } | Promise<{ put: GeoJSONFeature[], remove: GeoJSONFeature[] }>;

/**
* To prevent an overwhelming volume of tile requests, any requests for zoom levels lower than the provider's setting are disregarded.
* Enabling "ignoreTileQueryLimit" will bypass the tile query limit but may risk browser crashes.
*
* @defaultValue false
*/
ignoreTileQueryLimit?: boolean;

loader?: any;
}

0 comments on commit 25b43f3

Please sign in to comment.