-
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
fire sourcedata when source metadata and tiles are loaded #4347
Conversation
I would like to advocate for
Can we eliminate the need for this new event by calling |
@lucaswoj as of now, sources are not 'aware of' / provided a reference to their containing SourceCache. We could either refactor to add this dependency now, or temporarily keep the (private) |
src/source/image_source.js
Outdated
@@ -115,7 +114,8 @@ class ImageSource extends Evented { | |||
centerCoord.column = Math.round(centerCoord.column); | |||
centerCoord.row = Math.round(centerCoord.row); | |||
|
|||
this.minzoom = this.maxzoom = centerCoord.zoom; | |||
// TODO this is making tests fail... what is it for? | |||
// this.minzoom = this.maxzoom = centerCoord.zoom; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lbud would love to know what this line is for. for some reason it's behaving in unexpected ways with the new eventing system and making the canvas source tests fail 😭
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lbud might be able to say more, but my recollection from a while back is that this had to do with 'tricking' the source cache into always requesting the 'right' tile from the ImageSource.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I think @anandthakker is right — because of #3186 (👺) we have to trick the source cache into thinking there's only one appropriate tile to ever request for image + image-inheriting sources. 👀 …
src/source/source_cache.js
Outdated
@@ -475,6 +477,7 @@ class SourceCache extends Evented { | |||
clearTimeout(this._timers[id]); | |||
this._timers[id] = undefined; | |||
} | |||
// TODO should we keep this?? | |||
this._source.fire('data', { tile: tile, coord: tile.coord, dataType: 'tile' }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@lucaswoj @anandthakker do you think we need to fire an event when a tile is removed now that tiledata
is ⚰️? I feel like this isn't useful, but let me know if you disagree.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that this event isn't useful -- if we're not using it anywhere internally, then I'm all for removing it.
What might be useful someday in the future would be a way for users to listen for changes to the list of currently renderable/rendered tile coordinates -- but this doesn't really provide that, and anyway that's a super non-urgent nice-to-have.
In its current state this PR:
TODO:
|
src/source/source_cache.js
Outdated
|
||
// for sources with mutable data, this event fires when the underlying data | ||
// to a source is changed. (i.e. GeoJSONSource#setData and ImageSource#serCoordinates) | ||
if (this._sourceLoaded && e.dataType==="source" && e.update) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great ❤️
Notes/questions:
-
We should update the internal documentation here to reflect these changes to the Source interface contract.
-
Is
e.metadata
too generic a name? I'm not even sure if I like this idea yet, but what about something likee.sourceDataType == 'metadata'
ande.sourceDataType == 'update'
? (Basically havingsourceDataType
be analogous todataType
, but specific to source data events.) -
Is there still a possibility of a race condition here for vector sources? We need
SourceCache#update()
to be called after the TileJSON has loaded. This currently happens either here (for events withe.update
) or viaStyle#_updateSources()
. I'm imagining this problematic timeline:
- map.addSource('mysource', ...) (plus map.addLayer() using
mysource
) => requests TileJSON, marksmap._sourceDirty
. - Next render frame fires; map._sourcesDirty being true leads to
style._updateSources()
... but since the TileJSON is still in flight, we don't get aSourceCache#update()
formysource
. - TileJSON lands => VectorTileSource fires
data
withe.metadata
=>mysource
's SourceCache marks itself_sourceLoaded
. - But now, the actual tiles for
mysource
are not loaded until something else causes_sourcesDirty
flag to be set.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me. Couple of internal-docs-related comments. Other than that, I'll just vote one last time for replacing 'update'
with 'content'
, as that feels like it's clearer / more parallel with 'metadata'
. Approving anyway though so your call 😄
@@ -50,7 +50,7 @@ exports.setType = function (name, type) { | |||
* @param {string} options.type The source type, matching the value of `name` used in {@link Style#addSourceType}. | |||
* @param {Dispatcher} dispatcher A {@link Dispatcher} instance, which can be used to send messages to the workers. | |||
* | |||
* @fires load to indicate source data has been loaded, so that it's okay to call `loadTile` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Small addition: "@fires data with sourceDataType: 'metadata'
to indicate..." -- since that's what source cache now requires of the event fired by Source
.
src/source/geojson_source.js
Outdated
// `update` is included here to prevent a race condition where `Style#_updateSources` is called | ||
// before the TileJSON arrives. this makes sure the tiles needed are loaded once TileJSON arrives | ||
// ref: https://github.com/mapbox/mapbox-gl-js/pull/4347#discussion_r104418088 | ||
this.fire('data', {dataType: 'source', sourceDataType: 'metadata'}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case (GeoJSONSource), the term 'metadata'
is slightly odd, since there isn't really any metadata for geojson sources. As such, it might be more helpful to replace the comment about update
in favor of a comment reminding us that we're firing metadata
to notify the source cache that it's 👍 to ask us for tiles.
(I.e., reading this source, I think it's metadata
that might be confusing; reading the vector/raster sources, it's update
that might be confusing)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh good catch! this should be in vector_tile_source
and not here.
source.on('data', t.end); | ||
source.on('data', (e)=>{ | ||
if (e.sourceDataType === 'metadata') t.end(); | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this test be checking for the 'update'
(or 'content'
) event, rather than 'metadata'
?
c4ca6f4
to
41157c5
Compare
🕐 benchmarks for posterity 🕙 |
* source sorcery ✨ * fix render tests 🎨 * fix unit tests 🔧 * refactor to make everything dependent on 'data' event with new properties * change language, updates tests * use sourceDataType event property 📆 * fixy tests ✅ * 'update' 👉 'content', update tests, docs 📝
This PR does a couple things in order to make the
sourcedata
event more useful for users:sourcedata
when the tilejson loads, but that is not really useful for users, so this PR will fire the event when the source + all tiles in the current viewport are loadedSourceCache#reload
on thesourcedata
event, but that was causing all vector tiles to be loaded twice on initial load of the source, and because this is only meant to reload geojson sources aftersetData
and image/video/canvas sources aftersetCoordinates
I created a new event (😬) to handle this calledsource.update