Skip to content

Commit 7bc2a1e

Browse files
fix: retry compilation if grpc client needs to be reinitialized
See #2547
1 parent a52bce2 commit 7bc2a1e

File tree

2 files changed

+81
-39
lines changed

2 files changed

+81
-39
lines changed

arduino-ide-extension/src/node/core-service-impl.ts

Lines changed: 76 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import { Instance } from './cli-protocol/cc/arduino/cli/commands/v1/common_pb';
3636
import {
3737
CompileRequest,
3838
CompileResponse,
39+
InstanceNeedsReinitializationError,
3940
} from './cli-protocol/cc/arduino/cli/commands/v1/compile_pb';
4041
import { Port as RpcPort } from './cli-protocol/cc/arduino/cli/commands/v1/port_pb';
4142
import {
@@ -89,48 +90,84 @@ export class CoreServiceImpl extends CoreClientAware implements CoreService {
8990
compileSummaryHandler
9091
);
9192
const toDisposeOnFinally = new DisposableCollection(handler);
93+
9294
return new Promise<void>((resolve, reject) => {
93-
const call = client.compile(request);
94-
if (cancellationToken) {
95-
toDisposeOnFinally.push(
96-
cancellationToken.onCancellationRequested(() => call.cancel())
95+
let hasRetried = false;
96+
97+
const handleUnexpectedError = (error: Error) => {
98+
console.error(
99+
'Unexpected error occurred while compiling the sketch.',
100+
error
97101
);
98-
}
99-
call
100-
.on('data', handler.onData)
101-
.on('error', (error) => {
102-
if (!ServiceError.is(error)) {
103-
console.error(
104-
'Unexpected error occurred while compiling the sketch.',
105-
error
106-
);
107-
reject(error);
108-
return;
109-
}
110-
if (ServiceError.isCancel(error)) {
111-
console.log(userAbort);
112-
reject(UserAbortApplicationError());
113-
return;
114-
}
115-
const compilerErrors = tryParseError({
116-
content: handler.content,
117-
sketch: options.sketch,
118-
});
119-
const message = nls.localize(
120-
'arduino/compile/error',
121-
'Compilation error: {0}',
122-
compilerErrors
123-
.map(({ message }) => message)
124-
.filter(notEmpty)
125-
.shift() ?? error.details
126-
);
127-
this.sendResponse(
128-
error.details + '\n\n' + message,
129-
OutputMessage.Severity.Error
102+
reject(error);
103+
};
104+
105+
const handleCancellationError = () => {
106+
console.log(userAbort);
107+
reject(UserAbortApplicationError());
108+
};
109+
110+
const handleInstanceNeedsReinitializationError = async (
111+
error: ServiceError & InstanceNeedsReinitializationError
112+
) => {
113+
if (hasRetried) {
114+
// If error persists, send the error message to the output
115+
return parseAndSendErrorResponse(error);
116+
}
117+
118+
hasRetried = true;
119+
await this.refresh();
120+
return startCompileStream();
121+
};
122+
123+
const parseAndSendErrorResponse = (error: ServiceError) => {
124+
const compilerErrors = tryParseError({
125+
content: handler.content,
126+
sketch: options.sketch,
127+
});
128+
const message = nls.localize(
129+
'arduino/compile/error',
130+
'Compilation error: {0}',
131+
compilerErrors
132+
.map(({ message }) => message)
133+
.filter(notEmpty)
134+
.shift() ?? error.details
135+
);
136+
this.sendResponse(
137+
error.details + '\n\n' + message,
138+
OutputMessage.Severity.Error
139+
);
140+
reject(CoreError.VerifyFailed(message, compilerErrors));
141+
};
142+
143+
const handleError = async (error: Error) => {
144+
if (!ServiceError.is(error)) return handleUnexpectedError(error);
145+
if (ServiceError.isCancel(error)) return handleCancellationError();
146+
147+
if (
148+
ServiceError.isInstanceOf(error, InstanceNeedsReinitializationError)
149+
) {
150+
return await handleInstanceNeedsReinitializationError(error);
151+
}
152+
153+
parseAndSendErrorResponse(error);
154+
};
155+
156+
const startCompileStream = () => {
157+
const call = client.compile(request);
158+
if (cancellationToken) {
159+
toDisposeOnFinally.push(
160+
cancellationToken.onCancellationRequested(() => call.cancel())
130161
);
131-
reject(CoreError.VerifyFailed(message, compilerErrors));
132-
})
133-
.on('end', resolve);
162+
}
163+
164+
call
165+
.on('data', handler.onData)
166+
.on('error', handleError)
167+
.on('end', resolve);
168+
};
169+
170+
startCompileStream();
134171
}).finally(() => {
135172
toDisposeOnFinally.dispose();
136173
if (!isCompileSummary(compileSummary)) {

arduino-ide-extension/src/node/service-error.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,18 @@ import { Status } from './cli-protocol/google/rpc/status_pb';
33
import { stringToUint8Array } from '../common/utils';
44
import { Status as StatusCode } from '@grpc/grpc-js/build/src/constants';
55
import { ProgrammerIsRequiredForUploadError } from './cli-protocol/cc/arduino/cli/commands/v1/upload_pb';
6+
import { InstanceNeedsReinitializationError } from './cli-protocol/cc/arduino/cli/commands/v1/compile_pb';
67

78
type ProtoError = typeof ProgrammerIsRequiredForUploadError;
89
const protoErrorsMap = new Map<string, ProtoError>([
910
[
1011
'cc.arduino.cli.commands.v1.ProgrammerIsRequiredForUploadError',
1112
ProgrammerIsRequiredForUploadError,
1213
],
14+
[
15+
'cc.arduino.cli.commands.v1.InstanceNeedsReinitializationError',
16+
InstanceNeedsReinitializationError,
17+
],
1318
// handle other cli defined errors here
1419
]);
1520

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy