Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

[core] Introduce Source::setMinimumTileUpdateInterval API #16416

Merged
merged 9 commits into from
Apr 20, 2020
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,16 @@

## master

### ✨ New features

- [core] Introduce Source::setMinimumTileUpdateInterval API ([#16416](https://github.com/mapbox/mapbox-gl-native/pull/16416))

The `Source::setMinimumTileUpdateInterval(Duration)` method sets the minimum tile update interval, which is used to throttle the tile update network requests.

The corresponding `Source::getMinimumTileUpdateInterval()` getter is added too.

Default minimum tile update interval value is `Duration::zero()`.

## maps-v1.6.0-rc.1

### ✨ New features
Expand Down
1 change: 1 addition & 0 deletions include/mbgl/storage/resource.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ class Resource {
optional<Timestamp> priorExpires = {};
optional<std::string> priorEtag = {};
std::shared_ptr<const std::string> priorData;
Duration minimumUpdateInterval{Duration::zero()};
};

inline bool Resource::hasLoadingMethod(Resource::LoadingMethod method) const {
Expand Down
19 changes: 15 additions & 4 deletions include/mbgl/style/source.hpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#pragma once

#include <mbgl/util/noncopyable.hpp>
#include <mbgl/util/optional.hpp>
#include <mbgl/util/immutable.hpp>
#include <mbgl/style/types.hpp>
#include <mbgl/util/chrono.hpp>
#include <mbgl/util/immutable.hpp>
#include <mbgl/util/optional.hpp>

#include <mapbox/std/weak.hpp>
#include <mapbox/util/type_wrapper.hpp>
Expand Down Expand Up @@ -40,8 +40,11 @@ struct LayerTypeInfo;
*
* auto vectorSource = std::make_unique<VectorSource>("my-vector-source");
*/
class Source : public mbgl::util::noncopyable {
class Source {
public:
Source(const Source&) = delete;
Source& operator=(const Source&) = delete;

virtual ~Source();

// Check whether this source is of the given subtype.
Expand Down Expand Up @@ -76,6 +79,14 @@ class Source : public mbgl::util::noncopyable {
void setPrefetchZoomDelta(optional<uint8_t> delta) noexcept;
optional<uint8_t> getPrefetchZoomDelta() const noexcept;

// If the given source supports loading tiles from a server,
// sets the minimum tile update interval, which is used to
// throttle the tile update network requests.
Copy link
Contributor

@chloekraw chloekraw Apr 22, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: "suppress" might be a better word here, if we're preventing the update network requests from happening entirely. "throttle" sounds like the request is still made but we're slowing them down.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In our requests are still made but less frequently, is "suppress" still a better word?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, so my thinking is, update network requests that are more frequent than the minimumTileUpdateInterval are suppressed (i.e., not made at all) -- is that accurate?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, we can put it that way, I'll update this comment in #16422

//
// Default value is `Duration::zero()`.
void setMinimumTileUpdateInterval(Duration) noexcept;
Duration getMinimumTileUpdateInterval() const noexcept;

// Sets a limit for how much a parent tile can be overscaled.
//
// When a set of tiles for a current zoom level is being rendered and some of the
Expand Down
55 changes: 30 additions & 25 deletions platform/default/src/mbgl/storage/online_file_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,15 @@ struct OnlineFileRequest {
~OnlineFileRequest();

void networkIsReachableAgain();
void schedule();
void schedule(optional<Timestamp> expires);
void activate();
void schedule(Duration timeout);
void completed(Response);

void setTransformedURL(const std::string& url);
ActorRef<OnlineFileRequest> actor();
void onCancel(std::function<void()>);

Duration getUpdateInterval(optional<Timestamp> expires) const;
OnlineFileSourceThread& impl;
Resource resource;
std::unique_ptr<AsyncRequest> request;
Expand Down Expand Up @@ -100,7 +101,7 @@ class OnlineFileSourceThread {
ref.invoke(&OnlineFileRequest::setTransformedURL, url);
});
} else {
req->schedule();
req->activate();
}
}

Expand Down Expand Up @@ -176,11 +177,11 @@ class OnlineFileSourceThread {
maximumConcurrentRequests = maximumConcurrentRequests_;
}

void setAPIBaseURL(const std::string& t) { apiBaseURL = t; }
std::string getAPIBaseURL() const { return apiBaseURL; }
void setAPIBaseURL(std::string t) { apiBaseURL = std::move(t); }
const std::string& getAPIBaseURL() const { return apiBaseURL; }

void setAccessToken(const std::string& t) { accessToken = t; }
std::string getAccessToken() const { return accessToken; }
void setAccessToken(std::string t) { accessToken = std::move(t); }
const std::string& getAccessToken() const { return accessToken; }

private:
friend struct OnlineFileRequest;
Expand Down Expand Up @@ -383,15 +384,6 @@ OnlineFileRequest::OnlineFileRequest(Resource resource_, Callback callback_, Onl
impl.add(this);
}

void OnlineFileRequest::schedule() {
// Force an immediate first request if we don't have an expiration time.
if (resource.priorExpires) {
schedule(resource.priorExpires);
} else {
schedule(util::now());
}
}

OnlineFileRequest::~OnlineFileRequest() {
if (mailbox) {
mailbox->close();
Expand Down Expand Up @@ -431,17 +423,21 @@ Timestamp interpolateExpiration(const Timestamp& current, optional<Timestamp> pr
return now + std::max<Seconds>(delta, util::CLOCK_SKEW_RETRY_TIMEOUT);
}

void OnlineFileRequest::schedule(optional<Timestamp> expires) {
void OnlineFileRequest::activate() {
// Force an immediate first request if we don't have an expiration time.
Duration timeout = Duration::zero();
if (resource.priorExpires) {
timeout = getUpdateInterval(resource.priorExpires);
}
schedule(timeout);
}

void OnlineFileRequest::schedule(Duration timeout) {
if (impl.isPending(this) || impl.isActive(this)) {
// There's already a request in progress; don't start another one.
return;
}

// If we're not being asked for a forced refresh, calculate a timeout that depends on how many
// consecutive errors we've encountered, and on the expiration time, if present.
Duration timeout = std::min(http::errorRetryTimeout(failedRequestReason, failedRequests, retryAfter),
http::expirationTimeout(std::move(expires), expiredRequests));

if (timeout == Duration::max()) {
return;
}
Expand All @@ -460,6 +456,15 @@ void OnlineFileRequest::schedule(optional<Timestamp> expires) {
});
}

Duration OnlineFileRequest::getUpdateInterval(optional<Timestamp> expires) const {
// Calculate a timeout that depends on how many
// consecutive errors we've encountered, and on the expiration time, if present.
Duration errorRetryTimeout = http::errorRetryTimeout(failedRequestReason, failedRequests, retryAfter);
Duration expirationTimeout =
std::max(http::expirationTimeout(std::move(expires), expiredRequests), resource.minimumUpdateInterval);
return std::min(errorRetryTimeout, expirationTimeout);
}

namespace {

inline std::string sanitizeURL(std::string& url) {
Expand Down Expand Up @@ -519,7 +524,7 @@ void OnlineFileRequest::completed(Response response) {
failedRequestReason = Response::Error::Reason::Success;
}

schedule(response.expires);
schedule(getUpdateInterval(response.expires));

// Calling the callback may result in `this` being deleted. It needs to be done last,
// and needs to make a local copy of the callback to ensure that it remains valid for
Expand All @@ -532,13 +537,13 @@ void OnlineFileRequest::networkIsReachableAgain() {
// We need all requests to fail at least once before we are going to start retrying
// them, and we only immediately restart request that failed due to connection issues.
if (failedRequestReason == Response::Error::Reason::Connection) {
schedule(util::now());
schedule(Duration::zero());
}
}

void OnlineFileRequest::setTransformedURL(const std::string& url) {
resource.url = url;
schedule();
activate();
}

ActorRef<OnlineFileRequest> OnlineFileRequest::actor() {
Expand Down
6 changes: 2 additions & 4 deletions src/mbgl/annotation/render_annotation_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,13 @@ void RenderAnnotationSource::update(Immutable<style::Source::Impl> baseImpl_,
needsRendering,
needsRelayout,
parameters,
SourceType::Annotations,
*baseImpl,
util::tileSize,
// Zoom level 16 is typically sufficient for annotations.
// See https://github.com/mapbox/mapbox-gl-native/issues/10197
{0, 16},
optional<LatLngBounds>{},
[&](const OverscaledTileID& tileID) { return std::make_unique<AnnotationTile>(tileID, parameters); },
baseImpl->getPrefetchZoomDelta(),
baseImpl->getMaxOverscaleFactorForParentTiles());
[&](const OverscaledTileID& tileID) { return std::make_unique<AnnotationTile>(tileID, parameters); });
}

std::unordered_map<std::string, std::vector<Feature>>
Expand Down
27 changes: 12 additions & 15 deletions src/mbgl/renderer/sources/render_custom_geometry_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,21 +40,18 @@ void RenderCustomGeometrySource::update(Immutable<style::Source::Impl> baseImpl_
return;
}

tilePyramid.update(
layers,
needsRendering,
needsRelayout,
parameters,
SourceType::CustomVector,
util::tileSize,
impl().getZoomRange(),
{},
[&](const OverscaledTileID& tileID) {
return std::make_unique<CustomGeometryTile>(
tileID, impl().id, parameters, impl().getTileOptions(), *tileLoader);
},
baseImpl->getPrefetchZoomDelta(),
baseImpl->getMaxOverscaleFactorForParentTiles());
tilePyramid.update(layers,
needsRendering,
needsRelayout,
parameters,
*baseImpl,
util::tileSize,
impl().getZoomRange(),
{},
[&](const OverscaledTileID& tileID) {
return std::make_unique<CustomGeometryTile>(
tileID, impl().id, parameters, impl().getTileOptions(), *tileLoader);
});
}

} // namespace mbgl
25 changes: 11 additions & 14 deletions src/mbgl/renderer/sources/render_geojson_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,20 +106,17 @@ void RenderGeoJSONSource::update(Immutable<style::Source::Impl> baseImpl_,

if (!data_) return;

tilePyramid.update(
layers,
needsRendering,
needsRelayout,
parameters,
SourceType::GeoJSON,
util::tileSize,
impl().getZoomRange(),
optional<LatLngBounds>{},
[&, data_](const OverscaledTileID& tileID) {
return std::make_unique<GeoJSONTile>(tileID, impl().id, parameters, data_);
},
baseImpl->getPrefetchZoomDelta(),
baseImpl->getMaxOverscaleFactorForParentTiles());
tilePyramid.update(layers,
needsRendering,
needsRelayout,
parameters,
*baseImpl,
util::tileSize,
impl().getZoomRange(),
optional<LatLngBounds>{},
[&, data_](const OverscaledTileID& tileID) {
return std::make_unique<GeoJSONTile>(tileID, impl().id, parameters, data_);
});
}

mapbox::util::variant<Value, FeatureCollection>
Expand Down
6 changes: 2 additions & 4 deletions src/mbgl/renderer/sources/render_raster_dem_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,11 @@ void RenderRasterDEMSource::updateInternal(const Tileset& tileset,
needsRendering,
needsRelayout,
parameters,
SourceType::RasterDEM,
*baseImpl,
impl().getTileSize(),
tileset.zoomRange,
tileset.bounds,
[&](const OverscaledTileID& tileID) { return std::make_unique<RasterDEMTile>(tileID, parameters, tileset); },
baseImpl->getPrefetchZoomDelta(),
baseImpl->getMaxOverscaleFactorForParentTiles());
[&](const OverscaledTileID& tileID) { return std::make_unique<RasterDEMTile>(tileID, parameters, tileset); });
algorithm::updateTileMasks(tilePyramid.getRenderedTiles());
}

Expand Down
6 changes: 2 additions & 4 deletions src/mbgl/renderer/sources/render_raster_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,11 @@ void RenderRasterSource::updateInternal(const Tileset& tileset,
needsRendering,
needsRelayout,
parameters,
SourceType::Raster,
*baseImpl,
impl().getTileSize(),
tileset.zoomRange,
tileset.bounds,
[&](const OverscaledTileID& tileID) { return std::make_unique<RasterTile>(tileID, parameters, tileset); },
baseImpl->getPrefetchZoomDelta(),
baseImpl->getMaxOverscaleFactorForParentTiles());
[&](const OverscaledTileID& tileID) { return std::make_unique<RasterTile>(tileID, parameters, tileset); });
algorithm::updateTileMasks(tilePyramid.getRenderedTiles());
}

Expand Down
25 changes: 11 additions & 14 deletions src/mbgl/renderer/sources/render_vector_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,17 @@ void RenderVectorSource::updateInternal(const Tileset& tileset,
const bool needsRendering,
const bool needsRelayout,
const TileParameters& parameters) {
tilePyramid.update(
layers,
needsRendering,
needsRelayout,
parameters,
SourceType::Vector,
util::tileSize,
tileset.zoomRange,
tileset.bounds,
[&](const OverscaledTileID& tileID) {
return std::make_unique<VectorTile>(tileID, baseImpl->id, parameters, tileset);
},
baseImpl->getPrefetchZoomDelta(),
baseImpl->getMaxOverscaleFactorForParentTiles());
tilePyramid.update(layers,
needsRendering,
needsRelayout,
parameters,
*baseImpl,
util::tileSize,
tileset.zoomRange,
tileset.bounds,
[&](const OverscaledTileID& tileID) {
return std::make_unique<VectorTile>(tileID, baseImpl->id, parameters, tileset);
});
}

} // namespace mbgl
Loading