429 Too Many Requests

The addon map allows to use wms from external source.
But in some cases, the user, by moving or zooming, does too many requests on the WMS endpoint.
OpenLayers get a “429 Too Many Requests” and the tule is not displayed

image

But often the solution is just to call again after a few time.
https://openlayers.org/en/latest/apidoc/module-ol_ImageTile-ImageTile.html

How can I add this code in my app ?
Or maybe could it be added in jmix ?

Hello!

I’ve write a code that sets this function to a WMS source. Could you check that this code resolves the issue? If it works, I would create a GitHub issue to provide the ability to add and configure this function from Maps.

@Subscribe
public void onReady(ReadyEvent event) {
    map.getElement().executeJs("""
            setTimeout(() => {
                const layers = this.olMap.getLayers().getArray();
                for (const layer of layers) {
                    if (layer.constructor.name !== 'TileLayer' || !layer.getSource()) {
                        continue;
                    }
                    const source = layer.getSource();
                    if (source.constructor.name !== 'TileWMS') {
                        continue;
                    }
                    const retryCodes = [408, 429, 500, 502, 503, 504];
                    const retries = {};
                    source.setTileLoadFunction((tile, src) => {
                        const image = tile.getImage();
                        fetch(src)
                          .then((response) => {
                            if (retryCodes.includes(response.status)) {
                              retries[src] = (retries[src] || 0) + 1;
                              if (retries[src] <= 3) {
                                setTimeout(() => tile.load(), retries[src] * 1000);
                              }
                              return Promise.reject();
                            }
                            return response.blob();
                          })
                          .then((blob) => {
                            const imageUrl = URL.createObjectURL(blob);
                            image.src = imageUrl;
                            setTimeout(() => URL.revokeObjectURL(imageUrl), 5000);
                          })
                          .catch(() => tile.setState(3)); // error
                    });
                }
            } , 0);
            """);
}