1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Fix issues

- Shell sessions are now not persisted if the cluster is disconnected

- On reconnect, fake the last data message being sent so that the
  terminal is not empty

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2021-11-17 09:46:22 -05:00
parent f2709caa72
commit 5e30aa9dae
2 changed files with 42 additions and 15 deletions

View File

@ -191,6 +191,7 @@ export abstract class ShellSession {
this.running = true; this.running = true;
shellProcess.onData(data => this.send({ type: TerminalChannels.STDOUT, data })); shellProcess.onData(data => this.send({ type: TerminalChannels.STDOUT, data }));
shellProcess.onExit(({ exitCode }) => { shellProcess.onExit(({ exitCode }) => {
logger.info(`[SHELL-SESSION]: shell has exited for ${this.terminalId} closed with code=${exitCode}`);
this.running = false; this.running = false;
if (exitCode > 0) { if (exitCode > 0) {
@ -204,7 +205,7 @@ export abstract class ShellSession {
this.websocket this.websocket
.on("message", (data: string | Uint8Array) => { .on("message", (data: string | Uint8Array) => {
if (!this.running) { if (!this.running) {
return; return void logger.debug(`[SHELL-SESSION]: received message from ${this.terminalId}, but shellProcess isn't running`);
} }
if (typeof data === "string") { if (typeof data === "string") {
@ -230,15 +231,24 @@ export abstract class ShellSession {
} }
}) })
.on("close", code => { .on("close", code => {
logger.debug(`[SHELL-SESSION]: websocket for ${this.terminalId} closed with code=${code}`); logger.info(`[SHELL-SESSION]: websocket for ${this.terminalId} closed with code=${code}`);
if (this.running && code !== WebSocketCloseEvent.AbnormalClosure && code !== WebSocketCloseEvent.GoingAway) { const stopShellSession = this.running
&& !(
code === WebSocketCloseEvent.AbnormalClosure
|| (
code === WebSocketCloseEvent.GoingAway
&& !this.cluster.disconnected
)
);
if (stopShellSession) {
try { try {
logger.info(`[SHELL-SESSION]: Killing shell process for ${this.terminalId}`); logger.info(`[SHELL-SESSION]: Killing shell process for ${this.terminalId}`);
process.kill(shellProcess.pid); process.kill(shellProcess.pid);
ShellSession.processes.delete(this.terminalId); ShellSession.processes.delete(this.terminalId);
} catch (e) { } catch {}
}
this.running = false; this.running = false;
} }
}); });

View File

@ -19,7 +19,7 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/ */
import { boundMethod, getHostedClusterId } from "../utils"; import { getHostedClusterId } from "../utils";
import { WebSocketApi, WebSocketEvents } from "./websocket-api"; import { WebSocketApi, WebSocketEvents } from "./websocket-api";
import isEqual from "lodash/isEqual"; import isEqual from "lodash/isEqual";
import url from "url"; import url from "url";
@ -27,6 +27,7 @@ import { makeObservable, observable } from "mobx";
import { ipcRenderer } from "electron"; import { ipcRenderer } from "electron";
import logger from "../../common/logger"; import logger from "../../common/logger";
import { deserialize, serialize } from "v8"; import { deserialize, serialize } from "v8";
import { once } from "lodash";
export enum TerminalChannels { export enum TerminalChannels {
STDIN = "stdin", STDIN = "stdin",
@ -119,7 +120,26 @@ export class TerminalApi extends WebSocketApi<TerminalEvents> {
slashes: true, slashes: true,
}); });
this.prependListener("data", this._onReady); const onReady = once((data?: string) => {
this.isReady = true;
this.emit("ready");
this.removeListener("data", onReady);
this.removeListener("connected", onReady);
this.flush();
// data is undefined if the event that was handled is "connected"
if (data === undefined) {
/**
* Output the last line, the makes sure that the terminal isn't completely
* empty when the user refreshes.
*/
this.emit("data", window.localStorage.getItem(`${this.query.id}:last-data`));
}
});
this.prependListener("data", onReady);
this.prependListener("connected", onReady);
super.connect(socketUrl); super.connect(socketUrl);
this.socket.binaryType = "arraybuffer"; this.socket.binaryType = "arraybuffer";
} }
@ -132,14 +152,6 @@ export class TerminalApi extends WebSocketApi<TerminalEvents> {
setTimeout(() => super.destroy(), 2000); setTimeout(() => super.destroy(), 2000);
} }
@boundMethod
protected _onReady() {
this.isReady = true;
this.emit("ready");
this.removeListener("data", this._onReady);
this.flush();
}
reconnect() { reconnect() {
super.reconnect(); super.reconnect();
} }
@ -166,6 +178,11 @@ export class TerminalApi extends WebSocketApi<TerminalEvents> {
switch (message.type) { switch (message.type) {
case TerminalChannels.STDOUT: case TerminalChannels.STDOUT:
/**
* save the last data for reconnections. User localStorage because we
* don't want this data to survive if the app is closed
*/
window.localStorage.setItem(`${this.query.id}:last-data`, message.data);
super._onMessage({ data: message.data, ...evt }); super._onMessage({ data: message.data, ...evt });
break; break;
case TerminalChannels.CONNECTED: case TerminalChannels.CONNECTED: