Skip to content

Commit

Permalink
eclipse-theiaGH-3072: Made the startup-timeout configurable.
Browse files Browse the repository at this point in the history
Adjusted the `appProjectPath` for the backend when running from electron.
Replaced the on the fly created application module loader with a function.

Closes: eclipse-theia#3072.
Closes: eclipse-theia#2624.
Closes: eclipse-theia#2992.

Signed-off-by: Akos Kitta <kittaakos@typefox.io>
  • Loading branch information
Akos Kitta authored and marcdumais-work committed Oct 12, 2018
1 parent 454483c commit f13db55
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,6 @@ const { BackendApplication, CliManager } = require('@theia/core/lib/node');
const { backendApplicationModule } = require('@theia/core/lib/node/backend-application-module');
const { messagingBackendModule } = require('@theia/core/lib/node/messaging/messaging-backend-module');
const { loggerBackendModule } = require('@theia/core/lib/node/logger-backend-module');
const { BackendApplicationConfigProvider } = require('@theia/core/lib/node/backend-application-config-provider');
BackendApplicationConfigProvider.set(${this.prettyStringify(this.pck.props.backend.config)});
const container = new Container();
container.load(backendApplicationModule);
Expand Down Expand Up @@ -73,6 +70,9 @@ module.exports = (port, host) => Promise.resolve()${this.compileBackendModuleImp

protected compileMain(backendModules: Map<string, string>): string {
return `// @ts-check
const { BackendApplicationConfigProvider } = require('@theia/core/lib/node/backend-application-config-provider');
BackendApplicationConfigProvider.set(${this.prettyStringify(this.pck.props.backend.config)});
const serverPath = require('path').resolve(__dirname, 'server');
const address = require('@theia/core/lib/node/cluster/main').default(serverPath);
address.then(function (address) {
Expand Down
27 changes: 23 additions & 4 deletions dev-packages/application-package/src/application-package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,10 +245,16 @@ export class ApplicationPackage {
*/
get resolveModule(): ApplicationModuleResolver {
if (!this._moduleResolver) {
const loaderPath = this.path('.application-module-loader.js');
fs.writeFileSync(loaderPath, 'module.exports = modulePath => require.resolve(modulePath);');
this._moduleResolver = require(loaderPath) as ApplicationModuleResolver;
fs.removeSync(loaderPath);
// If running a bundled electron application, we cannot create a file for the module on the fly.
// https://github.com/theia-ide/theia/issues/2992
if (this.runsInBundledElectron) {
this._moduleResolver = modulePath => require.resolve(modulePath);
} else {
const loaderPath = this.path('.application-module-loader.js');
fs.writeFileSync(loaderPath, 'module.exports = modulePath => require.resolve(modulePath);');
this._moduleResolver = require(loaderPath) as ApplicationModuleResolver;
fs.removeSync(loaderPath);
}
}
return this._moduleResolver!;
}
Expand All @@ -257,4 +263,17 @@ export class ApplicationPackage {
return paths.resolve(this.resolveModule(moduleName + '/package.json'), '..', ...segments);
}

/**
* `true` if the process (or `childProcess.fork`) is an electron process and it was started in production mode from a launcher.
* Otherwise, `false`.
*/
protected get runsInBundledElectron(): boolean {
// tslint:disable-next-line:no-any
const p = process as any;
if (!!p.versions.electron || p.env.ELECTRON_RUN_AS_NODE) {
return p.defaultApp || /node_modules[/]electron[/]/.test(p.execPath);
}
return false;
}

}
10 changes: 10 additions & 0 deletions dev-packages/application-package/src/application-props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,24 @@ export interface ApplicationConfig {
* Application configuration for the frontend. The following properties will be injected into the `index.html`.
*/
export interface FrontendApplicationConfig extends ApplicationConfig {

/**
* The default theme for the application. If not give, defaults to `dark`. If invalid theme is given, also defaults to `dark`.
*/
readonly defaultTheme?: string;

}

/**
* Application configuration for the backend.
*/
export interface BackendApplicationConfig extends ApplicationConfig {

/**
* The default backend startup timeout in milliseconds. If specified here, then this value will be used as opposed to the default timeout.
* If the `--startup-timeout` option is defined, this configuration value has no effect. A negative values will disable the timeout.
* For more details, see [`startupTimeoutOption`](MasterProcess#startupTimeoutOption).
*/
readonly startupTimeout?: number;

}
19 changes: 17 additions & 2 deletions packages/core/src/node/backend-application.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ import * as http from 'http';
import * as https from 'https';
import * as express from 'express';
import * as yargs from 'yargs';
import * as path from 'path';
import * as fs from 'fs-extra';
import { inject, named, injectable } from 'inversify';
import { ILogger, ContributionProvider, MaybePromise } from '../common';
import { CliContribution } from './cli';
import { Deferred } from '../common/promise-util';
import { BackendProcess } from './backend-process';
import * as fs from 'fs-extra';

export const BackendApplicationContribution = Symbol('BackendApplicationContribution');
export interface BackendApplicationContribution {
Expand Down Expand Up @@ -60,7 +61,7 @@ export class BackendApplicationCliContribution implements CliContribution {
conf.option('ssl', { description: 'Use SSL (HTTPS), cert and certkey must also be set', type: 'boolean', default: defaultSSL });
conf.option('cert', { description: 'Path to SSL certificate.', type: 'string' });
conf.option('certkey', { description: 'Path to SSL certificate key.', type: 'string' });
conf.option(appProjectPath, { description: 'Sets the application project directory', default: process.cwd() });
conf.option(appProjectPath, { description: 'Sets the application project directory', default: this.appProjectPath() });
}

setArguments(args: yargs.Arguments): void {
Expand All @@ -71,6 +72,20 @@ export class BackendApplicationCliContribution implements CliContribution {
this.certkey = args.certkey;
this.projectPath = args[appProjectPath];
}

protected appProjectPath(): string {
const cwd = process.cwd();
if (BackendProcess.electron) {
// Check whether we are in bundled application or development mode.
const devMode = process.defaultApp || /node_modules[/]electron[/]/.test(process.execPath);
if (!devMode) {
// In a bundled electron application, the `package.json` is in `resources/app` by default.
return path.join(cwd, 'resources', 'app');
}
}
return cwd;
}

}

/**
Expand Down
6 changes: 5 additions & 1 deletion packages/core/src/node/cluster/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import * as cluster from 'cluster';
import { checkParentAlive } from '../messaging/ipc-protocol';
import { MasterProcess } from './master-process';
import { BackendApplicationConfigProvider } from '../backend-application-config-provider';

checkParentAlive();

Expand All @@ -28,13 +29,16 @@ import yargs = require('yargs');
const args = yargs.option(MasterProcess.startupTimeoutOption, {
description: 'The number of milliseconds to wait for the server to start up. Pass a negative number to disable the timeout.',
type: 'number',
default: 5000
default: BackendApplicationConfigProvider.get().startupTimeout || MasterProcess.defaultStartupTimeoutOption
}).help(false).argv;
const noCluster = args['cluster'] === false;
const isMaster = !noCluster && cluster.isMaster;
const development = process.env.NODE_ENV === 'development';

const startupTimeout = args[MasterProcess.startupTimeoutOption] as number;
if (isMaster) {
console.log(`Starting the master backend process ${Number.isInteger(startupTimeout) && startupTimeout > 0 ? `with ${startupTimeout} (ms)` : 'without a'} timeout.`);
}

if (isMaster && development) {
// https://github.com/Microsoft/vscode/issues/3201
Expand Down
8 changes: 8 additions & 0 deletions packages/core/src/node/cluster/master-process.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,16 @@ class ProcessError extends Error {
export type MasterProcessEvent = 'started' | 'restarted' | 'restarting';
export class MasterProcess extends EventEmitter {

/**
* The option for the backend startup.
*/
static startupTimeoutOption = 'startup-timeout';

/**
* The default timeout (in milliseconds) for the backend startup.
*/
static defaultStartupTimeoutOption = 5_000;

protected serverWorker: ServerWorker | undefined;
protected workerCount: number = 0;

Expand Down

0 comments on commit f13db55

Please sign in to comment.