Stopping all local servers when leaving application

This commit is contained in:
ziajka 2019-02-19 15:03:33 +01:00
parent 6759568933
commit 16185d2461
6 changed files with 95 additions and 36 deletions

View File

@ -8,7 +8,6 @@ const isWin = /^win/.test(process.platform);
let runningServers = {}; let runningServers = {};
exports.getLocalServerPath = async () => { exports.getLocalServerPath = async () => {
const distDirectory = path.join(__dirname, 'dist'); const distDirectory = path.join(__dirname, 'dist');
if (!fs.existsSync(distDirectory)) { if (!fs.existsSync(distDirectory)) {
@ -51,13 +50,17 @@ exports.getRunningServers = () => {
return Object.keys(runningServers); return Object.keys(runningServers);
} }
exports.stopAllLocalServers = async () => {
return await stopAll();
}
function getServerArguments(server, overrides) { function getServerArguments(server, overrides) {
let serverArguments = []; let serverArguments = [];
return serverArguments; return serverArguments;
} }
function getChannelForServer(server) { function getChannelForServer(server) {
return `local-server-run-${server.name}`; return `local-server-run-${server.name}`;
} }
function notifyStatus(status) { function notifyStatus(status) {
@ -66,7 +69,7 @@ function notifyStatus(status) {
async function stopAll() { async function stopAll() {
for(var serverName in runningServers) { for(var serverName in runningServers) {
let result, error = await stop(serverName); let result, error = await stop(serverName);
} }
console.log(`Stopped all servers`); console.log(`Stopped all servers`);
} }
@ -159,38 +162,41 @@ async function run(server, options) {
}); });
} }
async function main() { async function main() {
await run({ await run({
name: 'my-local', name: 'my-local',
path: 'c:\\Program Files\\GNS3\\gns3server.EXE', path: 'c:\\Program Files\\GNS3\\gns3server.EXE',
port: 3080 port: 3080
}, { }, {
logStdout: true logStdout: true
}); });
} }
ipcMain.on('local-server-run', async function (event, server) { ipcMain.on('local-server-run', async function (event, server) {
const responseChannel = getChannelForServer(); const responseChannel = getChannelForServer();
await run(server); await run(server);
event.sender.send(responseChannel, { event.sender.send(responseChannel, {
success: true success: true
}); });
});
ipcMain.on('before-quit', async function (event) {
console.log(event);
}); });
if (require.main === module) { if (require.main === module) {
process.on('SIGINT', function() { process.on('SIGINT', function() {
console.log("Caught interrupt signal"); console.log("Caught interrupt signal");
stopAll(); stopAll();
}); });
process.on('unhandledRejection', (reason, promise) => { process.on('unhandledRejection', (reason, promise) => {
console.log(`UnhandledRejection occured 'reason'`); console.log(`UnhandledRejection occured 'reason'`);
process.exit(1); process.exit(1);
}); });
main(); main();
} }

View File

@ -59,13 +59,14 @@ function createWindow () {
} }
// Emitted when the window is closed. // Emitted when the window is closed.
mainWindow.on('closed', function () { mainWindow.on('closed',async function () {
// Dereference the window object, usually you would store windows // Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time // in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element. // when you should delete the corresponding element.
mainWindow = null mainWindow = null
}); });
// forward event to renderer // forward event to renderer
electron.ipcMain.on('local-server-status-events', (event) => { electron.ipcMain.on('local-server-status-events', (event) => {
mainWindow.webContents.send('local-server-status-events', event); mainWindow.webContents.send('local-server-status-events', event);

View File

@ -138,7 +138,10 @@ export class AddServerDialogComponent implements OnInit {
} }
getDefaultLocalServerPath() { getDefaultLocalServerPath() {
return this.electronService.remote.require('./local-server.js').getLocalServerPath(); if(this.electronService.isElectronApp) {
return this.electronService.remote.require('./local-server.js').getLocalServerPath();
}
return;
} }
ngOnInit() { ngOnInit() {

View File

@ -16,7 +16,7 @@ class ElectronServiceMock {
public isElectronApp: boolean; public isElectronApp: boolean;
} }
describe('DefaultLayoutComponent', () => { fdescribe('DefaultLayoutComponent', () => {
let component: DefaultLayoutComponent; let component: DefaultLayoutComponent;
let fixture: ComponentFixture<DefaultLayoutComponent>; let fixture: ComponentFixture<DefaultLayoutComponent>;
let electronServiceMock: ElectronServiceMock; let electronServiceMock: ElectronServiceMock;
@ -89,4 +89,25 @@ describe('DefaultLayoutComponent', () => {
}); });
expect(toaster.errors).toEqual([]); expect(toaster.errors).toEqual([]);
}); });
describe('auto stopping servers', () => {
let event;
beforeEach(() => {
event = new Event('onbeforeunload');
});
it('should close window with no action when not in electron', async () => {
component.shouldStopServersOnClosing = false;
const isClosed = await component.onBeforeUnload(event);
expect(isClosed).toBeUndefined();
});
it('should stop all servers and close window', () => {
component.shouldStopServersOnClosing = true;
const isClosed = component.onBeforeUnload(event);
expect(isClosed).toBeTruthy();
});
});
}); });

