Skip to content

Commit 9222dcf

Browse files
committed
Add --fastStartup flag
When flag is enabled the plugin deployment will be delayed until a frontend is connected. This way the deployment of the plugins cannot slow down the fronend loading time. When the flag is not enabled the performance is not affected. Contributed on behalf of STMicroelectronics Signed-off-by: Simon Graband <sgraband@eclipsesource.com>
1 parent 8b34669 commit 9222dcf

File tree

8 files changed

+75
-11
lines changed

8 files changed

+75
-11
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
[1.22.0 Milestone](https://github.com/eclipse-theia/theia/milestone/30)
55

6+
- [plugin-ext] add --fastStartup flag to wait for frontend start to deploy the plugins. [#](https://github.com/eclipse-theia/theia/pull/) - Contributed on behalf of STMicroelectronics
7+
68
<a name="breaking_changes_1.22.0">[Breaking Changes:](#breaking_changes_1.22.0)</a>
79
- [core] Removed `MarkdownRenderer` class [#10589](https://github.com/eclipse-theia/theia/pull/10589)
810
- [core] `ContextKeyService` is now an interface. Extenders should extend `ContextKeyServiceDummyImpl` [#10546](https://github.com/eclipse-theia/theia/pull/10546)

packages/core/src/browser/frontend-application-module.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ import {
3030
MessageClient,
3131
InMemoryResources,
3232
messageServicePath,
33-
InMemoryTextResourceResolver
33+
InMemoryTextResourceResolver,
34+
ClientConnectionNotifier
3435
} from '../common';
3536
import { KeybindingRegistry, KeybindingContext, KeybindingContribution } from './keybinding';
3637
import { FrontendApplication, FrontendApplicationContribution, DefaultFrontendApplicationContribution } from './frontend-application';
@@ -390,4 +391,8 @@ export const frontendApplicationModule = new ContainerModule((bind, unbind, isBo
390391
child.bind(Coordinate).toConstantValue(position);
391392
return child.get(BreadcrumbPopupContainer);
392393
});
394+
bind(ClientConnectionNotifier).toDynamicValue(ctx => {
395+
const connection = ctx.container.get(WebSocketConnectionProvider);
396+
return connection.createProxy<ClientConnectionNotifier>('clientConnected');
397+
}).inSingletonScope();
393398
});

packages/core/src/browser/frontend-application.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
********************************************************************************/
1616

1717
import { inject, injectable, named } from 'inversify';
18-
import { ContributionProvider, CommandRegistry, MenuModelRegistry, isOSX } from '../common';
18+
import { ContributionProvider, CommandRegistry, MenuModelRegistry, isOSX, ClientConnectionNotifier } from '../common';
1919
import { MaybePromise } from '../common/types';
2020
import { KeybindingRegistry } from './keybinding';
2121
import { Widget } from './widgets';
@@ -129,7 +129,8 @@ export class FrontendApplication {
129129
@inject(ContributionProvider) @named(FrontendApplicationContribution)
130130
protected readonly contributions: ContributionProvider<FrontendApplicationContribution>,
131131
@inject(ApplicationShell) protected readonly _shell: ApplicationShell,
132-
@inject(FrontendApplicationStateService) protected readonly stateService: FrontendApplicationStateService
132+
@inject(FrontendApplicationStateService) protected readonly stateService: FrontendApplicationStateService,
133+
@inject(ClientConnectionNotifier) protected readonly connectionNotifier: ClientConnectionNotifier
133134
) { }
134135

135136
get shell(): ApplicationShell {
@@ -258,9 +259,10 @@ export class FrontendApplication {
258259
const startupElem = this.getStartupIndicator(host);
259260
if (startupElem) {
260261
return new Promise(resolve => {
261-
window.requestAnimationFrame(() => {
262+
window.requestAnimationFrame(async () => {
262263
startupElem.classList.add('theia-hidden');
263264
console.log(`Finished loading frontend application after ${(performance.now() / 1000).toFixed(3)} seconds`);
265+
await this.connectionNotifier.clientConnected();
264266
const preloadStyle = window.getComputedStyle(startupElem);
265267
const transitionDuration = parseCssTime(preloadStyle.transitionDuration, 0);
266268
window.setTimeout(() => {
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/********************************************************************************
2+
* Copyright (C) 2022 STMicroelectronics and others.
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License v. 2.0 which is available at
6+
* http://www.eclipse.org/legal/epl-2.0.
7+
*
8+
* This Source Code may also be made available under the following Secondary
9+
* Licenses when the conditions for such availability set forth in the Eclipse
10+
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
11+
* with the GNU Classpath Exception which is available at
12+
* https://www.gnu.org/software/classpath/license.html.
13+
*
14+
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15+
********************************************************************************/
16+
import { injectable } from 'inversify';
17+
import * as events from 'events';
18+
19+
export const ConnectionTimeout = Symbol('ConnectionTimeout');
20+
21+
@injectable()
22+
export class ClientConnectionNotifier {
23+
24+
static readonly CLIENT_CONNECTED = 'clientConnected';
25+
26+
readonly connectionEvent = new events.EventEmitter();
27+
28+
currentlyConnected = false;
29+
30+
async clientConnected(): Promise<void> {
31+
if (!this.currentlyConnected) {
32+
this.currentlyConnected = true;
33+
this.connectionEvent.emit(ClientConnectionNotifier.CLIENT_CONNECTED);
34+
}
35+
}
36+
37+
}

packages/core/src/common/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export * from './lsp-types';
4040
export * from './contribution-filter';
4141
export * from './nls';
4242
export * from './numbers';
43+
export * from './connection-notifier';
4344

4445
import { environment } from '@theia/application-package/lib/environment';
4546
export { environment };

packages/core/src/node/backend-application-module.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import { ContainerModule, decorate, injectable } from 'inversify';
1818
import { ApplicationPackage } from '@theia/application-package';
1919
import {
2020
bindContributionProvider, MessageService, MessageClient, ConnectionHandler, JsonRpcConnectionHandler,
21-
CommandService, commandServicePath, messageServicePath
21+
CommandService, commandServicePath, messageServicePath, ClientConnectionNotifier
2222
} from '../common';
2323
import { BackendApplication, BackendApplicationContribution, BackendApplicationCliContribution, BackendApplicationServer } from './backend-application';
2424
import { CliManager, CliContribution } from './cli';
@@ -109,4 +109,8 @@ export const backendApplicationModule = new ContainerModule(bind => {
109109

110110
bind(EnvironmentUtils).toSelf().inSingletonScope();
111111
bind(ProcessUtils).toSelf().inSingletonScope();
112+
bind(ConnectionHandler).toDynamicValue(({container}) =>
113+
new JsonRpcConnectionHandler<never>('clientConnected', () => container.get<ClientConnectionNotifier>(ClientConnectionNotifier))
114+
).inSingletonScope();
115+
bind(ClientConnectionNotifier).toSelf().inSingletonScope();
112116
});

packages/core/src/node/backend-application.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ const TIMER_WARNING_THRESHOLD = 50;
3737
const DEFAULT_PORT = environment.electron.is() ? 0 : 3000;
3838
const DEFAULT_HOST = 'localhost';
3939
const DEFAULT_SSL = false;
40+
const DEFAULT_FAST_STARTUP = false;
4041

4142
export const BackendApplicationServer = Symbol('BackendApplicationServer');
4243
/**
@@ -107,6 +108,7 @@ export class BackendApplicationCliContribution implements CliContribution {
107108
cert: string | undefined;
108109
certkey: string | undefined;
109110
projectPath: string;
111+
fastStartup: boolean;
110112

111113
configure(conf: yargs.Argv): void {
112114
conf.option('port', { alias: 'p', description: 'The port the backend server listens on.', type: 'number', default: DEFAULT_PORT });
@@ -115,6 +117,7 @@ export class BackendApplicationCliContribution implements CliContribution {
115117
conf.option('cert', { description: 'Path to SSL certificate.', type: 'string' });
116118
conf.option('certkey', { description: 'Path to SSL certificate key.', type: 'string' });
117119
conf.option(APP_PROJECT_PATH, { description: 'Sets the application project directory', default: this.appProjectPath() });
120+
conf.option('fastStartup', {description: 'delay plugin deployment to decrease startup time', type: 'boolean', default: DEFAULT_FAST_STARTUP});
118121
}
119122

120123
setArguments(args: yargs.Arguments): void {
@@ -124,6 +127,7 @@ export class BackendApplicationCliContribution implements CliContribution {
124127
this.cert = args.cert as string;
125128
this.certkey = args.certkey as string;
126129
this.projectPath = args[APP_PROJECT_PATH] as string;
130+
this.fastStartup = args['fastStartup'] as boolean;
127131
}
128132

129133
protected appProjectPath(): string {

packages/plugin-ext/src/main/node/plugin-deployer-contribution.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,30 @@
1414
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
1515
********************************************************************************/
1616

17-
import { BackendApplicationContribution } from '@theia/core/lib/node';
17+
import { BackendApplicationCliContribution, BackendApplicationContribution } from '@theia/core/lib/node';
18+
import { ClientConnectionNotifier } from '@theia/core/lib/common';
1819
import { injectable, inject } from '@theia/core/shared/inversify';
1920
import { PluginDeployer } from '../../common/plugin-protocol';
20-
import { ILogger } from '@theia/core';
2121

2222
@injectable()
2323
export class PluginDeployerContribution implements BackendApplicationContribution {
2424

25-
@inject(ILogger)
26-
protected readonly logger: ILogger;
27-
2825
@inject(PluginDeployer)
2926
protected pluginDeployer: PluginDeployer;
3027

28+
@inject(ClientConnectionNotifier)
29+
protected readonly connectionNotifier: ClientConnectionNotifier;
30+
31+
@inject(BackendApplicationCliContribution)
32+
protected readonly cliParams: BackendApplicationCliContribution;
33+
3134
initialize(): void {
32-
this.pluginDeployer.start();
35+
if (this.cliParams.fastStartup) {
36+
this.connectionNotifier.connectionEvent.on(ClientConnectionNotifier.CLIENT_CONNECTED, async () => {
37+
this.pluginDeployer.start();
38+
});
39+
} else {
40+
this.pluginDeployer.start();
41+
}
3342
}
3443
}

0 commit comments

Comments
 (0)