mirror of
https://github.com/arduino/arduino-ide.git
synced 2025-04-19 12:57:17 +00:00
ATL-1137: Show error when could not connect to CLI
Signed-off-by: Akos Kitta <kittaakos@typefox.io>
This commit is contained in:
parent
a3f7b795a0
commit
26a1db3cf8
3
.vscode/launch.json
vendored
3
.vscode/launch.json
vendored
@ -29,9 +29,10 @@
|
||||
"NODE_PRESERVE_SYMLINKS": "1"
|
||||
}
|
||||
},
|
||||
"program": "${workspaceRoot}/electron-app/src-gen/frontend/electron-main.js",
|
||||
"cwd": "${workspaceFolder}/electron-app",
|
||||
"protocol": "inspector",
|
||||
"args": [
|
||||
".",
|
||||
"--log-level=debug",
|
||||
"--hostname=localhost",
|
||||
"--no-cluster",
|
||||
|
@ -6,6 +6,7 @@ import { MessageService } from '@theia/core/lib/common/message-service';
|
||||
import { ApplicationServer } from '@theia/core/lib/common/application-protocol';
|
||||
import { FrontendApplication } from '@theia/core/lib/browser/frontend-application';
|
||||
import { FocusTracker, Widget } from '@theia/core/lib/browser';
|
||||
import { FrontendApplicationStateService } from '@theia/core/lib/browser/frontend-application-state';
|
||||
import { WorkspaceService as TheiaWorkspaceService } from '@theia/workspace/lib/browser/workspace-service';
|
||||
import { ConfigService } from '../../../common/protocol/config-service';
|
||||
import { SketchesService, Sketch, SketchContainer } from '../../../common/protocol/sketches-service';
|
||||
@ -29,10 +30,15 @@ export class WorkspaceService extends TheiaWorkspaceService {
|
||||
@inject(ApplicationServer)
|
||||
protected readonly applicationServer: ApplicationServer;
|
||||
|
||||
@inject(FrontendApplicationStateService)
|
||||
protected readonly appStateService: FrontendApplicationStateService;
|
||||
|
||||
private application: FrontendApplication;
|
||||
private workspaceUri?: Promise<string | undefined>;
|
||||
private version?: string
|
||||
private version?: string;
|
||||
|
||||
async onStart(application: FrontendApplication): Promise<void> {
|
||||
this.application = application;
|
||||
const info = await this.applicationServer.getApplicationInfo();
|
||||
this.version = info?.version;
|
||||
application.shell.onDidChangeCurrentWidget(this.onCurrentWidgetChange.bind(this));
|
||||
@ -62,11 +68,12 @@ export class WorkspaceService extends TheiaWorkspaceService {
|
||||
}
|
||||
return (await this.sketchService.createNewSketch()).uri;
|
||||
} catch (err) {
|
||||
this.appStateService.reachedState('ready').then(() => this.application.shell.update());
|
||||
this.logger.fatal(`Failed to determine the sketch directory: ${err}`)
|
||||
this.messageService.error(
|
||||
'There was an error creating the sketch directory. ' +
|
||||
'See the log for more details. ' +
|
||||
'The application will probably not work as expected.')
|
||||
'The application will probably not work as expected.');
|
||||
return super.getDefaultWorkspaceUri();
|
||||
}
|
||||
})();
|
||||
|
@ -2,7 +2,7 @@ import { injectable, inject, postConstruct, named } from 'inversify';
|
||||
import { ClientDuplexStream } from '@grpc/grpc-js';
|
||||
import { ILogger } from '@theia/core/lib/common/logger';
|
||||
import { deepClone } from '@theia/core/lib/common/objects';
|
||||
import { CoreClientProvider } from './core-client-provider';
|
||||
import { CoreClientAware } from './core-client-provider';
|
||||
import { BoardListWatchReq, BoardListWatchResp } from './cli-protocol/commands/board_pb';
|
||||
import { Board, Port, NotificationServiceServer, AvailablePorts, AttachedBoardsChangeEvent } from '../common/protocol';
|
||||
|
||||
@ -12,15 +12,12 @@ import { Board, Port, NotificationServiceServer, AvailablePorts, AttachedBoardsC
|
||||
* Unlike other services, this is not connection scoped.
|
||||
*/
|
||||
@injectable()
|
||||
export class BoardDiscovery {
|
||||
export class BoardDiscovery extends CoreClientAware {
|
||||
|
||||
@inject(ILogger)
|
||||
@named('discovery')
|
||||
protected discoveryLogger: ILogger;
|
||||
|
||||
@inject(CoreClientProvider)
|
||||
protected readonly coreClientProvider: CoreClientProvider;
|
||||
|
||||
@inject(NotificationServiceServer)
|
||||
protected readonly notificationService: NotificationServiceServer;
|
||||
|
||||
@ -133,23 +130,4 @@ export class BoardDiscovery {
|
||||
return availablePorts;
|
||||
}
|
||||
|
||||
private async coreClient(): Promise<CoreClientProvider.Client> {
|
||||
const coreClient = await new Promise<CoreClientProvider.Client>(async resolve => {
|
||||
const client = await this.coreClientProvider.client();
|
||||
if (client) {
|
||||
resolve(client);
|
||||
return;
|
||||
}
|
||||
const toDispose = this.coreClientProvider.onClientReady(async () => {
|
||||
const client = await this.coreClientProvider.client();
|
||||
if (client) {
|
||||
toDispose.dispose();
|
||||
resolve(client);
|
||||
return;
|
||||
}
|
||||
});
|
||||
});
|
||||
return coreClient;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import * as grpc from '@grpc/grpc-js';
|
||||
import { inject, injectable } from 'inversify';
|
||||
import { Event, Emitter } from '@theia/core/lib/common/event';
|
||||
import { DisposableCollection } from '@theia/core/lib/common/disposable';
|
||||
import { GrpcClientProvider } from './grpc-client-provider';
|
||||
import { ArduinoCoreClient } from './cli-protocol/commands/commands_grpc_pb';
|
||||
import * as commandsGrpcPb from './cli-protocol/commands/commands_grpc_pb';
|
||||
@ -27,7 +28,7 @@ export class CoreClientProvider extends GrpcClientProvider<CoreClientProvider.Cl
|
||||
protected async reconcileClient(port: string | undefined): Promise<void> {
|
||||
if (port && port === this._port) {
|
||||
// No need to create a new gRPC client, but we have to update the indexes.
|
||||
if (this._client) {
|
||||
if (this._client && !(this._client instanceof Error)) {
|
||||
await this.updateIndexes(this._client);
|
||||
this.onClientReadyEmitter.fire();
|
||||
}
|
||||
@ -48,7 +49,7 @@ export class CoreClientProvider extends GrpcClientProvider<CoreClientProvider.Cl
|
||||
let resp: InitResp | undefined = undefined;
|
||||
const stream = client.init(initReq);
|
||||
stream.on('data', (data: InitResp) => resp = data);
|
||||
stream.on('end', () => resolve(resp));
|
||||
stream.on('end', () => resolve(resp!));
|
||||
stream.on('error', err => reject(err));
|
||||
});
|
||||
|
||||
@ -175,20 +176,27 @@ export abstract class CoreClientAware {
|
||||
protected readonly coreClientProvider: CoreClientProvider;
|
||||
|
||||
protected async coreClient(): Promise<CoreClientProvider.Client> {
|
||||
const coreClient = await new Promise<CoreClientProvider.Client>(async resolve => {
|
||||
const coreClient = await new Promise<CoreClientProvider.Client>(async (resolve, reject) => {
|
||||
const handle = (c: CoreClientProvider.Client | Error) => {
|
||||
if (c instanceof Error) {
|
||||
reject(c);
|
||||
} else {
|
||||
resolve(c);
|
||||
}
|
||||
}
|
||||
const client = await this.coreClientProvider.client();
|
||||
if (client) {
|
||||
resolve(client);
|
||||
handle(client);
|
||||
return;
|
||||
}
|
||||
const toDispose = this.coreClientProvider.onClientReady(async () => {
|
||||
const toDispose = new DisposableCollection();
|
||||
toDispose.push(this.coreClientProvider.onClientReady(async () => {
|
||||
const client = await this.coreClientProvider.client();
|
||||
if (client) {
|
||||
toDispose.dispose();
|
||||
resolve(client);
|
||||
return;
|
||||
handle(client);
|
||||
}
|
||||
});
|
||||
toDispose.dispose();
|
||||
}));
|
||||
});
|
||||
return coreClient;
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ export abstract class GrpcClientProvider<C> {
|
||||
protected readonly configService: ConfigServiceImpl;
|
||||
|
||||
protected _port: string | number | undefined;
|
||||
protected _client: C | undefined;
|
||||
protected _client: C | Error | undefined;
|
||||
|
||||
@postConstruct()
|
||||
protected init(): void {
|
||||
@ -28,7 +28,7 @@ export abstract class GrpcClientProvider<C> {
|
||||
this.configService.onConfigChange(updateClient);
|
||||
this.daemon.ready.then(updateClient);
|
||||
this.daemon.onDaemonStopped(() => {
|
||||
if (this._client) {
|
||||
if (this._client && !(this._client instanceof Error)) {
|
||||
this.close(this._client);
|
||||
}
|
||||
this._client = undefined;
|
||||
@ -36,12 +36,12 @@ export abstract class GrpcClientProvider<C> {
|
||||
})
|
||||
}
|
||||
|
||||
async client(): Promise<C | undefined> {
|
||||
async client(): Promise<C | Error | undefined> {
|
||||
try {
|
||||
await this.daemon.ready;
|
||||
return this._client;
|
||||
} catch (error) {
|
||||
return undefined;
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
@ -50,7 +50,7 @@ export abstract class GrpcClientProvider<C> {
|
||||
return; // Nothing to do.
|
||||
}
|
||||
this._port = port;
|
||||
if (this._client) {
|
||||
if (this._client && !(this._client instanceof Error)) {
|
||||
this.close(this._client);
|
||||
this._client = undefined;
|
||||
}
|
||||
@ -60,6 +60,7 @@ export abstract class GrpcClientProvider<C> {
|
||||
this._client = client;
|
||||
} catch (error) {
|
||||
this.logger.error('Could not create client for gRPC.', error)
|
||||
this._client = error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -72,6 +72,9 @@ export class MonitorServiceImpl implements MonitorService {
|
||||
if (!client) {
|
||||
return Status.NOT_CONNECTED;
|
||||
}
|
||||
if (client instanceof Error) {
|
||||
return { message: client.message };
|
||||
}
|
||||
const duplex = client.streamingOpen();
|
||||
this.connection = { duplex, config };
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user