Thanks! I tested your snippet and it does help, but the issue still persists on our side.
The main cause seems to be that Promise.reject() flows into .catch(() => tile.setState(3)), so the tile is marked as error during the retry phase. Also, three retries is often too few under throttling.
I switched to keeping retries going and honoring Retry-After from the response headers (seconds or HTTP-date); otherwise I use a small capped backoff.
map.element.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 MAX_BACKOFF_MS = 15000;
const BASE_BACKOFF_MS = 800;
const sleep = (ms) => new Promise(r => setTimeout(r, ms));
source.setTileLoadFunction((tile, src) => {
const image = tile.getImage();
let attempt = 0;
(async function loadForever() {
while (true) {
attempt++;
try {
const resp = await fetch(src);
if (retryCodes.includes(resp.status)) {
const ra = resp.headers.get(‘Retry-After’);
const raMs = ra
? (isNaN(+ra) ? Math.max(0, Date.parse(ra) - Date.now()) : (+ra * 1000))
: Math.min(BASE_BACKOFF_MS * attempt, MAX_BACKOFF_MS);
await sleep(raMs);
continue;
}
const blob = await resp.blob();
const url = URL.createObjectURL(blob);
image.src = url;
setTimeout(() => URL.revokeObjectURL(url), 5000);
break;
} catch (e) {
const delay = Math.min(BASE_BACKOFF_MS * attempt, MAX_BACKOFF_MS);
await sleep(delay);
}
}
})();
});
}
} , 0);
“”");