[maps] fix tile errors displayed when layer is no longer using tiles (#172019)

Closes https://github.com/elastic/kibana/issues/172013

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

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Nathan Reese 2023-11-28 12:38:58 -07:00 committed by GitHub
parent a8647151cb
commit d81c367850
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 76 additions and 0 deletions

View file

@ -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;

View file

@ -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 }> = [];
@ -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();

View file

@ -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';
@ -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);