Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit a003831

Browse files
Akos Kittakittaakos
Akos Kitta
authored andcommitted
fixup.
Signed-off-by: Akos Kitta <a.kitta@arduino.cc>
1 parent aea550f commit a003831

File tree

2 files changed

+80
-46
lines changed

2 files changed

+80
-46
lines changed

‎arduino-ide-extension/src/node/board-discovery.ts‎

Lines changed: 79 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,14 @@ import {
1414
AvailablePorts,
1515
AttachedBoardsChangeEvent,
1616
} from '../common/protocol';
17-
import { Emitter } from '@theia/core/lib/common/event';
17+
import { Emitter,Event } from '@theia/core/lib/common/event';
1818
import { DisposableCollection } from '@theia/core/lib/common/disposable';
1919
import { Disposable } from '@theia/core/shared/vscode-languageserver-protocol';
2020
import { ArduinoCoreServiceClient } from './cli-protocol/cc/arduino/cli/commands/v1/commands_grpc_pb';
2121
import { v4 } from 'uuid';
2222
import { ServiceError } from './service-error';
2323
import { BackendApplicationContribution } from '@theia/core/lib/node';
24+
import { Deferred } from '@theia/core/lib/common/promise-util';
2425

2526
type Duplex = ClientDuplexStream<BoardListWatchRequest, BoardListWatchResponse>;
2627
interface StreamWrapper extends Disposable {
@@ -30,7 +31,8 @@ interface StreamWrapper extends Disposable {
3031

3132
/**
3233
* Singleton service for tracking the available ports and board and broadcasting the
33-
* changes to all connected frontend instances. \
34+
* changes to all connected frontend instances.
35+
*
3436
* Unlike other services, this is not connection scoped.
3537
*/
3638
@injectable()
@@ -45,16 +47,16 @@ export class BoardDiscovery
4547
@inject(NotificationServiceServer)
4648
private readonly notificationService: NotificationServiceServer;
4749

48-
// Used to know if the board watch process is already running to avoid
49-
// starting it multiple times
50-
private watching: boolean;
50+
private watching: Deferred<void> | undefined;
51+
private stopping: Deferred<void> | undefined;
5152
private wrapper: StreamWrapper | undefined;
5253
private readonly onStreamDidEndEmitter = new Emitter<void>(); // sent from the CLI when the discovery process is killed for example after the indexes update and the core client re-initialization.
5354
private readonly onStreamDidCancelEmitter = new Emitter<void>(); // when the watcher is canceled by the IDE2
5455
private readonly toDisposeOnStopWatch = new DisposableCollection();
5556

5657
/**
5758
* Keys are the `address` of the ports.
59+
*
5860
* The `protocol` is ignored because the board detach event does not carry the protocol information,
5961
* just the address.
6062
* ```json
@@ -64,46 +66,57 @@ export class BoardDiscovery
6466
* }
6567
* ```
6668
*/
67-
private _state: AvailablePorts = {};
68-
get state(): AvailablePorts {
69-
return this._state;
69+
private _availablePorts: AvailablePorts = {};
70+
get availablePorts(): AvailablePorts {
71+
return this._availablePorts;
7072
}
7173

7274
onStart(): void {
7375
this.start();
74-
this.onClientDidRefresh(() => this.start());
76+
this.onClientDidRefresh(() => this.restart());
77+
}
78+
79+
private async restart(): Promise<void> {
80+
this.logger.info('restarting before stop');
81+
await this.stop();
82+
this.logger.info('restarting after stop');
83+
return this.start();
7584
}
7685

7786
onStop(): void {
7887
this.stop();
7988
}
8089

81-
stop(): Promise<void> {
90+
async stop(restart = false): Promise<void> {
91+
this.logger.info('stop');
92+
if (this.stopping) {
93+
this.logger.info('stop already stopping');
94+
return this.stopping.promise;
95+
}
96+
if (!this.watching) {
97+
return;
98+
}
99+
this.stopping = new Deferred();
82100
this.logger.info('>>> Stopping boards watcher...');
83101
return new Promise<void>((resolve, reject) => {
84-
const timeout = this.createTimeout(
85-
BoardDiscovery.StopWatchTimeout,
86-
reject
87-
);
102+
const timeout = this.createTimeout(10_000, reject);
88103
const toDispose = new DisposableCollection();
89-
toDispose.pushAll([
90-
timeout,
91-
this.onStreamDidEndEmitter.event(() => {
92-
this.logger.info(
93-
`<<< Received the end event from the stream. Boards watcher has been successfully stopped.`
94-
);
95-
this.watching = false;
104+
const waitForEvent = (event: Event<unknown>) =>
105+
event(() => {
106+
this.logger.info('stop received event: either end or cancel');
96107
toDispose.dispose();
108+
this.stopping?.resolve();
109+
this.stopping = undefined;
110+
this.logger.info('stop stopped');
97111
resolve();
98-
}),
99-
this.onStreamDidCancelEmitter.event(() => {
100-
this.logger.info(
101-
`<<< Received the cancel event from the stream. Boards watcher has been successfully stopped.`
102-
);
103-
this.watching = false;
104-
toDispose.dispose();
105-
resolve();
106-
}),
112+
if (restart) {
113+
this.start();
114+
}
115+
});
116+
toDispose.pushAll([
117+
timeout,
118+
waitForEvent(this.onStreamDidEndEmitter.event),
119+
waitForEvent(this.onStreamDidCancelEmitter.event),
107120
]);
108121
this.logger.info('Canceling boards watcher...');
109122
this.toDisposeOnStopWatch.dispose();
@@ -149,9 +162,14 @@ export class BoardDiscovery
149162
}
150163
const stream = client
151164
.boardListWatch()
152-
.on('end', () => this.onStreamDidEndEmitter.fire())
165+
.on('end', () => {
166+
this.logger.info('received end');
167+
this.onStreamDidEndEmitter.fire();
168+
})
153169
.on('error', (error) => {
170+
this.logger.info('error received');
154171
if (ServiceError.isCancel(error)) {
172+
this.logger.info('cancel error received!');
155173
this.onStreamDidCancelEmitter.fire();
156174
} else {
157175
this.logger.error(
@@ -165,13 +183,21 @@ export class BoardDiscovery
165183
stream,
166184
uuid: v4(),
167185
dispose: () => {
186+
this.logger.info('disposing requesting cancel');
168187
// Cancelling the stream will kill the discovery `builtin:mdns-discovery process`.
169188
// The client (this class) will receive a `{"eventType":"quit","error":""}` response from the CLI.
170189
stream.cancel();
190+
this.logger.info('disposing canceled');
171191
this.wrapper = undefined;
172192
},
173193
};
174-
this.toDisposeOnStopWatch.pushAll([wrapper]);
194+
this.toDisposeOnStopWatch.pushAll([
195+
wrapper,
196+
Disposable.create(() => {
197+
this.watching?.reject(new Error(`Stopping watcher.`));
198+
this.watching = undefined;
199+
}),
200+
]);
175201
return wrapper;
176202
}
177203

@@ -188,17 +214,25 @@ export class BoardDiscovery
188214
}
189215

190216
async start(): Promise<void> {
217+
this.logger.info('start');
218+
if (this.stopping) {
219+
this.logger.info('start is stopping wait');
220+
await this.stopping.promise;
221+
this.logger.info('start stopped');
222+
}
191223
if (this.watching) {
192-
// We want to avoid starting the board list watch process multiple
193-
// times to meet unforeseen consequences
194-
return;
224+
this.logger.info('start already watching');
225+
return this.watching.promise;
195226
}
227+
this.watching = new Deferred();
228+
this.logger.info('start new deferred');
196229
const { client, instance } = await this.coreClient;
197230
const wrapper = await this.createWrapper(client);
198231
wrapper.stream.on('data', async (resp: BoardListWatchResponse) => {
199232
this.logger.info('onData', this.toJson(resp));
200233
if (resp.getEventType() === 'quit') {
201-
await this.stop();
234+
this.logger.info('quit received');
235+
this.stop();
202236
return;
203237
}
204238

@@ -217,8 +251,8 @@ export class BoardDiscovery
217251
throw new Error(`Unexpected event type: '${resp.getEventType()}'`);
218252
}
219253

220-
const oldState = deepClone(this._state);
221-
const newState = deepClone(this._state);
254+
const oldState = deepClone(this._availablePorts);
255+
const newState = deepClone(this._availablePorts);
222256

223257
const address = (detectedPort as any).getPort().getAddress();
224258
const protocol = (detectedPort as any).getPort().getProtocol();
@@ -286,18 +320,21 @@ export class BoardDiscovery
286320
},
287321
};
288322

289-
this._state = newState;
323+
this._availablePorts = newState;
290324
this.notificationService.notifyAttachedBoardsDidChange(event);
291325
}
292326
});
327+
this.logger.info('start request start watch');
293328
await this.requestStartWatch(
294329
new BoardListWatchRequest().setInstance(instance),
295330
wrapper.stream
296331
);
297-
this.watching = true;
332+
this.logger.info('start requested start watch');
333+
this.watching.resolve();
334+
this.logger.info('start resolved watching');
298335
}
299336

300-
getAttachedBoards(state: AvailablePorts = this.state): Board[] {
337+
getAttachedBoards(state: AvailablePorts = this.availablePorts): Board[] {
301338
const attachedBoards: Board[] = [];
302339
for (const portID of Object.keys(state)) {
303340
const [, boards] = state[portID];
@@ -306,7 +343,7 @@ export class BoardDiscovery
306343
return attachedBoards;
307344
}
308345

309-
getAvailablePorts(state: AvailablePorts = this.state): Port[] {
346+
getAvailablePorts(state: AvailablePorts = this.availablePorts): Port[] {
310347
const availablePorts: Port[] = [];
311348
for (const portID of Object.keys(state)) {
312349
const [port] = state[portID];
@@ -315,6 +352,3 @@ export class BoardDiscovery
315352
return availablePorts;
316353
}
317354
}
318-
export namespace BoardDiscovery {
319-
export const StopWatchTimeout = 10_000;
320-
}

‎arduino-ide-extension/src/node/boards-service-impl.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ export class BoardsServiceImpl
6060
protected readonly boardDiscovery: BoardDiscovery;
6161

6262
async getState(): Promise<AvailablePorts> {
63-
return this.boardDiscovery.state;
63+
return this.boardDiscovery.availablePorts;
6464
}
6565

6666
async getAttachedBoards(): Promise<Board[]> {

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /