Skip to content

Commit

Permalink
[maps] fix tile errors displayed when layer is no longer using tiles (e…
Browse files Browse the repository at this point in the history
…lastic#172019)

Closes elastic#172013

PR updates TileStatusTracker to clear tile error cache when layer is not
tiled.

---------

Co-authored-by: kibanamachine <[email protected]>
  • Loading branch information
nreese and kibanamachine authored Nov 28, 2023
1 parent a864715 commit d81c367
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ export function getErrorCacheTileKey(canonical: { x: number; y: number; z: numbe
export class TileErrorCache {
private _cache: Record<LayerId, Record<TileKey, TileError>> = {};

public clearLayer(layerId: string, onClear: () => void) {
if (!(layerId in this._cache)) {
return;
}

delete this._cache[layerId];
onClear();
}

public clearTileError(layerId: string | undefined, tileKey: string, onClear: () => void) {
if (!layerId || !(layerId in this._cache)) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type { Map as MbMap, MapSourceDataEvent } from '@kbn/mapbox-gl';
import type { TileError, TileMetaFeature } from '../../../../common/descriptor_types';
import { TileStatusTracker } from './tile_status_tracker';
import { ILayer } from '../../../classes/layers/layer';
import type { IVectorSource } from '../../../classes/sources/vector_source';

class MockMbMap {
public listeners: Array<{ type: string; callback: (e: unknown) => void }> = [];
Expand Down Expand Up @@ -249,6 +250,53 @@ describe('TileStatusTracker', () => {
expect(tileErrorsMap.get('layer2')).toBeUndefined();
});

test('should clear layer tile errors when layer is not tiled', async () => {
const mockMbMap = new MockMbMap();
const layer1 = createMockLayer('layer1', 'layer1Source');

const wrapper = mount(
<TileStatusTracker
mbMap={mockMbMap as unknown as MbMap}
layerList={[layer1]}
onTileStateChange={onTileStateChange}
/>
);

mockMbMap.emit(
'sourcedataloading',
createSourceDataEvent('layer1Source', IN_VIEW_CANONICAL_TILE)
);
mockMbMap.emit('error', {
...createSourceDataEvent('layer1Source', IN_VIEW_CANONICAL_TILE),
error: {
message: 'simulated error',
},
});

// simulate delay. Cache-checking is debounced.
await sleep(300);

expect(tileErrorsMap.get('layer1')?.length).toBe(1);

const geojsonLayer1 = createMockLayer('layer1', 'layer1Source');
geojsonLayer1.getSource = () => {
return {
isESSource() {
return true;
},
isMvt() {
return false;
},
} as unknown as IVectorSource;
};
wrapper.setProps({ layerList: [geojsonLayer1] });

// simulate delay. Cache-checking is debounced.
await sleep(300);

expect(tileErrorsMap.get('layer1')).toBeUndefined();
});

test('should only return tile errors within map zoom', async () => {
const mockMbMap = new MockMbMap();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type { AJAXError, Map as MbMap, MapSourceDataEvent } from '@kbn/mapbox-gl
import type { TileError, TileMetaFeature } from '../../../../common/descriptor_types';
import { SPATIAL_FILTERS_LAYER_ID } from '../../../../common/constants';
import { ILayer } from '../../../classes/layers/layer';
import { isLayerGroup } from '../../../classes/layers/layer_group';
import { IVectorSource } from '../../../classes/sources/vector_source';
import { getTileKey as getCenterTileKey } from '../../../classes/util/geo_tile_utils';
import { boundsToExtent } from '../../../classes/util/maplibre_utils';
Expand Down Expand Up @@ -62,6 +63,24 @@ export class TileStatusTracker extends Component<Props> {
this.props.mbMap.on('moveend', this._onMoveEnd);
}

componentDidUpdate() {
this.props.layerList.forEach((layer) => {
if (isLayerGroup(layer)) {
return;
}

const source = layer.getSource();
if (
source.isESSource() &&
typeof (source as IVectorSource).isMvt === 'function' &&
!(source as IVectorSource).isMvt()
) {
// clear tile cache when layer is not tiled
this._tileErrorCache.clearLayer(layer.getId(), this._updateTileStatusForAllLayers);
}
});
}

componentWillUnmount() {
this._isMounted = false;
this.props.mbMap.off('error', this._onError);
Expand Down

0 comments on commit d81c367

Please sign in to comment.