Skip to content

Commit 296d59b

Browse files
author
Akos Kitta
committed
Buffer events from BoardListWatchResponse.
Signed-off-by: Akos Kitta <[email protected]>
1 parent 197cea2 commit 296d59b

File tree

3 files changed

+99
-54
lines changed

3 files changed

+99
-54
lines changed

Diff for: arduino-ide-extension/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
"dateformat": "^3.0.3",
7070
"deepmerge": "2.0.1",
7171
"electron-updater": "^4.6.5",
72+
"fast-json-stable-stringify": "^2.0.0",
7273
"fast-safe-stringify": "^2.1.1",
7374
"glob": "^7.1.6",
7475
"google-protobuf": "^3.20.1",

Diff for: arduino-ide-extension/src/common/protocol/boards-service.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,19 @@ import { Searchable } from './searchable';
33
import { Installable } from './installable';
44
import { ArduinoComponent } from './arduino-component';
55
import { nls } from '@theia/core/lib/common/nls';
6+
import URI from '@theia/core/lib/common/uri';
67
import {
78
All,
89
Contributed,
910
Partner,
1011
Type as TypeLabel,
1112
Updatable,
1213
} from '../nls';
13-
import URI from '@theia/core/lib/common/uri';
14+
import stableJsonStringify = require('fast-json-stable-stringify');
1415

16+
/**
17+
* Keys come from `Port#keyOf`.
18+
*/
1519
export type AvailablePorts = Record<string, [Port, Array<Board>]>;
1620
export namespace AvailablePorts {
1721
export function groupByProtocol(
@@ -44,6 +48,11 @@ export namespace AvailablePorts {
4448
ports: availablePorts,
4549
};
4650
}
51+
export function sameAs(left: AvailablePorts, right: AvailablePorts): boolean {
52+
return (
53+
left === right || stableJsonStringify(left) === stableJsonStringify(right)
54+
);
55+
}
4756
}
4857

