-
Notifications
You must be signed in to change notification settings - Fork 92
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Reticulate support to the kernel supervisor (#5854)
This change makes it possible to use Reticulate sessions with the kernel supervisor. <img width="885" alt="image" src="https://github.com/user-attachments/assets/493a7c36-6d49-498f-86f1-886d4255d4e2" /> The supervisor has a new `adopt` endpoint that allows it to connect to a session that is already running somewhere else. Now, when you start a Reticulate session, the following things happen: - An R session is started, if necessary. - A Reticulate session is started inside the R session. - The Python kernel is started inside the Reticulate session. - The supervisor "adopts" the Python kernel, connecting to its ZeroMQ sockets and proxying messages as it does for other kernels. In addition to adding the orchestration to use the supervisor, there are a couple of other small changes in this PR: - There is a new _Restart the Kernel Supervisor_ command, which shuts down the supervisor process and all sessions, regardless of what state they're in. This is mostly intended as a debugging tool, and it was added in order to make it possible to pick up e.g. debug log level changes without restarting Positron, but could also be helpful as a last resort if things get stuck. - The progress shown when starting a Reticulate session is now much more chatty; it appears as soon as you try to start the session and shows more information along the way. Progress towards #4579; this enables the use of Reticulate on Posit Workbench, and is the last major piece of functionality that required the Jupyter Adapter. (Note that the main body of this change lives in the supervisor itself; this is just the front end / UI bits.) ### QA Notes There's a _lot_ of orchestration involved already in starting Reticulate and this makes it even more complicated. The highest risk areas are around lifecycle management: shutting down, restarting, reconnecting, etc. There is a known issue in which if you have an exited R session in your Console and try to start a Reticulate session, it never happens. I didn't try to fix that in this PR.
- Loading branch information
Showing
12 changed files
with
585 additions
and
78 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
/*--------------------------------------------------------------------------------------------- | ||
* Copyright (C) 2024 Posit Software, PBC. All rights reserved. | ||
* Licensed under the Elastic License 2.0. See LICENSE.txt for license information. | ||
*--------------------------------------------------------------------------------------------*/ | ||
|
||
/** | ||
* PromiseHandles is a class that represents a promise that can be resolved or | ||
* rejected externally. | ||
*/ | ||
export class PromiseHandles<T> { | ||
resolve!: (value: T | Promise<T>) => void; | ||
|
||
reject!: (error: unknown) => void; | ||
|
||
promise: Promise<T>; | ||
|
||
constructor() { | ||
this.promise = new Promise((resolve, reject) => { | ||
this.resolve = resolve; | ||
this.reject = reject; | ||
}); | ||
} | ||
} | ||
|
||
/** | ||
* A barrier that is initially closed and then becomes opened permanently. | ||
* Ported from VS Code's async.ts. | ||
*/ | ||
|
||
export class Barrier { | ||
private _isOpen: boolean; | ||
private _promise: Promise<boolean>; | ||
private _completePromise!: (v: boolean) => void; | ||
|
||
constructor() { | ||
this._isOpen = false; | ||
this._promise = new Promise<boolean>((c, _e) => { | ||
this._completePromise = c; | ||
}); | ||
} | ||
|
||
isOpen(): boolean { | ||
return this._isOpen; | ||
} | ||
|
||
open(): void { | ||
this._isOpen = true; | ||
this._completePromise(true); | ||
} | ||
|
||
wait(): Promise<boolean> { | ||
return this._promise; | ||
} | ||
} | ||
|
||
/** | ||
* Wraps a promise in a timeout that rejects the promise if it does not resolve | ||
* within the given time. | ||
* | ||
* @param promise The promise to wrap | ||
* @param timeout The timeout interval in milliseconds | ||
* @param message The error message to use if the promise times out | ||
* | ||
* @returns The wrapped promise | ||
*/ | ||
export function withTimeout<T>(promise: Promise<T>, | ||
timeout: number, | ||
message: string): Promise<T> { | ||
return Promise.race([ | ||
promise, | ||
new Promise<T>((_, reject) => setTimeout(() => reject(new Error(message)), timeout)) | ||
]); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.