Skip to content

Commit c7f2f4f

Browse files
author
Akos Kitta
committed
asynchronous core and lib index update.
Signed-off-by: Akos Kitta <[email protected]>
1 parent 68afacf commit c7f2f4f

File tree

1 file changed

+91
-17
lines changed

1 file changed

+91
-17
lines changed

arduino-ide-extension/src/node/core-client-provider.ts

Lines changed: 91 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import {
2121
import * as commandsGrpcPb from './cli-protocol/cc/arduino/cli/commands/v1/commands_grpc_pb';
2222
import { NotificationServiceServer } from '../common/protocol';
2323
import { Deferred } from '@theia/core/lib/common/promise-util';
24+
import { Status as RpcStatus } from './cli-protocol/google/rpc/status_pb';
2425

2526
@injectable()
2627
export class CoreClientProvider extends GrpcClientProvider<CoreClientProvider.Client> {
@@ -66,23 +67,41 @@ export class CoreClientProvider extends GrpcClientProvider<CoreClientProvider.Cl
6667
}
6768

6869
@postConstruct()
69-
protected override async init(): Promise<void> {
70+
protected override init(): void {
7071
this.daemon.getPort().then(async (port) => {
7172
// First create the client and the instance synchronously
7273
// and notify client is ready.
7374
// TODO: Creation failure should probably be handled here
74-
await this.reconcileClient(port).then(() => {
75-
this._created.resolve();
76-
});
75+
await this.reconcileClient(port); // create instance
76+
this._created.resolve();
77+
78+
// Normal startup workflow:
79+
// 1. create instance,
80+
// 2. init instance,
81+
// 3. update indexes asynchronously.
7782

78-
// If client has been created correctly update indexes and initialize
79-
// its instance by loading platforms and cores.
83+
// First startup workflow:
84+
// 1. create instance,
85+
// 2. update indexes and wait,
86+
// 3. init instance.
8087
if (this._client && !(this._client instanceof Error)) {
81-
await this.updateIndexes(this._client)
82-
.then(this.initInstance)
83-
.then(() => {
88+
try {
89+
await this.initInstance(this._client);
90+
this._initialized.resolve();
91+
this.updateIndex(this._client); // Update the indexes asynchronously
92+
} catch (error: unknown) {
93+
if (
94+
this.isPackageIndexMissingError(error) ||
95+
this.isDiscoveryNotFoundError(error)
96+
) {
97+
await this.updateIndexes(this._client);
98+
await this.initInstance(this._client);
99+
console.log('fooo');
84100
this._initialized.resolve();
85-
});
101+
} else {
102+
throw error;
103+
}
104+
}
86105
}
87106
});
88107

@@ -95,6 +114,41 @@ export class CoreClientProvider extends GrpcClientProvider<CoreClientProvider.Cl
95114
});
96115
}
97116

117+
private isPackageIndexMissingError(error: unknown): boolean {
118+
const assert = (message: string) =>
119+
message.includes('loading json index file');
120+
// https://github.com/arduino/arduino-cli/blob/f0245bc2da6a56fccea7b2c9ea09e85fdcc52cb8/arduino/cores/packagemanager/package_manager.go#L247
121+
return this.isRpcStatusError(error, assert);
122+
}
123+
124+
private isDiscoveryNotFoundError(error: unknown): boolean {
125+
const assert = (message: string) =>
126+
message.includes('discovery') &&
127+
(message.includes('not found') || message.includes('not installed'));
128+
// https://github.com/arduino/arduino-cli/blob/f0245bc2da6a56fccea7b2c9ea09e85fdcc52cb8/arduino/cores/packagemanager/loader.go#L740
129+
// https://github.com/arduino/arduino-cli/blob/f0245bc2da6a56fccea7b2c9ea09e85fdcc52cb8/arduino/cores/packagemanager/loader.go#L744
130+
return this.isRpcStatusError(error, assert);
131+
}
132+
133+
private isCancelError(error: unknown): boolean {
134+
return (
135+
error instanceof Error &&
136+
error.message.toLocaleLowerCase().includes('cancelled on client')
137+
);
138+
}
139+
140+
// Final error codes are not yet defined by the CLI. Hence, we do string match in the error message.
141+
private isRpcStatusError(
142+
error: unknown,
143+
assert: (message: string) => boolean
144+
) {
145+
if (error instanceof RpcStatus) {
146+
const { message } = RpcStatus.toObject(false, error);
147+
return assert(message.toLocaleLowerCase());
148+
}
149+
return false;
150+
}
151+
98152
protected async createClient(
99153
port: string | number
100154
): Promise<CoreClientProvider.Client> {
@@ -136,8 +190,9 @@ export class CoreClientProvider extends GrpcClientProvider<CoreClientProvider.Cl
136190
}: CoreClientProvider.Client): Promise<void> {
137191
const initReq = new InitRequest();
138192
initReq.setInstance(instance);
139-
await new Promise<void>((resolve, reject) => {
193+
return new Promise<void>((resolve, reject) => {
140194
const stream = client.init(initReq);
195+
const errorStatus: RpcStatus[] = [];
141196
stream.on('data', (res: InitResponse) => {
142197
const progress = res.getInitProgress();
143198
if (progress) {
@@ -153,13 +208,30 @@ export class CoreClientProvider extends GrpcClientProvider<CoreClientProvider.Cl
153208
}
154209
}
155210

156-
const err = res.getError();
157-
if (err) {
158-
console.error(err.getMessage());
211+
const error = res.getError();
212+
if (error) {
213+
console.error(error.getMessage());
214+
errorStatus.push(error);
215+
// Cancel the init request. This will result in a cancel error.
216+
stream.cancel();
217+
}
218+
});
219+
stream.on('error', (error) => {
220+
// on any error during the init request, the request is canceled.
221+
// on cancel, the IDE2 ignores the cancel error and rejects with the original one.
222+
reject(
223+
this.isCancelError(error) && errorStatus.length
224+
? errorStatus[0]
225+
: error
226+
);
227+
});
228+
stream.on('end', () => {
229+
if (errorStatus.length) {
230+
reject(errorStatus);
231+
} else {
232+
resolve();
159233
}
160234
});
161-
stream.on('error', (err) => reject(err));
162-
stream.on('end', resolve);
163235
});
164236
}
165237

@@ -233,7 +305,9 @@ export class CoreClientProvider extends GrpcClientProvider<CoreClientProvider.Cl
233305
}
234306
});
235307
await new Promise<void>((resolve, reject) => {
236-
resp.on('error', reject);
308+
resp.on('error', (error) => {
309+
reject(error);
310+
});
237311
resp.on('end', resolve);
238312
});
239313
}

0 commit comments

Comments
 (0)