4958
export interface AttachedBoardsChangeEvent {

Diff for: arduino-ide-extension/src/node/board-discovery.ts

+88-53
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import { Disposable } from '@theia/core/lib/common/disposable';
1010
import { v4 } from 'uuid';
1111
import { Unknown } from '../common/nls';
1212
import {
13-
AttachedBoardsChangeEvent,
1413
AvailablePorts,
1514
Board,
1615
NotificationServiceServer,
@@ -251,57 +250,14 @@ export class BoardDiscovery
251250
return;
252251
}
253252

254-
const detectedPort = resp.getPort();
255-
if (detectedPort) {
256-
const { port, boards } = this.fromRpc(detectedPort);
257-
if (!port) {
258-
if (!!boards.length) {
259-
console.warn(
260-
`Could not detect the port, but unexpectedly received discovered boards. This is most likely a bug! Response was: ${this.toJson(
261-
resp
262-
)}`
263-
);
264-
}
265-
return;
266-
}
267-
const oldState = deepClone(this._availablePorts);
268-
const newState = deepClone(this._availablePorts);
269-
const key = Port.keyOf(port);
270-
271-
if (eventType === EventType.Add) {
272-
if (newState[key]) {
273-
const [, knownBoards] = newState[key];
274-
this.logger.warn(
275-
`Port '${Port.toString(
276-
port
277-
)}' was already available. Known boards before override: ${JSON.stringify(
278-
knownBoards
279-
)}`
280-
);
281-
}
282-
newState[key] = [port, boards];
283-
} else if (eventType === EventType.Remove) {
284-
if (!newState[key]) {
285-
this.logger.warn(
286-
`Port '${Port.toString(port)}' was not available. Skipping`
287-
);
288-
return;
289-
}
290-
delete newState[key];
291-
}
292-
293-
const event: AttachedBoardsChangeEvent = {
294-
oldState: {
295-
...AvailablePorts.split(oldState),
296-
},
297-
newState: {
298-
...AvailablePorts.split(newState),
299-
},
300-
uploadInProgress: this.uploadInProgress,
301-
};
302-
303-
this._availablePorts = newState;
304-
this.notificationService.notifyAttachedBoardsDidChange(event);
253+
const rpcDetectedPort = resp.getPort();
254+
if (rpcDetectedPort) {
255+
const detectedPort = this.fromRpc(rpcDetectedPort);
256+
this.fireSoon({ detectedPort, eventType });
257+
} else if (resp.getError()) {
258+
this.logger.error(
259+
`Could not extract any detected 'port' from the board list watch response. An 'error' has occurred: ${resp.getError()}`
260+
);
305261
}
306262
}
307263

@@ -332,6 +288,75 @@ export class BoardDiscovery
332288
};
333289
return port;
334290
}
291+
292+
private fireSoonHandle?: NodeJS.Timeout;
293+
private bufferedEvents: DetectedPortChangeEvent[] = [];
294+
private fireSoon(event: DetectedPortChangeEvent): void {
295+
this.bufferedEvents.push(event);
296+
clearTimeout(this.fireSoonHandle);
297+
this.fireSoonHandle = setTimeout(() => {
298+
const prevState = deepClone(this.availablePorts);
299+
const newState = this.calculateNewState(this.bufferedEvents, prevState);
300+
if (!AvailablePorts.sameAs(prevState, newState)) {
301+
this._availablePorts = newState;
302+
this.notificationService.notifyAttachedBoardsDidChange({
303+
newState: AvailablePorts.split(newState),
304+
oldState: AvailablePorts.split(prevState),
305+
uploadInProgress: this.uploadInProgress,
306+
});
307+
}
308+
this.bufferedEvents.length = 0;
309+
}, 100);
310+
}
311+
312+
private calculateNewState(
313+
events: DetectedPortChangeEvent[],
314+
prevState: AvailablePorts
315+
): AvailablePorts {
316+
const newState = deepClone(prevState);
317+
for (const { detectedPort, eventType } of events) {
318+
if (!DetectedPort.hasPort(detectedPort)) {
319+
if (!!detectedPort.boards.length) {
320+
console.warn(
321+
`Could not detect the port, but unexpectedly received discovered boards. This is most likely a bug! Detected port was: ${JSON.stringify(
322+
detectedPort
323+
)}`
324+
);
325+
} else {
326+
console.warn(
327+
`Could not detect the port. Skipping: ${JSON.stringify(
328+
detectedPort
329+
)}`
330+
);
331+
}
332+
continue;
333+
}
334+
const { port, boards } = detectedPort;
335+
const key = Port.keyOf(port);
336+
if (eventType === EventType.Add) {
337+
const alreadyDetectedPort = newState[key];
338+
if (alreadyDetectedPort) {
339+
console.warn(
340+
`Detected a new port that has been already discovered. The old value will be overridden. Old value: ${JSON.stringify(
341+
alreadyDetectedPort
342+
)}, new value: ${JSON.stringify(detectedPort)}`
343+
);
344+
}
345+
newState[key] = [port, boards];
346+
} else if (eventType === EventType.Remove) {
347+
const alreadyDetectedPort = newState[key];
348+
if (!alreadyDetectedPort) {
349+
console.warn(
350+
`Detected a port removal but it has not been discovered. This is most likely a bug! Detected port was: ${JSON.stringify(
351+
detectedPort
352+
)}`
353+
);
354+
}
355+
delete newState[key];
356+
}
357+
}
358+
return newState;
359+
}
335360
}
336361

337362
enum EventType {
@@ -356,8 +381,18 @@ namespace EventType {
356381
}
357382
}
358383
}
359-
360384
interface DetectedPort {
361385
port: Port | undefined;
362386
boards: Board[];
363387
}
388+
namespace DetectedPort {
389+
export function hasPort(
390+
detectedPort: DetectedPort
391+
): detectedPort is DetectedPort & { port: Port } {
392+
return !!detectedPort.port;
393+
}
394+
}
395+
interface DetectedPortChangeEvent {
396+
detectedPort: DetectedPort;
397+
eventType: EventType.Add | EventType.Remove;
398+
}

0 commit comments

Comments
 (0)