Skip to content

Commit d3a3d50

Browse files
author
Beatriz Rizental
authored
Merge pull request #970 from brizental/1741898-a-throttling-bug
Bug 1741898 - Don't enqueue multiple stop command on uploader dispatcher
2 parents 36ba85b + 3f892d9 commit d3a3d50

File tree

3 files changed

+37
-9
lines changed

3 files changed

+37
-9
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* Users may provide a folder name through the `VIRTUAL_ENV` environment variable.
77
* If the user is inside an active virtualenv the `VIRTUAL_ENV` environment variable is already set by Python. See: https://docs.python.org/3/library/venv.html.
88
* [#968](https://github.com/mozilla/glean.js/pull/968): Add runtime arguments type checking to `Glean.setUploadEnabled` API.
9+
* [#970](https://github.com/mozilla/glean.js/pull/970): BUGFIX: Guarantee uploading is immediatelly resumed if the uploader has been stopped due to any of the uploading limits being hit.
910

1011
# v0.25.0 (2021-11-15)
1112

glean/src/core/upload/index.ts

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,8 @@ class PingUploader implements PingsDatabaseObserver {
9393
private readonly platformInfo: PlatformInfo;
9494
// The server address we are sending pings to.
9595
private readonly serverEndpoint: string;
96+
// Whether or not uploading is currently stopped due to limits having been hit.
97+
private stopped = false;
9698

9799
constructor(
98100
config: Configuration,
@@ -132,17 +134,21 @@ class PingUploader implements PingsDatabaseObserver {
132134
const { state: rateLimiterState, remainingTime } = this.rateLimiter.getState();
133135
if (rateLimiterState === RateLimiterState.Incrementing) {
134136
this.dispatcher.resume();
137+
this.stopped = false;
135138
} else {
136-
// Stop the dispatcher respecting the order of the dispatcher queue,
137-
// to make sure the Stop command is enqueued _after_ previously enqueued requests.
138-
this.dispatcher.stop(false);
139+
if(!this.stopped) {
140+
// Stop the dispatcher respecting the order of the dispatcher queue,
141+
// to make sure the Stop command is enqueued _after_ previously enqueued requests.
142+
this.dispatcher.stop(false);
143+
this.stopped = true;
144+
}
139145

140146
if (rateLimiterState === RateLimiterState.Throttled) {
141147
log(
142148
LOG_TAG,
143149
[
144-
"Attempted to upload a ping, but Glean is currently throttled.",
145-
`Pending pings will be processed in ${(remainingTime || 0) / 1000}s.`
150+
"Succesfully submitted a ping, but Glean is currently throttled.",
151+
`Pending pings may be uploaded in ${(remainingTime || 0) / 1000}s.`
146152
],
147153
LoggingLevel.Debug
148154
);
@@ -151,9 +157,9 @@ class PingUploader implements PingsDatabaseObserver {
151157
log(
152158
LOG_TAG,
153159
[
154-
"Attempted to upload a ping, but Glean has reached maximum recoverable upload failures",
155-
"for the current uploading window.",
156-
`Will retry in ${(remainingTime || 0) / 1000}s.`
160+
"Succesfully submitted a ping,",
161+
"but Glean has reached maximum recoverable upload failures for the current uploading window.",
162+
`May retry in ${(remainingTime || 0) / 1000}s.`
157163
],
158164
LoggingLevel.Debug
159165
);

glean/tests/unit/core/upload/index.spec.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ const sandbox = sinon.createSandbox();
2525
* @param pingName the name of the ping to fill the database with, defaults to "ping".
2626
* @returns The array of identifiers of the pings added to the database.
2727
*/
28-
async function fillUpPingsDatabase(numPings: number, pingName = "ping"): Promise<string[]> {
28+
async function fillUpPingsDatabase(
29+
numPings: number,
30+
pingName = "ping"
31+
): Promise<string[]> {
2932
const ping = new PingType({
3033
name: pingName,
3134
includeClientId: true,
@@ -246,4 +249,22 @@ describe("PingUploader", function() {
246249
assert.ok("X-Client-Version" in headers);
247250
assert.ok("X-Telemetry-Agent" in headers);
248251
});
252+
253+
it("dispatcher is only once stopped if upload limits are hit and is immediatelly restarted after", async function () {
254+
const httpClient = new CounterUploader();
255+
await Glean.testResetGlean(testAppId, true, { httpClient });
256+
257+
const stopSpy = sandbox.spy(Glean["pingUploader"]["dispatcher"], "stop");
258+
await fillUpPingsDatabase((MAX_PINGS_PER_INTERVAL * 2) - 1);
259+
await Glean["pingUploader"].testBlockOnPingsQueue();
260+
assert.strictEqual(1, stopSpy.callCount);
261+
262+
// Reset the rate limiter so that we are not throttled anymore.
263+
Glean["pingUploader"]["rateLimiter"]["reset"]();
264+
265+
// Add one more ping to the queue so that uploading is resumed.
266+
await fillUpPingsDatabase(1);
267+
await Glean["pingUploader"].testBlockOnPingsQueue();
268+
assert.strictEqual(httpClient.count, MAX_PINGS_PER_INTERVAL * 2);
269+
});
249270
});

0 commit comments

Comments
 (0)