зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1552199 - Include records from dump in Remote Settings sync event created data r=glasserc
Differential Revision: https://phabricator.services.mozilla.com/D31599 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
0ac415c764
Коммит
0c8c03610c
|
@ -282,6 +282,7 @@ class RemoteSettingsClient extends EventEmitter {
|
|||
async maybeSync(expectedTimestamp, options = {}) {
|
||||
const { loadDump = true, trigger = "manual" } = options;
|
||||
|
||||
let importedFromDump = [];
|
||||
const startedAt = new Date();
|
||||
let reportStatus = null;
|
||||
try {
|
||||
|
@ -295,7 +296,11 @@ class RemoteSettingsClient extends EventEmitter {
|
|||
// cold start.
|
||||
if (!collectionLastModified && loadDump) {
|
||||
try {
|
||||
await RemoteSettingsWorker.importJSONDump(this.bucketName, this.collectionName);
|
||||
const imported = await RemoteSettingsWorker.importJSONDump(this.bucketName, this.collectionName);
|
||||
// The worker only returns an integer. List the imported records to build the sync event.
|
||||
if (imported > 0) {
|
||||
({ data: importedFromDump } = await kintoCollection.list());
|
||||
}
|
||||
collectionLastModified = await kintoCollection.db.getLastModified();
|
||||
} catch (e) {
|
||||
// Report but go-on.
|
||||
|
@ -337,6 +342,9 @@ class RemoteSettingsClient extends EventEmitter {
|
|||
// With SERVER_WINS, there cannot be any conflicts, but don't silent it anyway.
|
||||
throw new Error("Synced failed");
|
||||
}
|
||||
// The records imported from the dump should be considered as "created" for the
|
||||
// listeners.
|
||||
syncResult.created = importedFromDump.concat(syncResult.created);
|
||||
} catch (e) {
|
||||
if (e instanceof RemoteSettingsClient.InvalidSignatureError) {
|
||||
// Signature verification failed during synchronization.
|
||||
|
|
|
@ -51,39 +51,12 @@ function run_test() {
|
|||
clientWithDump = RemoteSettings("language-dictionaries");
|
||||
clientWithDump.verifySignature = false;
|
||||
|
||||
// Setup server fake responses.
|
||||
function handleResponse(request, response) {
|
||||
try {
|
||||
const sample = getSampleResponse(request, server.identity.primaryPort);
|
||||
if (!sample) {
|
||||
do_throw(`unexpected ${request.method} request for ${request.path}?${request.queryString}`);
|
||||
}
|
||||
|
||||
response.setStatusLine(null, sample.status.status,
|
||||
sample.status.statusText);
|
||||
// send the headers
|
||||
for (let headerLine of sample.sampleHeaders) {
|
||||
let headerElements = headerLine.split(":");
|
||||
response.setHeader(headerElements[0], headerElements[1].trimLeft());
|
||||
}
|
||||
response.setHeader("Date", (new Date()).toUTCString());
|
||||
|
||||
const body = typeof sample.responseBody == "string" ? sample.responseBody
|
||||
: JSON.stringify(sample.responseBody);
|
||||
response.write(body);
|
||||
response.finish();
|
||||
} catch (e) {
|
||||
info(e);
|
||||
}
|
||||
}
|
||||
const configPath = "/v1/";
|
||||
const changesPath = "/v1/buckets/monitor/collections/changes/records";
|
||||
const metadataPath = "/v1/buckets/main/collections/password-fields";
|
||||
const recordsPath = "/v1/buckets/main/collections/password-fields/records";
|
||||
server.registerPathHandler(configPath, handleResponse);
|
||||
server.registerPathHandler(changesPath, handleResponse);
|
||||
server.registerPathHandler(metadataPath, handleResponse);
|
||||
server.registerPathHandler(recordsPath, handleResponse);
|
||||
server.registerPathHandler("/v1/", handleResponse);
|
||||
server.registerPathHandler("/v1/buckets/monitor/collections/changes/records", handleResponse);
|
||||
server.registerPathHandler("/v1/buckets/main/collections/password-fields", handleResponse);
|
||||
server.registerPathHandler("/v1/buckets/main/collections/password-fields/records", handleResponse);
|
||||
server.registerPathHandler("/v1/buckets/main/collections/language-dictionaries", handleResponse);
|
||||
server.registerPathHandler("/v1/buckets/main/collections/language-dictionaries/records", handleResponse);
|
||||
server.registerPathHandler("/fake-x5u", handleResponse);
|
||||
|
||||
run_next_test();
|
||||
|
@ -104,6 +77,22 @@ add_task(async function test_records_obtained_from_server_are_stored_in_db() {
|
|||
});
|
||||
add_task(clear_state);
|
||||
|
||||
add_task(async function test_records_from_dump_are_listed_as_created_in_event() {
|
||||
let received;
|
||||
clientWithDump.on("sync", ({ data }) => received = data);
|
||||
// Use a timestamp superior to latest record in dump.
|
||||
const timestamp = 5000000000000; // Fri Jun 11 2128
|
||||
|
||||
await clientWithDump.maybeSync(timestamp);
|
||||
|
||||
const list = await clientWithDump.get();
|
||||
ok(list.length > 20, "The dump was loaded");
|
||||
equal(received.created[received.created.length - 1].id, "xx", "Last record comes from the sync.");
|
||||
equal(received.created.length, list.length, "The list of created records contains the dump");
|
||||
equal(received.current.length, received.created.length);
|
||||
});
|
||||
add_task(clear_state);
|
||||
|
||||
add_task(async function test_records_can_have_local_fields() {
|
||||
const c = RemoteSettings("password-fields", { localFields: ["accepted"] });
|
||||
await c.maybeSync(2000);
|
||||
|
@ -487,7 +476,30 @@ add_task(async function test_inspect_changes_the_list_when_bucket_pref_is_change
|
|||
});
|
||||
add_task(clear_state);
|
||||
|
||||
// get a response for a given request from sample data
|
||||
function handleResponse(request, response) {
|
||||
try {
|
||||
const sample = getSampleResponse(request, server.identity.primaryPort);
|
||||
if (!sample) {
|
||||
do_throw(`unexpected ${request.method} request for ${request.path}?${request.queryString}`);
|
||||
}
|
||||
|
||||
response.setStatusLine(null, sample.status.status, sample.status.statusText);
|
||||
// send the headers
|
||||
for (let headerLine of sample.sampleHeaders) {
|
||||
let headerElements = headerLine.split(":");
|
||||
response.setHeader(headerElements[0], headerElements[1].trimLeft());
|
||||
}
|
||||
response.setHeader("Date", (new Date()).toUTCString());
|
||||
|
||||
const body = typeof sample.responseBody == "string" ? sample.responseBody
|
||||
: JSON.stringify(sample.responseBody);
|
||||
response.write(body);
|
||||
response.finish();
|
||||
} catch (e) {
|
||||
info(e);
|
||||
}
|
||||
}
|
||||
|
||||
function getSampleResponse(req, port) {
|
||||
const responses = {
|
||||
"OPTIONS": {
|
||||
|
@ -741,6 +753,43 @@ wNuvFqc=
|
|||
}],
|
||||
},
|
||||
},
|
||||
"GET:/v1/buckets/main/collections/language-dictionaries": {
|
||||
"sampleHeaders": [
|
||||
"Access-Control-Allow-Origin: *",
|
||||
"Access-Control-Expose-Headers: Retry-After, Content-Length, Alert, Backoff",
|
||||
"Content-Type: application/json; charset=UTF-8",
|
||||
"Server: waitress",
|
||||
"Etag: \"1234\"",
|
||||
],
|
||||
"status": { status: 200, statusText: "OK" },
|
||||
"responseBody": JSON.stringify({
|
||||
"data": {
|
||||
"id": "language-dictionaries",
|
||||
"last_modified": 1234,
|
||||
"signature": {
|
||||
"signature": "xyz",
|
||||
"x5u": `http://localhost:${port}/fake-x5u`,
|
||||
},
|
||||
},
|
||||
}),
|
||||
},
|
||||
"GET:/v1/buckets/main/collections/language-dictionaries/records": {
|
||||
"sampleHeaders": [
|
||||
"Access-Control-Allow-Origin: *",
|
||||
"Access-Control-Expose-Headers: Retry-After, Content-Length, Alert, Backoff",
|
||||
"Content-Type: application/json; charset=UTF-8",
|
||||
"Server: waitress",
|
||||
"Etag: \"5000000000000\"",
|
||||
],
|
||||
"status": { status: 200, statusText: "OK" },
|
||||
"responseBody": {
|
||||
"data": [{
|
||||
"id": "xx",
|
||||
"last_modified": 5000000000000,
|
||||
"dictionaries": ["xx-XX@dictionaries.addons.mozilla.org"],
|
||||
}],
|
||||
},
|
||||
},
|
||||
"GET:/v1/buckets/monitor/collections/changes/records?collection=no-mocked-responses&bucket=main": {
|
||||
"sampleHeaders": [
|
||||
"Access-Control-Allow-Origin: *",
|
||||
|
|
Загрузка…
Ссылка в новой задаче