Skip to content

Commit 66737d8

Browse files
author
Beatriz Rizental
authored
Merge pull request #534 from ChinYing-Li/bug_1702206
Bug 1702206: Refactor Uploader into class for external use
2 parents 9b91d59 + 78c2e9e commit 66737d8

File tree

11 files changed

+56
-71
lines changed

11 files changed

+56
-71
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
[Full changelog](https://github.com/mozilla/glean.js/compare/v0.18.1...main)
44

5+
* [#534](https://github.com/mozilla/glean.js/pull/534): Expose `Uploader` base class through `@mozilla/glean/<platform>/uploader` entry point.
6+
57
# v0.18.1 (2021-07-22)
68

79
[Full changelog](https://github.com/mozilla/glean.js/compare/v0.18.0...v0.18.1)

glean/package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
"./webext": "./dist/webext/index/webext.js",
1010
"./webext/private/metrics/*": "./dist/webext/core/metrics/types/*.js",
1111
"./webext/private/ping": "./dist/webext/core/pings/ping_type.js",
12-
"./webext/plugins/*": "./dist/webext/plugins/*.js"
12+
"./webext/plugins/*": "./dist/webext/plugins/*.js",
13+
"./webext/uploader": "./dist/webext/core/upload/uploader.js"
1314
},
1415
"typesVersions": {
1516
"*": {
@@ -24,6 +25,9 @@
2425
],
2526
"webext/plugins/*": [
2627
"./dist/webext/types/plugins/*"
28+
],
29+
"webext/uploader": [
30+
"./dist/webext/types/core/upload/uploader.d.ts"
2731
]
2832
}
2933
},

glean/src/core/upload/index.ts

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import log, { LoggingLevel } from "../log.js";
1313
import type { Observer as PingsDatabaseObserver, PingInternalRepresentation } from "../pings/database.js";
1414
import type PingsDatabase from "../pings/database.js";
1515
import type PlatformInfo from "../platform_info.js";
16-
import type { UploadResult } from "./uploader.js";
16+
import { UploadResult } from "./uploader.js";
1717
import type Uploader from "./uploader.js";
1818
import { UploadResultStatus } from "./uploader.js";
1919

@@ -223,7 +223,7 @@ class PingUploader implements PingsDatabaseObserver {
223223
"Attempted to upload a ping, but Glean is not initialized yet. Ignoring.",
224224
LoggingLevel.Warn
225225
);
226-
return { result: UploadResultStatus.RecoverableFailure };
226+
return new UploadResult(UploadResultStatus.RecoverableFailure);
227227
}
228228

229229
try {
@@ -247,9 +247,7 @@ class PingUploader implements PingsDatabaseObserver {
247247
);
248248
// An unrecoverable failure will make sure the offending ping is removed from the queue and
249249
// deleted from the database, which is what we want here.
250-
return {
251-
result: UploadResultStatus.UnrecoverableFailure
252-
};
250+
return new UploadResult(UploadResultStatus.RecoverableFailure);
253251
}
254252
}
255253

