Skip to content

Commit 13ea21f

Browse files
author
Akos Kitta
committed
moved out progress reporting from indexes update
Signed-off-by: Akos Kitta <[email protected]>
1 parent 3e2f048 commit 13ea21f

File tree

2 files changed

+93
-69
lines changed

2 files changed

+93
-69
lines changed

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

+42-69
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import {
1919
UpdateLibrariesIndexResponse,
2020
} from './cli-protocol/cc/arduino/cli/commands/v1/commands_pb';
2121
import * as commandsGrpcPb from './cli-protocol/cc/arduino/cli/commands/v1/commands_grpc_pb';
22-
import { NotificationServiceServer, ProgressMessage } from '../common/protocol';
22+
import { NotificationServiceServer } from '../common/protocol';
2323
import { Deferred, retry } from '@theia/core/lib/common/promise-util';
2424
import {
2525
Status as RpcStatus,
@@ -29,8 +29,10 @@ import { ConfigServiceImpl } from './config-service-impl';
2929
import { ArduinoDaemonImpl } from './arduino-daemon-impl';
3030
import { DisposableCollection } from '@theia/core/lib/common/disposable';
3131
import { Disposable } from '@theia/core/shared/vscode-languageserver-protocol';
32-
import { v4 } from 'uuid';
33-
import { InstallWithProgress } from './grpc-installable';
32+
import {
33+
IndexesUpdateProgressHandler,
34+
InstallWithProgress,
35+
} from './grpc-installable';
3436
import type { DefaultCliConfig } from './cli-config';
3537
import { ServiceError } from './service-error';
3638

@@ -242,91 +244,45 @@ export class CoreClientProvider {
242244
private async updateIndexes(
243245
client: CoreClientProvider.Client
244246
): Promise<CoreClientProvider.Client> {
245-
const progressId = v4();
246-
// Note: at this point, the IDE2 backend might not have any connected clients, so this notification is not delivered to anywhere
247-
// Hence, clients must handle gracefully when no `willUpdate` is received before any `didProgress`.
248-
this.notificationService.notifyIndexWillUpdate(progressId);
249-
// The index update progress responses are not much helpful from the CLI. They cannot provide a fine-grain progress.
250-
// So IDE2 could report two total works only: index update and library index update.
251-
// See here an example: https://github.com/arduino/arduino-ide/issues/906#issuecomment-1171145630
252-
// Due to this, IDE2 fakes the progress to provide slightly better UX.
253-
const totalPlatformIndexCount =
254-
(this.configService.cliConfiguration?.board_manager?.additional_urls
255-
?.length ?? 0) + 1; // +1 for the `package_index.tar.bz2` when updating the platform index.
256-
// The `library_index.json.gz` and `library_index.json.sig` when running the library index update.
257-
const totalLibraryIndexCount = 2;
258-
let work = {
259-
done: 0,
260-
total: totalPlatformIndexCount + totalLibraryIndexCount + 1, // +1 for better UX, leave the last step complete when all subtasks are done.
261-
};
262-
const reportProgress = ({
263-
progressId,
264-
message,
265-
}: Omit<ProgressMessage, 'work'>) => {
266-
work = {
267-
...work,
268-
done: work.done + 1,
269-
};
270-
this.notificationService.notifyIndexUpdateDidProgress({
271-
message,
272-
progressId,
273-
work,
274-
});
275-
};
276-
const toDispose = new DisposableCollection();
247+
const progressHandler = this.createProgressHandler();
277248
try {
278-
const onDidProgressEmitter = new Emitter<ProgressMessage>();
279-
const onDidProgress = onDidProgressEmitter.event;
280-
toDispose.pushAll([
281-
onDidProgressEmitter,
282-
onDidProgress(({ message, progressId }) =>
283-
reportProgress({ progressId, message })
284-
),
285-
]);
286249
await Promise.all([
287-
this.updateIndex(client, progressId, onDidProgressEmitter),
288-
this.updateLibraryIndex(client, progressId, onDidProgressEmitter),
289-
]);
290-
this.notificationService.notifyIndexDidUpdate(progressId);
250+
this.updateIndex(client, progressHandler),
251+
this.updateLibraryIndex(client, progressHandler),
252+
]).then(() => progressHandler.reportEnd());
291253
} catch (err) {
292-
this.notificationService.notifyIndexUpdateDidFail({
293-
progressId,
294-
message: ServiceError.is(err) ? err.details : String(err),
295-
});
296-
} finally {
297-
toDispose.dispose();
254+
console.error('Failed to update indexes', err);
255+
progressHandler.reportError(
256+
ServiceError.is(err) ? err.details : String(err)
257+
);
298258
}
299259
return client;
300260
}
301261

302262
private async updateIndex(
303263
client: CoreClientProvider.Client,
304-
progressId: string,
305-
onDidProgressEmitter: Emitter<ProgressMessage>
264+
progressHandler: IndexesUpdateProgressHandler
306265
): Promise<void> {
307266
return this.doUpdateIndex(
308267
() =>
309268
client.client.updateIndex(
310269
new UpdateIndexRequest().setInstance(client.instance)
311270
),
312-
progressId,
313-
onDidProgressEmitter,
271+
progressHandler,
314272
'platform-index'
315273
);
316274
}
317275

