Skip to content

Commit 15a6526

Browse files
committed
Address review comments
1 parent 991d3fc commit 15a6526

File tree

2 files changed

+39
-48
lines changed

2 files changed

+39
-48
lines changed

glean/src/core/pings/ping_type.ts

Lines changed: 23 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class PingType implements CommonPingData {
2727
// execute and synchronize with the submission API.
2828
private resolveTestPromiseFunction?: PromiseCallback;
2929
private rejectTestPromiseFunction?: PromiseCallback;
30-
private testValidator?: ValidatorFunction;
30+
private testCallback?: ValidatorFunction;
3131

3232
constructor (meta: CommonPingData) {
3333
this.name = meta.name;
@@ -59,69 +59,55 @@ class PingType implements CommonPingData {
5959
// other dispatched tasks. Unfortunately, this causes a deadlock.
6060
// In order to work around that problem, we kick off validation
6161
// right before the actual submission takes place, through another
62-
// async function (and not through the dispatcher). We then await
63-
// in the dispatched submission task on the related promise, which
64-
// will always resolve due to the use of `finally`.
65-
if (this.testValidator) {
66-
const cleanup = () => {
67-
this.resolveTestPromiseFunction = undefined;
68-
this.rejectTestPromiseFunction = undefined;
69-
this.testValidator = undefined;
70-
};
71-
72-
this.testValidator(reason)
62+
// async function (and not through the dispatcher). After validation
63+
// is complete, regardless of the outcome, the ping submission is
64+
// finally triggered.
65+
if (this.testCallback) {
66+
this.testCallback(reason)
7367
.then(() => {
74-
// Temporarily store the function and then clean up, so that fast consecutive
75-
// calls to `testBeforeNextSubmit` don't fail because things are still set
76-
// after the calling promise is resolved.
77-
const resolver = this.resolveTestPromiseFunction;
78-
cleanup();
79-
80-
this.internalSubmit(reason, resolver);
68+
PingType._private_internalSubmit(this, reason, this.resolveTestPromiseFunction);
8169
})
8270
.catch(e => {
8371
console.error(`There was an error validating "${this.name}" (${reason ?? "no reason"}):`, e);
84-
85-
// Temporarily store the function and then clean up, so that fast consecutive
86-
// calls to `testBeforeNextSubmit` don't fail because things are still set
87-
// after the calling promise is resolved.
88-
const rejecter = this.rejectTestPromiseFunction;
89-
cleanup();
90-
91-
this.internalSubmit(reason, rejecter);
72+
PingType._private_internalSubmit(this, reason, this.rejectTestPromiseFunction);
9273
});
9374
} else {
94-
this.internalSubmit(reason);
75+
PingType._private_internalSubmit(this, reason);
9576
}
9677
}
9778

98-
private internalSubmit(reason?: string, testResolver?: PromiseCallback): void {
79+
private static _private_internalSubmit(instance: PingType, reason?: string, testResolver?: PromiseCallback): void {
9980
Context.dispatcher.launch(async () => {
10081
if (!Context.initialized) {
10182
console.info("Glean must be initialized before submitting pings.");
10283
return;
10384
}
10485

105-
if (!Context.uploadEnabled && !this.isDeletionRequest()) {
86+
if (!Context.uploadEnabled && !instance.isDeletionRequest()) {
10687
console.info("Glean disabled: not submitting pings. Glean may still submit the deletion-request ping.");
10788
return;
10889
}
10990

11091
let correctedReason = reason;
111-
if (reason && !this.reasonCodes.includes(reason)) {
92+
if (reason && !instance.reasonCodes.includes(reason)) {
11293
console.error(`Invalid reason code ${reason} from ${this.name}. Ignoring.`);
11394
correctedReason = undefined;
11495
}
11596

11697
const identifier = generateUUIDv4();
117-
await collectAndStorePing(identifier, this, correctedReason);
98+
await collectAndStorePing(identifier, instance, correctedReason);
11899

119100
// This guarantees that, when running tests, the promise returned by
120101
// `testBeforeNextSubmit` is resolved after the ping is collected: this is
121102
// needed to make sure calling the testing APIs on metrics behave consistently
122103
// if tests run fast.
123104
if (testResolver) {
124105
testResolver();
106+
107+
// Finally clean up!
108+
instance.resolveTestPromiseFunction = undefined;
109+
instance.rejectTestPromiseFunction = undefined;
110+
instance.testCallback = undefined;
125111
}
126112
});
127113
}
@@ -133,22 +119,22 @@ class PingType implements CommonPingData {
133119
*
134120
* TODO: Only allow this function to be called on test mode (depends on Bug 1682771).
135121
*
136-
* @param validatorFn The asynchronous validation function to run in order to validate
137-
* the ping content.
122+
* @param callbackFn The asynchronous validation function to run in order to validate
123+
* the ping content.
138124
*
139125
* @returns A `Promise` resolved when the ping is collected and the validation function
140126
* is executed.
141127
*/
142-
async testBeforeNextSubmit(validatorFn: ValidatorFunction): Promise<void> {
143-
if (this.testValidator) {
128+
async testBeforeNextSubmit(callbackFn: ValidatorFunction): Promise<void> {
129+
if (this.testCallback) {
144130
console.error(`There is an existing test call for ping "${this.name}". Ignoring.`);
145131
return;
146132
}
147133

148134
return new Promise((resolve, reject) => {
149135
this.resolveTestPromiseFunction = resolve;
150136
this.rejectTestPromiseFunction = reject;
151-
this.testValidator = validatorFn;
137+
this.testCallback = callbackFn;
152138
});
153139
}
154140
}

glean/tests/core/pings/index.spec.ts

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,8 @@ describe("PingType", function() {
118118

119119
// We did not call the testing API yet, internals should be undefined.
120120
assert.strictEqual(ping["resolveTestPromiseFunction"], undefined);
121-
assert.strictEqual(ping["testValidator"], undefined);
121+
assert.strictEqual(ping["rejectTestPromiseFunction"], undefined);
122+
assert.strictEqual(ping["testCallback"], undefined);
122123

123124
let validatorRun = false;
124125
const p = ping.testBeforeNextSubmit(r => {
@@ -129,7 +130,8 @@ describe("PingType", function() {
129130

130131
// Internals should be defined after the API was called.
131132
assert.notStrictEqual(ping["resolveTestPromiseFunction"], undefined);
132-
assert.notStrictEqual(ping["testValidator"], undefined);
133+
assert.notStrictEqual(ping["rejectTestPromiseFunction"], undefined);
134+
assert.notStrictEqual(ping["testCallback"], undefined);
133135

134136
ping.submit("test");
135137
await p;
@@ -202,21 +204,21 @@ describe("PingType", function() {
202204
}
203205
});
204206

205-
it("runs a validator multiple times fails when not awaiting", function() {
207+
it("running a validator multiple times fails when not awaiting", function() {
206208
const ping = new PingType({
207209
name: "custom",
208210
includeClientId: true,
209211
sendIfEmpty: false
210212
});
211213

212-
assert.strictEqual(ping["testValidator"], undefined);
214+
assert.strictEqual(ping["testCallback"], undefined);
213215

214216
const testFunction = async () => Promise.resolve();
215217
void ping.testBeforeNextSubmit(testFunction);
216-
assert.strictEqual(ping["testValidator"], testFunction);
218+
assert.strictEqual(ping["testCallback"], testFunction);
217219

218220
void ping.testBeforeNextSubmit(() => Promise.resolve());
219-
assert.strictEqual(ping["testValidator"], testFunction);
221+
assert.strictEqual(ping["testCallback"], testFunction);
220222
});
221223

222224
it("runs a validator that rejects", async function() {
@@ -259,9 +261,13 @@ describe("PingType", function() {
259261
const TEST_NUM_ADDITIONS = 100;
260262

261263
const p = ping.testBeforeNextSubmit(async () => {
264+
// The timeout is here to make the test fail more
265+
// reliably with the current implementation.
262266
await new Promise(r => setTimeout(r, 100));
263267

264268
const value = await counter.testGetValue();
269+
// We don't expect any value to be stored, because the
270+
// calls to 'add' happen after the ping submission.
265271
assert.strictEqual(value, undefined);
266272
validatorRun = true;
267273
});
@@ -288,7 +294,7 @@ describe("PingType", function() {
288294
reasonCodes: ["test"]
289295
});
290296

291-
const counter = new CounterMetricType({
297+
const delayedCounter = new CounterMetricType({
292298
category: "aCategory",
293299
name: "aCounterMetric",
294300
sendInPings: ["custom"],
@@ -310,8 +316,8 @@ describe("PingType", function() {
310316
const p = ping.testBeforeNextSubmit(async () => {
311317
await new Promise(r => setTimeout(r, 100));
312318

313-
assert.strictEqual(await counter.testGetValue(), 37, "Canary must match");
314-
const value = await counter.testGetValue();
319+
assert.strictEqual(await canary.testGetValue(), 37, "Canary must match");
320+
const value = await delayedCounter.testGetValue();
315321
assert.strictEqual(value, undefined);
316322
validatorRun = true;
317323
});
@@ -325,10 +331,9 @@ describe("PingType", function() {
325331

326332
await p;
327333
for (let i = 0; i < TEST_NUM_ADDITIONS; i++) {
328-
counter.add();
334+
delayedCounter.add();
329335
}
330336

331-
332337
assert.ok(validatorRun);
333338
});
334339
});

0 commit comments

Comments
 (0)