View File

@ -1,8 +1,9 @@
import { ElectronService } from 'ngx-electron'; import { ElectronService } from 'ngx-electron';
import { Component, OnInit, ViewEncapsulation, OnDestroy } from '@angular/core'; import { Component, OnInit, ViewEncapsulation, OnDestroy, HostListener } from '@angular/core';
import { ServerManagementService } from '../../services/server-management.service'; import { ServerManagementService } from '../../services/server-management.service';
import { Subscription } from 'rxjs'; import { Subscription } from 'rxjs';
import { ToasterService } from '../../services/toaster.service'; import { ToasterService } from '../../services/toaster.service';
import { ProgressService } from '../../common/progress/progress.service';
@Component({ @Component({
selector: 'app-default-layout', selector: 'app-default-layout',
@ -14,22 +15,42 @@ export class DefaultLayoutComponent implements OnInit, OnDestroy {
public isInstalledSoftwareAvailable = false; public isInstalledSoftwareAvailable = false;
serverStatusSubscription: Subscription; serverStatusSubscription: Subscription;
shouldStopServersOnClosing = true;
constructor( constructor(
private electronService: ElectronService, private electronService: ElectronService,
private serverManagement: ServerManagementService, private serverManagement: ServerManagementService,
private toasterService: ToasterService private toasterService: ToasterService,
private progressService: ProgressService
) {} ) {}
ngOnInit() { ngOnInit() {
this.isInstalledSoftwareAvailable = this.electronService.isElectronApp; this.isInstalledSoftwareAvailable = this.electronService.isElectronApp;
// attach to notification stream when any of running local servers experienced issues
this.serverStatusSubscription = this.serverManagement.serverStatusChanged.subscribe((serverStatus) => { this.serverStatusSubscription = this.serverManagement.serverStatusChanged.subscribe((serverStatus) => {
if(serverStatus.status === 'errored') { if(serverStatus.status === 'errored') {
this.toasterService.error(serverStatus.message); this.toasterService.error(serverStatus.message);
} }
}); });
// stop servers only when in Electron
this.shouldStopServersOnClosing = this.electronService.isElectronApp;
}
@HostListener('window:beforeunload', ['$event'])
async onBeforeUnload($event) {
if(!this.shouldStopServersOnClosing) {
return;
}
$event.preventDefault()
$event.returnValue = false;
this.progressService.activate();
await this.serverManagement.stopAll();
this.shouldStopServersOnClosing = false;
this.progressService.deactivate();
window.close();
return false;
} }
ngOnDestroy() { ngOnDestroy() {

View File

@ -29,15 +29,22 @@ export class ServerManagementService implements OnDestroy {
} }
async start(server: Server) { async start(server: Server) {
await this.electronService.remote.require('./local-server.js').startLocalServer(server); return await this.electronService.remote.require('./local-server.js').startLocalServer(server);
} }
async stop(server: Server) { async stop(server: Server) {
await this.electronService.remote.require('./local-server.js').stopLocalServer(server); return await this.electronService.remote.require('./local-server.js').stopLocalServer(server);
}
async stopAll() {
return await this.electronService.remote.require('./local-server.js').stopAllLocalServers();
} }
getRunningServers() { getRunningServers() {
return this.electronService.remote.require('./local-server.js').getRunningServers(); if(this.electronService.isElectronApp) {
return this.electronService.remote.require('./local-server.js').getRunningServers();
}
return [];
} }
ngOnDestroy() { ngOnDestroy() {