318276
private async updateLibraryIndex(
319277
client: CoreClientProvider.Client,
320-
progressId: string,
321-
onDidProgressEmitter: Emitter<ProgressMessage>
278+
progressHandler: IndexesUpdateProgressHandler
322279
): Promise<void> {
323280
return this.doUpdateIndex(
324281
() =>
325282
client.client.updateLibrariesIndex(
326283
new UpdateLibrariesIndexRequest().setInstance(client.instance)
327284
),
328-
progressId,
329-
onDidProgressEmitter,
285+
progressHandler,
330286
'library-index'
331287
);
332288
}
@@ -338,10 +294,10 @@ export class CoreClientProvider {
338294
| UpdateCoreLibrariesIndexResponse // not used by IDE2
339295
>(
340296
responseProvider: () => grpc.ClientReadableStream<R>,
341-
progressId: string,
342-
onDidProgressEmitter: Emitter<ProgressMessage>,
297+
progressHandler: IndexesUpdateProgressHandler,
343298
task?: string
344299
): Promise<void> {
300+
const { progressId } = progressHandler;
345301
return retry(
346302
() =>
347303
new Promise<void>((resolve, reject) => {
@@ -350,15 +306,12 @@ export class CoreClientProvider {
350306
'data',
351307
InstallWithProgress.createDataCallback({
352308
responseService: {
353-
appendToOutput: (message) => {
309+
appendToOutput: ({ chunk: message }) => {
354310
console.log(
355311
`core-client-provider${task ? ` [${task}]` : ''}`,
356-
message.chunk
312+
message
357313
);
358-
onDidProgressEmitter.fire({
359-
message: message.chunk,
360-
progressId,
361-
});
314+
progressHandler.reportProgress(message);
362315
},
363316
},
364317
progressId,
@@ -372,6 +325,26 @@ export class CoreClientProvider {
372325
);
373326
}
374327

328+
private createProgressHandler() {
329+
const additionalUrlsCount =
330+
this.configService.cliConfiguration?.board_manager?.additional_urls
331+
?.length ?? 0;
332+
const progressHandler = new IndexesUpdateProgressHandler(
333+
additionalUrlsCount,
334+
(progressMessage) =>
335+
this.notificationService.notifyIndexUpdateDidProgress(progressMessage),
336+
({ progressId, message }) =>
337+
this.notificationService.notifyIndexUpdateDidFail({
338+
progressId,
339+
message,
340+
}),
341+
(progressId) =>
342+
this.notificationService.notifyIndexWillUpdate(progressId),
343+
(progressId) => this.notificationService.notifyIndexDidUpdate(progressId)
344+
);
345+
return progressHandler;
346+
}
347+
375348
private address(port: string): string {
376349
return `localhost:${port}`;
377350
}

Diff for: arduino-ide-extension/src/node/grpc-installable.ts

+51
Original file line numberDiff line numberDiff line change
@@ -213,3 +213,54 @@ export namespace InstallWithProgress {
213213
return undefined;
214214
}
215215
}
216+
217+
export class IndexesUpdateProgressHandler {
218+
private done = 0;
219+
private readonly total: number;
220+
readonly progressId: string;
221+
222+
constructor(
223+
additionalUrlsCount: number,
224+
private readonly onProgress: (progressMessage: ProgressMessage) => void,
225+
private readonly onError?: ({
226+
progressId,
227+
message,
228+
}: {
229+
progressId: string;
230+
message: string;
231+
}) => void,
232+
private readonly onStart?: (progressId: string) => void,
233+
private readonly onEnd?: (progressId: string) => void
234+
) {
235+
this.progressId = v4();
236+
this.total = IndexesUpdateProgressHandler.total(additionalUrlsCount);
237+
// Note: at this point, the IDE2 backend might not have any connected clients, so this notification is not delivered to anywhere
238+
// Hence, clients must handle gracefully when no `willUpdate` is received before any `didProgress`.
239+
this.onStart?.(this.progressId);
240+
}
241+
242+
reportEnd(): void {
243+
this.onEnd?.(this.progressId);
244+
}
245+
246+
reportProgress(message: string): void {
247+
this.onProgress({
248+
message,
249+
progressId: this.progressId,
250+
work: { total: this.total, done: this.done++ },
251+
});
252+
}
253+
254+
reportError(message: string): void {
255+
this.onError?.({ progressId: this.progressId, message });
256+
}
257+
258+
private static total(additionalUrlsCount: number): number {
259+
// +1 for the `package_index.tar.bz2` when updating the platform index.
260+
const totalPlatformIndexCount = additionalUrlsCount + 1;
261+
// The `library_index.json.gz` and `library_index.json.sig` when running the library index update.
262+
const totalLibraryIndexCount = 2;
263+
// +1 for better UX (`reportEnd`)
264+
return totalPlatformIndexCount + totalLibraryIndexCount + 1;
265+
}
266+
}

0 commit comments

Comments
 (0)