-
Notifications
You must be signed in to change notification settings - Fork 134
Fix cleanup of R sessions #10933
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix cleanup of R sessions #10933
Changes from 8 commits
f7a2b0a
ed325f9
e615941
c42f93d
5781b84
4e2a0b8
9b86e5c
d87869a
dc06be7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| // Folder-specific settings | ||
| // | ||
| // For a full list of overridable settings, and general information on folder-specific settings, | ||
| // see the documentation: https://zed.dev/docs/configuring-zed#settings-files | ||
| { | ||
| "languages": { | ||
| "TypeScript": { | ||
| "tab_size": 2, | ||
| "hard_tabs": true, | ||
| "ensure_final_newline_on_save": true, | ||
| "remove_trailing_whitespace_on_save": true, | ||
| "format_on_save": "on", | ||
| "formatter": "language_server", | ||
| "code_actions_on_format": { | ||
| "source.fixAll.eslint": false | ||
| } | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,12 +5,10 @@ | |
|
|
||
| import * as positron from 'positron'; | ||
| import * as vscode from 'vscode'; | ||
| import { RSession } from './session'; | ||
| import { RSession, getActiveRSessions } from './session'; | ||
|
|
||
| /** | ||
| * Manages all the R sessions. We keep our own references to each session in a | ||
| * singleton instance of this class so that we can invoke methods/check status | ||
| * directly, without going through Positron's API. | ||
| * Manages all the R sessions. | ||
| */ | ||
| export class RSessionManager implements vscode.Disposable { | ||
| /// Singleton instance | ||
|
|
@@ -21,9 +19,6 @@ export class RSessionManager implements vscode.Disposable { | |
| /// but we may improve on this in the future so it is good practice to track them. | ||
| private readonly _disposables: vscode.Disposable[] = []; | ||
|
|
||
| /// Map of session IDs to RSession instances | ||
| private _sessions: Map<string, RSession> = new Map(); | ||
|
|
||
| /// The most recent foreground R session (foreground implies it is a console session) | ||
| private _lastForegroundSessionId: string | null = null; | ||
|
|
||
|
|
@@ -50,18 +45,12 @@ export class RSessionManager implements vscode.Disposable { | |
| } | ||
|
|
||
| /** | ||
| * Registers a runtime with the manager. Throws an error if a runtime with | ||
| * the same ID is already registered. | ||
| * Registers a runtime with the manager. | ||
| * | ||
| * @param id The runtime's ID | ||
| * @param runtime The runtime. | ||
| * @param session The session. | ||
| */ | ||
| setSession(sessionId: string, session: RSession): void { | ||
| if (this._sessions.has(sessionId)) { | ||
| throw new Error(`Session ${sessionId} already registered.`); | ||
| } | ||
| this._sessions.set(sessionId, session); | ||
| this._disposables.push( | ||
| setSession(session: RSession): void { | ||
| session.register( | ||
| session.onDidChangeRuntimeState(async (state) => { | ||
| await this.didChangeSessionRuntimeState(session, state); | ||
| }) | ||
|
|
@@ -99,18 +88,20 @@ export class RSessionManager implements vscode.Disposable { | |
| return; | ||
| } | ||
|
|
||
| // TODO: Switch to `getActiveRSessions()` built on `positron.runtime.getActiveSessions()` | ||
| // and remove `this._sessions` entirely. | ||
| const session = this._sessions.get(sessionId); | ||
| const sessions = await getActiveRSessions(); | ||
| const session = sessions.find(s => s.metadata.sessionId === sessionId); | ||
| if (!session) { | ||
| // The foreground session is for another language. | ||
| // The foreground session is for another language or was deactivated in the meantime | ||
| return; | ||
| } | ||
|
|
||
| if (session.metadata.sessionMode === positron.LanguageRuntimeSessionMode.Background) { | ||
| throw Error(`Foreground session with ID ${sessionId} must not be a background session.`); | ||
| } | ||
|
|
||
| // Multiple `activateConsoleSession()` might run concurrently if the | ||
| // `didChangeForegroundSession` event fires rapidly. We might want to queue | ||
| // the handling. | ||
| this._lastForegroundSessionId = session.metadata.sessionId; | ||
| await this.activateConsoleSession(session, 'foreground session changed'); | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks like multiple |
||
| } | ||
|
|
@@ -120,7 +111,8 @@ export class RSessionManager implements vscode.Disposable { | |
| */ | ||
| private async activateConsoleSession(session: RSession, reason: string): Promise<void> { | ||
| // Deactivate other console session servers first | ||
| await Promise.all(Array.from(this._sessions.values()) | ||
| const sessions = await getActiveRSessions(); | ||
| await Promise.all(sessions | ||
| .filter(s => { | ||
| return s.metadata.sessionId !== session.metadata.sessionId && | ||
| s.metadata.sessionMode === positron.LanguageRuntimeSessionMode.Console; | ||
|
|
@@ -152,9 +144,10 @@ export class RSessionManager implements vscode.Disposable { | |
| * | ||
| * @returns The R console session, or undefined if there isn't one. | ||
| */ | ||
| getConsoleSession(): RSession | undefined { | ||
| async getConsoleSession(): Promise<RSession | undefined> { | ||
| const sessions = await getActiveRSessions(); | ||
|
|
||
| // Sort the sessions by creation time (descending) | ||
| const sessions = Array.from(this._sessions.values()); | ||
| sessions.sort((a, b) => b.created - a.created); | ||
|
|
||
| // Remove any sessions that aren't console sessions and have either | ||
|
|
@@ -186,8 +179,9 @@ export class RSessionManager implements vscode.Disposable { | |
| * @param sessionId The session identifier | ||
| * @returns The R session, or undefined if not found | ||
| */ | ||
| getSessionById(sessionId: string): RSession | undefined { | ||
| return this._sessions.get(sessionId); | ||
| async getSessionById(sessionId: string): Promise<RSession | undefined> { | ||
| const sessions = await getActiveRSessions(); | ||
| return sessions.find(s => s.metadata.sessionId === sessionId); | ||
| } | ||
|
|
||
| /** | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,8 +9,10 @@ import * as testKit from './kit'; | |
| export let currentTestName: string | undefined; | ||
|
|
||
| suiteSetup(async () => { | ||
| // Set global Positron log level to trace for easier debugging | ||
| await vscode.commands.executeCommand('_extensionTests.setLogLevel', 'trace'); | ||
| // Set global Positron log level to debug on CI for easier debugging | ||
| if (process.env.CI) { | ||
| await vscode.commands.executeCommand('_extensionTests.setLogLevel', 'debug'); | ||
|
||
| } | ||
|
|
||
| // Set Ark kernel process log level to trace | ||
| await vscode.workspace.getConfiguration().update('positron.r.kernel.logLevel', 'trace', vscode.ConfigurationTarget.Global); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because of the
await, the session might no longer exist.