-
Notifications
You must be signed in to change notification settings - Fork 2.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow developers to clear all tile caches #2633
Comments
related to #1947 |
Per #3715, it may be useful to allow a developer to clear a specific tile rather than all tiles. |
With the new smart ...
style.sources['mySource'].dirty = Math.random();
map.setStyle(style);
... ... which does work. However, after a while these messages start to show up on the console: mapbox-gl.js:103 Uncaught TypeError: Cannot read property 'state' of undefined ... which probably is because this workaround is incompatible with #3944. Works fine with 0.31.0. |
I am the same error. I am not doing that magic to put source dirty. I am using the new smart |
I get the same error ... without calling |
@karlguillotte and @jaapster -- when you see this error in the console, what symptoms do you see in the rendered map? Could you by any chance provide a minimal example that reproduces the error? |
@anandthakker I don't see any symptoms in the rendered map, just the error messages. I'll try and reproduce. |
I actually never saw that error myself and I can not reproduce it. We are using Sentry as error reporting tool and that error has been reported many times. I am sorry, it can be hard for you, I tried to reproduce, but I can not find a way to reproduce. |
I have a datasource consisting of vector tile points. When I currently add a new point on my client, the server updates the relevant tiles. Then it shows up in my client at all layers (when zooming in & out after adding the point) except on the layer on which the point was added as that tile did not refresh yet... So I could use this feature! An ETA maybe? Any suggestions how to deal with my issue in the meantime? |
@averas Did you ever find a working solution for this? |
This is big use case with us as well. We are creating vector tiles and allowing user to modify the shapes. Flow is like
Here , there is no explicit way to tell mapbox that we don't want to use cached layer after update! It will keep on loading old tiles even if we want it to reload layer ! |
@jfirebaugh Ok great thanks - I hope this issue can be pushed forward before 0.43.0 is released it would prevent me and i'm sure others from upgrading at the moment. If it could work like this as well that would be a bonus:
|
Can't upgrade before this is working. |
Uh, any progress on this maybe? |
Mmmh, I just tried and upgraded from version 0.42.2 to 0.49.0 and without changing any code all layer tiles seem to refresh... Quite a surprise there...?! |
I don't know what feature takes care of this, but the issue I described on 12 sept 2017 is solved. Also the precision of the point at different layers is improved somehow. Anyway, I am really happy I upgraded. |
@musicformellons glad to hear this! Although I'm also not sure what change you're seeing. 😅 Just to recap, the current state of this ticket is that we recognize the value of an explicit tile cache invalidation API for cases where you have some external way of knowing that some or all tiles are outdated. The current mechanism of removing and re-adding the source should work but is a cumbersome way to accomplish a re-load. The cache is supposed to respect HTTP |
I have a use case very similar to what @jignesh-techvasu described, and as @ChrisLoer said if the cache respect HTTP Cache-Control headers it would be great. Any new about this issue guys? |
As of v1.1.1 of the library there are some changes with relation to tiles being cached. Mapbox-hosted tiles are cached using the browser's For self hosted tiles, or other non-mapbox hosted tiles, the browser cache will be used and GL-JS will respect that |
@asheemmamoowala Cache-Control/Expires headers are certainly a nice feature, but what if you want any changes that happen to be reflected within a few seconds? Setting Cache-Control to a few seconds would be a way of doing this, but this kind of constant polling/reloading would use a lot of unnecessary bandwidth. It would be really useful if there was some way to manually expire the tiles from within the client. Rather than reloading all of the tile data every few seconds, the client could simply wait for a signal to reload over a WebSocket connection or something similar. |
If the headers on the tile are longer than the TTL for the data, then the browser will cache those URLs and respond to subsequent tile requests with the already cached data. This is part of the browser's default caching behavior.
This can be done using |
I'm familiar with/and have used the cache-busting query earlier based on your suggestion. (Currently only when I refresh/reload the website, in which case it works great)
|
I found a solution by looking through the source code!Essentially: /* my tile source id is "electrical-grid" */
function reloadElectricalGrid(map) {
// Set the tile url to a cache-busting url (Thanks @asheemmamoowala):
map.getSource('electrical-grid').tiles = [ `http://some.url/{z}/{x}/{y}.pbf?dt=${Date.now()}` ]
// Clear the tile cache for a particular source
map.style.sourceCaches['electrical-grid'].clearTiles()
// Load the new tiles for the current viewport (map.transform -> viewport)
map.style.sourceCaches['electrical-grid'].update(map.transform)
// Force a repaint, so that the map will be repainted without movements
map.triggerRepaint()
} NOTEThis causes the layer to visually flash/dissappear for less than a second. This is a clear indication it is working, but this could be a bit annoying if these reloads happen often. This happens because the cache is empty while the new tiles are being fetched. (update is asynchronous) A solution that avoids this "flicker" might be creating a new source, letting it load the new tiles in the background, before somehow switching. |
@bergkvist, Do you think you solution has any difference than remove the source and remove the layer, then add the source and layer back for a certain layer? These two approach seems both present a short gap while the new source is loading. Have you managed to have a seamless source swapping solution yet? |
I'm using the code above by @bergkvist, but noticed that if the tab is in the background, the sourceLayer is not available until the tab is in the foreground again (at least in the browser I'm using, Chrome). In the mean time, if layers that use this sourceLayer are updated (for example added), mapbox throws errors like
and
|
@zhenyanghua I think both approaches should be quite similar. I haven't tried removing the "flash", but what I would look for: Some way of creating an invisible layer, waiting until all the tiles in the viewport have finished loading - and removing the previous layer whilst simultaneously making the new version of the layer visible. @everhardt My guess is that this has something to do with "map.transform" being null or missing some internals when the browser tab is not active. You could try |
@bergkvist There's no change. I've noticed that these two lines are enough to trigger the errors:
If I look at https://developers.google.com/web/updates/2017/03/background_tabs, I see that |
I am using the following code to refresh all tiles when I receive a notification (via a websocket) that the tiles have changed on the server. The refresh is perfectly smooth with no flicker and I haven't seen any problems with refreshing while in the background. The server sets max-age=86400 on the tiles so the code needs to both bust the browser cache (using Cache-Control:max-age=0 in the request) and also set the tile expiration time in the sourceCache. It would be easy to extend this to refresh only a particular set of tiles. Note that using Cache-Control to bust the cache is better than changing the url because it forces the browser to revalidate its cached resource rather than requesting a completely new resource, allowing the server to return 304 if a particular tile has not actually changed (which is usually the case in my app).
And my transformRequest
It would be nice if something like this could be wrapped up into a public refreshTiles method on the source, so that I don't have to worry about implementation details changing in future, but it is only half a dozen lines of code so should be no big deal to rework. |
Hey @rogeraustin, I'm trying to avoid caching map tiles into "mapbox-tiles" cache storage. I tried adding `headers: { 'Cache-Control: 'max-age=0'. However, I get Cors error. I was wondering if there was a way to disable mapbox caching? |
resetting the cache and triggering a repaint doesn't fetch new tiles unfortunately... The view will not change. till the user zooms out or in, but the current zoom level still stays broken regardless. So, the cache reset posted above seems largely ineffective. Also |
After some more testing, this works intermittently. One action will cause a tile re-fetch, then the next won't, and the next will, then the next won't. Even using |
There is (as far as I know) no way of directly modifying or clearing the tile cache. In cases where the client is made aware that the server side vector tiles have been updated, is the supported way of clearing the tile cache simply removing and adding the tile source? Should there be a discrete API method to clear the tile cache?
The text was updated successfully, but these errors were encountered: