Skip to content

Commit 994ca03

Browse files
committed
Implement shutdown API in Glean singleton
1 parent da5103d commit 994ca03

File tree

2 files changed

+43
-0
lines changed

2 files changed

+43
-0
lines changed

glean/src/core/glean.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,27 @@ class Glean {
413413
});
414414
}
415415

416+
/**
417+
* Finishes executing all pending tasks
418+
* and shutsdown both Glean's dispatcher and ping uploader.
419+
*
420+
* # Important
421+
*
422+
* This is irreversible.
423+
* Only a restart will return Glean back to an idle state.
424+
*
425+
* @returns A promise which resolves once the shutdown is complete.
426+
*/
427+
static async shutdown(): Promise<void> {
428+
// Order here matters!
429+
//
430+
// The main dispatcher needs to be shutdown first,
431+
// because some of its tasks may enqueue new tasks on the ping uploader dispatcher
432+
// and we want these uploading tasks to also be executed prior to complete shutdown.
433+
await Context.dispatcher.shutdown();
434+
await Glean.pingUploader.shutdown();
435+
}
436+
416437
/**
417438
* Sets the current environment.
418439
*

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import TestPlatform from "../../../src/platform/test";
1818
import Plugin from "../../../src/plugins";
1919
import { Lifetime } from "../../../src/core/metrics/lifetime";
2020
import { Context } from "../../../src/core/context";
21+
import { DispatcherState } from "../../../src/core/dispatcher";
2122

2223
class MockPlugin extends Plugin<typeof CoreEvents["afterPingCollection"]> {
2324
constructor() {
@@ -504,4 +505,25 @@ describe("Glean", function() {
504505

505506
assert.strictEqual(TestPlatform.name, Glean.platform.name);
506507
});
508+
509+
it("shutdown correctly shutsdown dispatcher and ping uploader", async function () {
510+
await Glean.shutdown();
511+
assert.strictEqual(Context.dispatcher["state"], DispatcherState.Shutdown);
512+
assert.strictEqual(Glean["pingUploader"]["dispatcher"]["state"], DispatcherState.Shutdown);
513+
});
514+
515+
it("shutdown allows all pending pings to be sent before shutting down uploader", async function() {
516+
const postSpy = sandbox.spy(Glean.platform.uploader, "post");
517+
518+
// `setUploadEnabled` is a task dispatched on the main dispatcher,
519+
// inside this task an uploading task is dispatched to the ping uploader dispatcher.
520+
//
521+
// We want to be sure the ping uploader dispatcher is not shutdown
522+
// before it can execute this final task.
523+
Glean.setUploadEnabled(false);
524+
await Glean.shutdown();
525+
526+
assert.strictEqual(postSpy.callCount, 1);
527+
assert.ok(postSpy.getCall(0).args[0].indexOf(DELETION_REQUEST_PING_NAME) !== -1);
528+
});
507529
});

0 commit comments

Comments
 (0)