forked from mirrors/gecko-dev
Bug 1873229 - Add a shutdown blocker for NotificationDB r=asuth
We have two very similar modules right now but with some different behavior: 1. With MOZ_NEW_NOTIFICATION_STORE=True we save the DB via kvstore, which has no shutdown blocker and causes crash when being too late. 2. With MOZ_NEW_NOTIFICATION_STORE=False we save the DB via IOUtils, which does have its shutdown blocker. Either way there's no shutdown blocker that ensures processing the whole task queue, which poses risk of losing notification data, which is required when notification is clicked by user. This patch adds that. Unfortunately we don't have a test here as I don't think we have infra for shutdown blocking test. Differential Revision: https://phabricator.services.mozilla.com/D200042
This commit is contained in:
parent
8641d3ff30
commit
8a3bc14ca4
2 changed files with 51 additions and 0 deletions
|
|
@ -10,6 +10,7 @@ function debug(s) {
|
|||
const lazy = {};
|
||||
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
AsyncShutdown: "resource://gre/modules/AsyncShutdown.sys.mjs",
|
||||
KeyValueService: "resource://gre/modules/kvstore.sys.mjs",
|
||||
});
|
||||
|
||||
|
|
@ -37,6 +38,11 @@ var NotificationDB = {
|
|||
// of the load via its resolution.
|
||||
_loadPromise: null,
|
||||
|
||||
// A promise that resolves once the ongoing task queue has been drained.
|
||||
// The value will be reset when the queue starts again.
|
||||
_queueDrainedPromise: null,
|
||||
_queueDrainedPromiseResolve: null,
|
||||
|
||||
init() {
|
||||
if (this._shutdownInProgress) {
|
||||
return;
|
||||
|
|
@ -47,6 +53,13 @@ var NotificationDB = {
|
|||
|
||||
Services.obs.addObserver(this, "xpcom-shutdown");
|
||||
this.registerListeners();
|
||||
|
||||
// This assumes that nothing will queue a new task at profile-change-teardown phase,
|
||||
// potentially replacing the _queueDrainedPromise if there was no existing task run.
|
||||
lazy.AsyncShutdown.profileChangeTeardown.addBlocker(
|
||||
"NotificationDB: Need to make sure that all notification messages are processed",
|
||||
() => this._queueDrainedPromise
|
||||
);
|
||||
},
|
||||
|
||||
registerListeners() {
|
||||
|
|
@ -261,6 +274,9 @@ var NotificationDB = {
|
|||
debug("Task queue was not running, starting now...");
|
||||
}
|
||||
this.runNextTask();
|
||||
this._queueDrainedPromise = new Promise(resolve => {
|
||||
this._queueDrainedPromiseResolve = resolve;
|
||||
});
|
||||
}
|
||||
|
||||
return promise;
|
||||
|
|
@ -272,6 +288,13 @@ var NotificationDB = {
|
|||
debug("No more tasks to run, queue depleted");
|
||||
}
|
||||
this.runningTask = null;
|
||||
if (this._queueDrainedPromiseResolve) {
|
||||
this._queueDrainedPromiseResolve();
|
||||
} else if (DEBUG) {
|
||||
debug(
|
||||
"_queueDrainedPromiseResolve was null somehow, no promise to resolve"
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.runningTask = this.tasks.shift();
|
||||
|
|
|
|||
|
|
@ -7,6 +7,12 @@ function debug(s) {
|
|||
dump("-*- NotificationDB component: " + s + "\n");
|
||||
}
|
||||
|
||||
const lazy = {};
|
||||
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
AsyncShutdown: "resource://gre/modules/AsyncShutdown.sys.mjs",
|
||||
});
|
||||
|
||||
const NOTIFICATION_STORE_DIR = PathUtils.profileDir;
|
||||
const NOTIFICATION_STORE_PATH = PathUtils.join(
|
||||
NOTIFICATION_STORE_DIR,
|
||||
|
|
@ -23,6 +29,11 @@ var NotificationDB = {
|
|||
// Ensure we won't call init() while xpcom-shutdown is performed
|
||||
_shutdownInProgress: false,
|
||||
|
||||
// A promise that resolves once the ongoing task queue has been drained.
|
||||
// The value will be reset when the queue starts again.
|
||||
_queueDrainedPromise: null,
|
||||
_queueDrainedPromiseResolve: null,
|
||||
|
||||
init() {
|
||||
if (this._shutdownInProgress) {
|
||||
return;
|
||||
|
|
@ -37,6 +48,13 @@ var NotificationDB = {
|
|||
|
||||
Services.obs.addObserver(this, "xpcom-shutdown");
|
||||
this.registerListeners();
|
||||
|
||||
// This assumes that nothing will queue a new task at profile-change-teardown phase,
|
||||
// potentially replacing the _queueDrainedPromise if there was no existing task run.
|
||||
lazy.AsyncShutdown.profileChangeTeardown.addBlocker(
|
||||
"NotificationDB: Need to make sure that all notification messages are processed",
|
||||
() => this._queueDrainedPromise
|
||||
);
|
||||
},
|
||||
|
||||
registerListeners() {
|
||||
|
|
@ -251,6 +269,9 @@ var NotificationDB = {
|
|||
debug("Task queue was not running, starting now...");
|
||||
}
|
||||
this.runNextTask();
|
||||
this._queueDrainedPromise = new Promise(resolve => {
|
||||
this._queueDrainedPromiseResolve = resolve;
|
||||
});
|
||||
}
|
||||
|
||||
return promise;
|
||||
|
|
@ -262,6 +283,13 @@ var NotificationDB = {
|
|||
debug("No more tasks to run, queue depleted");
|
||||
}
|
||||
this.runningTask = null;
|
||||
if (this._queueDrainedPromiseResolve) {
|
||||
this._queueDrainedPromiseResolve();
|
||||
} else if (DEBUG) {
|
||||
debug(
|
||||
"_queueDrainedPromiseResolve was null somehow, no promise to resolve"
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.runningTask = this.tasks.shift();
|
||||
|
|
|
|||
Loading…
Reference in a new issue