Skip to content

Commit 4e0edbd

Browse files
committed
retry pet refresh on process crash
1 parent 76c2430 commit 4e0edbd

File tree

1 file changed

+15
-10
lines changed

1 file changed

+15
-10
lines changed

src/managers/common/nativePythonFinder.ts

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -260,10 +260,11 @@ class NativePythonFinderImpl implements NativePythonFinder {
260260
this.restartAttempts = 0;
261261
return environment;
262262
} catch (ex) {
263-
// On resolve timeout (not configure — configure handles its own timeout),
263+
// On resolve timeout or connection error (not configure — configure handles its own timeout),
264264
// kill the hung process so next request triggers restart
265-
if (ex instanceof RpcTimeoutError && ex.method !== 'configure') {
266-
this.outputChannel.warn('[pet] Resolve request timed out, killing hung process for restart');
265+
if ((ex instanceof RpcTimeoutError && ex.method !== 'configure') || ex instanceof rpc.ConnectionError) {
266+
const reason = ex instanceof rpc.ConnectionError ? 'crashed' : 'timed out';
267+
this.outputChannel.warn(`[pet] Resolve request ${reason}, killing process for restart`);
267268
this.killProcess();
268269
this.processExited = true;
269270
}
@@ -574,11 +575,14 @@ class NativePythonFinderImpl implements NativePythonFinder {
574575
} catch (ex) {
575576
lastError = ex;
576577

577-
// Only retry on timeout errors
578-
if (ex instanceof RpcTimeoutError && ex.method !== 'configure') {
578+
// Retry on timeout or connection errors (PET hung or crashed mid-request)
579+
const isRetryable =
580+
(ex instanceof RpcTimeoutError && ex.method !== 'configure') || ex instanceof rpc.ConnectionError;
581+
if (isRetryable) {
579582
if (attempt < MAX_REFRESH_RETRIES) {
583+
const reason = ex instanceof rpc.ConnectionError ? 'crashed' : 'timed out';
580584
this.outputChannel.warn(
581-
`[pet] Refresh timed out (attempt ${attempt + 1}/${MAX_REFRESH_RETRIES + 1}), restarting and retrying...`,
585+
`[pet] Refresh ${reason} (attempt ${attempt + 1}/${MAX_REFRESH_RETRIES + 1}), restarting and retrying...`,
582586
);
583587
// Kill and restart for retry
584588
this.killProcess();
@@ -588,7 +592,7 @@ class NativePythonFinderImpl implements NativePythonFinder {
588592
// Final attempt failed
589593
this.outputChannel.error(`[pet] Refresh failed after ${MAX_REFRESH_RETRIES + 1} attempts`);
590594
}
591-
// Non-timeout errors or final timeout - rethrow
595+
// Non-retryable errors or final attempt - rethrow
592596
throw ex;
593597
}
594598
}
@@ -652,10 +656,11 @@ class NativePythonFinderImpl implements NativePythonFinder {
652656
this.outputChannel.info(`[pet] Refresh succeeded on retry attempt ${attempt + 1}`);
653657
}
654658
} catch (ex) {
655-
// On refresh timeout (not configure — configure handles its own timeout),
659+
// On refresh timeout or connection error (not configure — configure handles its own timeout),
656660
// kill the hung process so next request triggers restart
657-
if (ex instanceof RpcTimeoutError && ex.method !== 'configure') {
658-
this.outputChannel.warn('[pet] Request timed out, killing hung process for restart');
661+
if ((ex instanceof RpcTimeoutError && ex.method !== 'configure') || ex instanceof rpc.ConnectionError) {
662+
const reason = ex instanceof rpc.ConnectionError ? 'crashed' : 'timed out';
663+
this.outputChannel.warn(`[pet] PET process ${reason}, killing for restart`);
659664
this.killProcess();
660665
this.processExited = true;
661666
}

0 commit comments

Comments
 (0)