Gracefully shut down database operations before app exit

This commit is contained in:
Scott Nonnenberg 2018-11-05 11:06:12 -08:00
parent 2822f4ce40
commit 6300256a3e
5 changed files with 161 additions and 11 deletions

74
main.js
View file

@ -329,27 +329,43 @@ function createWindow() {
captureClicks(mainWindow);
// Emitted when the window is about to be closed.
mainWindow.on('close', e => {
// Note: We do most of our shutdown logic here because all windows are closed by
// Electron before the app quits.
mainWindow.on('close', async e => {
console.log('close event', {
readyForShutdown: mainWindow ? mainWindow.readyForShutdown : null,
shouldQuit: windowState.shouldQuit(),
});
// If the application is terminating, just do the default
if (
windowState.shouldQuit() ||
config.environment === 'test' ||
config.environment === 'test-lib'
config.environment === 'test-lib' ||
(mainWindow.readyForShutdown && windowState.shouldQuit())
) {
return;
}
// Prevent the shutdown
e.preventDefault();
mainWindow.hide();
// On Mac, or on other platforms when the tray icon is in use, the window
// should be only hidden, not closed, when the user clicks the close button
if (usingTrayIcon || process.platform === 'darwin') {
e.preventDefault();
mainWindow.hide();
if (
!windowState.shouldQuit() &&
(usingTrayIcon || process.platform === 'darwin')
) {
// toggle the visibility of the show/hide tray icon menu entries
if (tray) {
tray.updateContextMenu();
}
return;
}
await requestShutdown();
mainWindow.readyForShutdown = true;
app.quit();
});
// Emitted when the window is closed.
@ -691,7 +707,51 @@ function setupMenu(options) {
Menu.setApplicationMenu(menu);
}
async function requestShutdown() {
if (!mainWindow || !mainWindow.webContents) {
return;
}
console.log('requestShutdown: Requesting close of mainWindow...');
const request = new Promise((resolve, reject) => {
ipc.once('now-ready-for-shutdown', (_event, error) => {
console.log('requestShutdown: Response received');
if (error) {
return reject(error);
}
return resolve();
});
mainWindow.webContents.send('get-ready-for-shutdown');
// We'll wait two minutes, then force the app to go down. This can happen if someone
// exits the app before we've set everything up in preload() (so the browser isn't
// yet listening for these events), or if there are a whole lot of stacked-up tasks.
// Note: two minutes is also our timeout for SQL tasks in data.js in the browser.
setTimeout(() => {
console.log(
'requestShutdown: Response never received; forcing shutdown.'
);
resolve();
}, 2 * 60 * 1000);
});
try {
await request;
} catch (error) {
console.log(
'requestShutdown error:',
error && error.stack ? error.stack : error
);
}
}
app.on('before-quit', () => {
console.log('before-quit event', {
readyForShutdown: mainWindow ? mainWindow.readyForShutdown : null,
shouldQuit: windowState.shouldQuit(),
});
windowState.markShouldQuit();
});