Bug 1464346 - Skip RemoteSettings changes that were already processed r?mgoodwin
MozReview-Commit-ID: FBe7JLwA0ld
--- a/services/settings/remote-settings.js
+++ b/services/settings/remote-settings.js
@@ -135,20 +135,22 @@ async function fetchLatestChanges(url, l
// {"data":[
// {
// "host":"kinto-ota.dev.mozaws.net",
// "last_modified":1450717104423,
// "bucket":"blocklists",
// "collection":"certificates"
// }]}
- // Use ETag to obtain a `304 Not modified` when no change occurred.
+ // Use ETag to obtain a `304 Not modified` when no change occurred,
+ // and `?_since` parameter to only keep entries that weren't processed yet.
const headers = {};
if (lastEtag) {
headers["If-None-Match"] = lastEtag;
+ url += `?_since=${lastEtag}`;
}
const response = await fetch(url, {headers});
let changes = [];
// If no changes since last time, go on with empty list of changes.
if (response.status != 304) {
let payload;
try {
--- a/services/settings/test/unit/test_remote_settings_poll.js
+++ b/services/settings/test/unit/test_remote_settings_poll.js
@@ -160,16 +160,60 @@ add_task(async function test_check_up_to
const expectedIncrements = {
[UptakeTelemetry.STATUS.UP_TO_DATE]: 1,
};
checkUptakeTelemetry(startHistogram, endHistogram, expectedIncrements);
});
add_task(clear_state);
+add_task(async function test_success_with_partial_list() {
+ function partialList(request, response) {
+ const entries = [{
+ id: "028261ad-16d4-40c2-a96a-66f72914d125",
+ last_modified: 43,
+ host: "localhost",
+ bucket: "main",
+ collection: "cid-1"
+ }, {
+ id: "98a34576-bcd6-423f-abc2-1d290b776ed8",
+ last_modified: 42,
+ host: "localhost",
+ bucket: "main",
+ collection: "test-collection"
+ }];
+ if (request.queryString == `_since=${encodeURIComponent('"42"')}`) {
+ response.write(JSON.stringify({
+ data: entries.slice(0, 1)
+ }));
+ response.setHeader("ETag", '"43"');
+ } else {
+ response.write(JSON.stringify({
+ data: entries
+ }));
+ response.setHeader("ETag", '"42"');
+ }
+ response.setHeader("Date", (new Date()).toUTCString());
+ response.setStatusLine(null, 200, "OK");
+ }
+ server.registerPathHandler(CHANGES_PATH, partialList);
+
+ const c = RemoteSettings("test-collection");
+ let maybeSyncCount = 0;
+ c.maybeSync = () => { maybeSyncCount++; };
+
+ await RemoteSettings.pollChanges();
+ await RemoteSettings.pollChanges();
+
+ // On the second call, the server does not mention the test-collection
+ // and maybeSync() is not called.
+ Assert.equal(maybeSyncCount, 1, "maybeSync should not be called twice");
+});
+add_task(clear_state);
+
add_task(async function test_server_error() {
const startHistogram = getUptakeTelemetrySnapshot(TELEMETRY_HISTOGRAM_KEY);
// Simulate a server error.
function simulateErrorResponse(request, response) {
response.setHeader("Date", (new Date(3000)).toUTCString());
response.setHeader("Content-Type", "application/json; charset=UTF-8");
response.write(JSON.stringify({