glean/src/core/upload/uploader.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,19 @@ export const enum UploadResultStatus {
2828
/**
2929
* The result of an attempted ping upload.
3030
*/
31-
export interface UploadResult {
32-
// The status is only present if `result` is UploadResultStatus.Success
33-
status?: number,
34-
// The status of an upload attempt
35-
result: UploadResultStatus
31+
export class UploadResult {
32+
constructor(
33+
// The status of an upload attempt
34+
readonly result: UploadResultStatus,
35+
// The status is only present if `result` is UploadResultStatus.Success
36+
readonly status?: number
37+
) {}
3638
}
3739

3840
/**
39-
* Uploader interface, actualy uploading logic varies per platform.
41+
* Uploader abstract class, actualy uploading logic varies per platform.
4042
*/
41-
export interface Uploader {
43+
export abstract class Uploader {
4244
/**
4345
* Makes a POST request to a given url, with the given headers and body.
4446
*
@@ -49,7 +51,7 @@ export interface Uploader {
4951
* @param headers Optional header to include in the request
5052
* @returns The status code of the response.
5153
*/
52-
post(url: string, body: string | Uint8Array, headers?: Record<string, string>): Promise<UploadResult>;
54+
abstract post(url: string, body: string | Uint8Array, headers?: Record<string, string>): Promise<UploadResult>;
5355
}
5456

5557
export default Uploader;

glean/src/platform/qt/uploader.ts

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,13 @@
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44

55
import log, { LoggingLevel } from "../../core/log.js";
6-
import type Uploader from "../../core/upload/uploader.js";
7-
import type { UploadResult } from "../../core/upload/uploader.js";
8-
import { DEFAULT_UPLOAD_TIMEOUT_MS, UploadResultStatus } from "../../core/upload/uploader.js";
6+
import Uploader from "../../core/upload/uploader.js";
7+
import { DEFAULT_UPLOAD_TIMEOUT_MS, UploadResultStatus, UploadResult } from "../../core/upload/uploader.js";
98
import { isString } from "../../core/utils.js";
109

1110
const LOG_TAG = "platform.qt.Uploader";
1211

13-
class QtUploader implements Uploader {
12+
class QtUploader extends Uploader {
1413
async post(url: string, body: string | Uint8Array, headers: Record<string, string> = {}): Promise<UploadResult> {
1514
return new Promise((resolve) => {
1615
const xhr = new XMLHttpRequest();
@@ -23,30 +22,21 @@ class QtUploader implements Uploader {
2322

2423
xhr.ontimeout = function(e) {
2524
log(LOG_TAG, ["Timeout while attempting to upload ping.\n", e.type], LoggingLevel.Error);
26-
resolve({
27-
result: UploadResultStatus.RecoverableFailure,
28-
});
25+
resolve(new UploadResult(UploadResultStatus.RecoverableFailure));
2926
};
3027

3128
xhr.onerror = function(e) {
3229
log(LOG_TAG, ["Network rror while attempting to upload ping.\n", e.type], LoggingLevel.Error);
33-
resolve({
34-
result: UploadResultStatus.RecoverableFailure,
35-
});
30+
resolve(new UploadResult(UploadResultStatus.RecoverableFailure));
3631
};
3732

3833
xhr.onabort = function (e) {
3934
log(LOG_TAG, ["The attempt to upload ping is aborted.\n", e.type], LoggingLevel.Error);
40-
resolve({
41-
result: UploadResultStatus.RecoverableFailure,
42-
});
35+
resolve(new UploadResult(UploadResultStatus.RecoverableFailure));
4336
};
4437

4538
xhr.onload = () => {
46-
resolve({
47-
status: xhr.status,
48-
result: UploadResultStatus.Success,
49-
});
39+
resolve(new UploadResult(UploadResultStatus.Success, xhr.status));
5040
};
5141

5242
if (!isString(body)) {

glean/src/platform/test/index.ts

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,14 @@
55
import MockStorage from "../test/storage.js";
66
import type PlatformInfo from "../../core/platform_info.js";
77
import { KnownOperatingSystems } from "../../core/platform_info.js";
8-
import type { UploadResult} from "../../core/upload/uploader.js";
9-
import type Uploader from "../../core/upload/uploader.js";
10-
import { UploadResultStatus } from "../../core/upload/uploader.js";
8+
import Uploader from "../../core/upload/uploader.js";
9+
import { UploadResultStatus, UploadResult } from "../../core/upload/uploader.js";
1110
import type Platform from "../index.js";
1211

13-
class MockUploader implements Uploader {
12+
class MockUploader extends Uploader {
1413
// eslint-disable-next-line @typescript-eslint/no-unused-vars
1514
post(_url: string, _body: string | Uint8Array, _headers?: Record<string, string>): Promise<UploadResult> {
16-
const result: UploadResult = {
17-
result: UploadResultStatus.Success,
18-
status: 200
19-
};
15+
const result = new UploadResult(UploadResultStatus.Success, 200);
2016
return Promise.resolve(result);
2117
}
2218
}

glean/src/platform/webext/uploader.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,12 @@
33
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
44

55
import log, { LoggingLevel } from "../../core/log.js";
6-
import type Uploader from "../../core/upload/uploader.js";
7-
import type { UploadResult } from "../../core/upload/uploader.js";
8-
import { DEFAULT_UPLOAD_TIMEOUT_MS, UploadResultStatus } from "../../core/upload/uploader.js";
6+
import Uploader from "../../core/upload/uploader.js";
7+
import { DEFAULT_UPLOAD_TIMEOUT_MS, UploadResultStatus, UploadResult } from "../../core/upload/uploader.js";
98

109
const LOG_TAG = "platform.webext.Uploader";
1110

12-
class BrowserUploader implements Uploader {
11+
class BrowserUploader extends Uploader {
1312
async post(url: string, body: string | Uint8Array, headers: Record<string, string> = {}): Promise<UploadResult> {
1413
const controller = new AbortController();
1514
const timeout = setTimeout(() => controller.abort(), DEFAULT_UPLOAD_TIMEOUT_MS);
@@ -44,14 +43,11 @@ class BrowserUploader implements Uploader {
4443
}
4544

4645
clearTimeout(timeout);
47-
return { result: UploadResultStatus.RecoverableFailure };
46+
return new UploadResult(UploadResultStatus.RecoverableFailure);
4847
}
4948

5049
clearTimeout(timeout);
51-
return {
52-
result: UploadResultStatus.Success,
53-
status: response.status
54-
};
50+
return new UploadResult(UploadResultStatus.Success, response.status);
5551
}
5652
}
5753

glean/tests/unit/platform/qt/uploader.spec.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import assert from "assert";
77
import sinon from "sinon";
88

99
import QtUploader from "../../../../src/platform/qt/uploader";
10-
import { DEFAULT_UPLOAD_TIMEOUT_MS, UploadResultStatus } from "../../../../src/core/upload/uploader";
10+
import { DEFAULT_UPLOAD_TIMEOUT_MS, UploadResult, UploadResultStatus } from "../../../../src/core/upload/uploader";
1111

1212
describe("Uploader/Qt", function () {
1313
let server: sinon.SinonFakeServer;
@@ -25,9 +25,10 @@ describe("Uploader/Qt", function () {
2525
const response = QtUploader.post("/hello", "");
2626
server.respondWith("POST", "/hello", [status, {}, ""]);
2727
server.respond();
28+
const expectedResponse = new UploadResult(UploadResultStatus.Success, status);
2829
assert.deepStrictEqual(
2930
await response,
30-
{ status: status, result: UploadResultStatus.Success });
31+
expectedResponse);
3132
}
3233
});
3334

@@ -37,8 +38,9 @@ describe("Uploader/Qt", function () {
3738
clock.tick(DEFAULT_UPLOAD_TIMEOUT_MS + 1);
3839
server.respondWith("POST", "/hello", [200, {}, ""]);
3940
server.respond();
41+
const expectedResponse = new UploadResult(UploadResultStatus.RecoverableFailure);
4042
assert.deepStrictEqual(
4143
await response,
42-
{ result: UploadResultStatus.RecoverableFailure });
44+
expectedResponse);
4345
});
4446
});

glean/tests/unit/platform/webext/uploader.spec.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import sinon from "sinon";
88

99
import BrowserUploader from "../../../../src/platform/webext/uploader";
1010
import type { JSONObject } from "../../../../src/core/utils";
11-
import { UploadResultStatus } from "../../../../src/core/upload/uploader";
11+
import { UploadResult, UploadResultStatus } from "../../../../src/core/upload/uploader";
1212

1313
const sandbox = sinon.createSandbox();
1414

@@ -64,17 +64,19 @@ describe("Uploader/browser", function () {
6464
const stub = sandbox.stub(global, "fetch");
6565
for (const [index, status] of [200, 400, 500].entries()) {
6666
stub.onCall(index).returns(Promise.resolve(createResponse(status)));
67+
const expectedResponse = new UploadResult(UploadResultStatus.Success, status);
6768
assert.deepStrictEqual(
6869
await BrowserUploader.post("https://localhost:8080", ""),
69-
{ status: status, result: UploadResultStatus.Success });
70+
expectedResponse);
7071
}
7172
});
7273

7374
it("doesn't throw if upload action throws", async function () {
7475
sandbox.stub(global, "fetch").callsFake(() => Promise.reject());
76+
const expectedResponse = new UploadResult(UploadResultStatus.RecoverableFailure);
7577
assert.deepStrictEqual(
7678
await BrowserUploader.post("https://localhost:8080", ""),
77-
{ result: UploadResultStatus.RecoverableFailure }
79+
expectedResponse
7880
);
7981
});
8082
});

glean/tests/unit/plugins/encryption.spec.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,11 @@ import compactDecrypt from "jose/jwe/compact/decrypt";
1111
import Glean from "../../../src/core/glean";
1212
import PingType from "../../../src/core/pings/ping_type";
1313
import type { JSONObject } from "../../../src/core/utils";
14-
import { WaitableUploader } from "../../../tests/utils";
14+
import { WaitableUploader } from "../../utils";
1515
import PingEncryptionPlugin from "../../../src/plugins/encryption";
1616
import collectAndStorePing, { makePath } from "../../../src/core/pings/maker";
17-
import type { UploadResult} from "../../../src/core/upload/uploader";
18-
import type Uploader from "../../../src/core/upload/uploader";
19-
import { UploadResultStatus } from "../../../src/core/upload/uploader";
17+
import Uploader from "../../../src/core/upload/uploader";
18+
import { UploadResultStatus, UploadResult } from "../../../src/core/upload/uploader";
2019
import CounterMetricType from "../../../src/core/metrics/types/counter";
2120
import { Lifetime } from "../../../src/core/metrics/lifetime";
2221
import { Context } from "../../../src/core/context";
@@ -82,13 +81,10 @@ describe("PingEncryptionPlugin", function() {
8281
let uploadPromiseResolve: (value: UploadSignature) => void;
8382
const uploadPromise = new Promise<UploadSignature>(r => uploadPromiseResolve = r);
8483

85-
class MockUploader implements Uploader {
84+
class MockUploader extends Uploader {
8685
post(url: string, body: string, headers?: Record<string, string>): Promise<UploadResult> {
8786
uploadPromiseResolve({url, body, headers});
88-
const result: UploadResult = {
89-
result: UploadResultStatus.Success,
90-
status: 200
91-
};
87+
const result = new UploadResult(UploadResultStatus.Success, 200);
9288
return Promise.resolve(result);
9389
}
9490
}

0 commit comments

Comments
 (0)