mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Remove all manual uses of v8 serialization (#5548)
* Remove all manual uses of v8 serialization - Seems that sometimes the is a versioning mismatch within the binary format causes cluster screen the go grey Signed-off-by: Sebastian Malton <sebastian@malton.name> * handle ping Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
parent
3eceb58663
commit
ae8f5d8537
31
src/common/terminal/channels.ts
Normal file
31
src/common/terminal/channels.ts
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) OpenLens Authors. All rights reserved.
|
||||||
|
* Licensed under MIT License. See LICENSE in root directory for more information.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
export enum TerminalChannels {
|
||||||
|
STDIN = "stdin",
|
||||||
|
STDOUT = "stdout",
|
||||||
|
CONNECTED = "connected",
|
||||||
|
RESIZE = "resize",
|
||||||
|
PING = "ping",
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TerminalMessage = {
|
||||||
|
type: TerminalChannels.STDIN;
|
||||||
|
data: string;
|
||||||
|
} | {
|
||||||
|
type: TerminalChannels.STDOUT;
|
||||||
|
data: string;
|
||||||
|
} | {
|
||||||
|
type: TerminalChannels.CONNECTED;
|
||||||
|
} | {
|
||||||
|
type: TerminalChannels.RESIZE;
|
||||||
|
data: {
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
|
};
|
||||||
|
} | {
|
||||||
|
type: TerminalChannels.PING;
|
||||||
|
};
|
||||||
@ -4,7 +4,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import v8 from "v8";
|
|
||||||
import * as yaml from "js-yaml";
|
import * as yaml from "js-yaml";
|
||||||
import type { HelmRepo } from "./helm-repo-manager";
|
import type { HelmRepo } from "./helm-repo-manager";
|
||||||
import logger from "../logger";
|
import logger from "../logger";
|
||||||
@ -13,7 +12,7 @@ import { iter, sortCharts } from "../../common/utils";
|
|||||||
import { execHelm } from "./exec";
|
import { execHelm } from "./exec";
|
||||||
|
|
||||||
interface ChartCacheEntry {
|
interface ChartCacheEntry {
|
||||||
data: Buffer;
|
data: string; // serialized JSON
|
||||||
mtimeMs: number;
|
mtimeMs: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,7 +76,7 @@ export class HelmChartManager {
|
|||||||
const normalized = normalizeHelmCharts(this.repo.name, data.entries);
|
const normalized = normalizeHelmCharts(this.repo.name, data.entries);
|
||||||
|
|
||||||
HelmChartManager.#cache.set(this.repo.name, {
|
HelmChartManager.#cache.set(this.repo.name, {
|
||||||
data: v8.serialize(normalized),
|
data: JSON.stringify(normalized),
|
||||||
mtimeMs: cacheFileStats.mtimeMs,
|
mtimeMs: cacheFileStats.mtimeMs,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -94,7 +93,7 @@ export class HelmChartManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return v8.deserialize(HelmChartManager.#cache.get(this.repo.name).data);
|
return JSON.parse(HelmChartManager.#cache.get(this.repo.name).data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -13,8 +13,8 @@ import { get } from "lodash";
|
|||||||
import { Node, NodesApi } from "../../../common/k8s-api/endpoints";
|
import { Node, NodesApi } from "../../../common/k8s-api/endpoints";
|
||||||
import { KubeJsonApi } from "../../../common/k8s-api/kube-json-api";
|
import { KubeJsonApi } from "../../../common/k8s-api/kube-json-api";
|
||||||
import logger from "../../logger";
|
import logger from "../../logger";
|
||||||
import { TerminalChannels } from "../../../renderer/api/terminal-api";
|
|
||||||
import type { Kubectl } from "../../kubectl/kubectl";
|
import type { Kubectl } from "../../kubectl/kubectl";
|
||||||
|
import { TerminalChannels } from "../../../common/terminal/channels";
|
||||||
|
|
||||||
export class NodeShellSession extends ShellSession {
|
export class NodeShellSession extends ShellSession {
|
||||||
ShellType = "node-shell";
|
ShellType = "node-shell";
|
||||||
|
|||||||
@ -16,10 +16,8 @@ import { UserStore } from "../../common/user-store";
|
|||||||
import * as pty from "node-pty";
|
import * as pty from "node-pty";
|
||||||
import { appEventBus } from "../../common/app-event-bus/event-bus";
|
import { appEventBus } from "../../common/app-event-bus/event-bus";
|
||||||
import logger from "../logger";
|
import logger from "../logger";
|
||||||
import type { TerminalMessage } from "../../renderer/api/terminal-api";
|
|
||||||
import { TerminalChannels } from "../../renderer/api/terminal-api";
|
|
||||||
import { deserialize, serialize } from "v8";
|
|
||||||
import { stat } from "fs/promises";
|
import { stat } from "fs/promises";
|
||||||
|
import { type TerminalMessage, TerminalChannels } from "../../common/terminal/channels";
|
||||||
|
|
||||||
export class ShellOpenError extends Error {
|
export class ShellOpenError extends Error {
|
||||||
constructor(message: string, public cause: Error) {
|
constructor(message: string, public cause: Error) {
|
||||||
@ -163,7 +161,7 @@ export abstract class ShellSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected send(message: TerminalMessage): void {
|
protected send(message: TerminalMessage): void {
|
||||||
this.websocket.send(serialize(message));
|
this.websocket.send(JSON.stringify(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected async getCwd(env: Record<string, string>): Promise<string> {
|
protected async getCwd(env: Record<string, string>): Promise<string> {
|
||||||
@ -234,17 +232,19 @@ export abstract class ShellSession {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.websocket
|
this.websocket
|
||||||
.on("message", (data: string | Uint8Array) => {
|
.on("message", (rawData: unknown): void => {
|
||||||
if (!this.running) {
|
if (!this.running) {
|
||||||
return void logger.debug(`[SHELL-SESSION]: received message from ${this.terminalId}, but shellProcess isn't running`);
|
return void logger.debug(`[SHELL-SESSION]: received message from ${this.terminalId}, but shellProcess isn't running`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof data === "string") {
|
if (!(rawData instanceof Buffer)) {
|
||||||
return void logger.silly(`[SHELL-SESSION]: Received message from ${this.terminalId}`, { data });
|
return void logger.error(`[SHELL-SESSION]: Received message non-buffer message.`, { rawData });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const data = rawData.toString();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const message: TerminalMessage = deserialize(data);
|
const message: TerminalMessage = JSON.parse(data);
|
||||||
|
|
||||||
switch (message.type) {
|
switch (message.type) {
|
||||||
case TerminalChannels.STDIN:
|
case TerminalChannels.STDIN:
|
||||||
@ -253,6 +253,9 @@ export abstract class ShellSession {
|
|||||||
case TerminalChannels.RESIZE:
|
case TerminalChannels.RESIZE:
|
||||||
shellProcess.resize(message.data.width, message.data.height);
|
shellProcess.resize(message.data.width, message.data.height);
|
||||||
break;
|
break;
|
||||||
|
case TerminalChannels.PING:
|
||||||
|
logger.silly(`[SHELL-SESSION]: ${this.terminalId} ping!`);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
logger.warn(`[SHELL-SESSION]: unknown or unhandleable message type for ${this.terminalId}`, message);
|
logger.warn(`[SHELL-SESSION]: unknown or unhandleable message type for ${this.terminalId}`, message);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -11,31 +11,8 @@ import url from "url";
|
|||||||
import { makeObservable, observable } from "mobx";
|
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 { once } from "lodash";
|
import { once } from "lodash";
|
||||||
|
import { type TerminalMessage, TerminalChannels } from "../../common/terminal/channels";
|
||||||
export enum TerminalChannels {
|
|
||||||
STDIN = "stdin",
|
|
||||||
STDOUT = "stdout",
|
|
||||||
CONNECTED = "connected",
|
|
||||||
RESIZE = "resize",
|
|
||||||
}
|
|
||||||
|
|
||||||
export type TerminalMessage = {
|
|
||||||
type: TerminalChannels.STDIN;
|
|
||||||
data: string;
|
|
||||||
} | {
|
|
||||||
type: TerminalChannels.STDOUT;
|
|
||||||
data: string;
|
|
||||||
} | {
|
|
||||||
type: TerminalChannels.CONNECTED;
|
|
||||||
} | {
|
|
||||||
type: TerminalChannels.RESIZE;
|
|
||||||
data: {
|
|
||||||
width: number;
|
|
||||||
height: number;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
enum TerminalColor {
|
enum TerminalColor {
|
||||||
RED = "\u001b[31m",
|
RED = "\u001b[31m",
|
||||||
@ -126,11 +103,10 @@ export class TerminalApi extends WebSocketApi<TerminalEvents> {
|
|||||||
this.prependListener("connected", onReady);
|
this.prependListener("connected", onReady);
|
||||||
|
|
||||||
super.connect(socketUrl);
|
super.connect(socketUrl);
|
||||||
this.socket.binaryType = "arraybuffer";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sendMessage(message: TerminalMessage) {
|
sendMessage(message: TerminalMessage) {
|
||||||
return this.send(serialize(message));
|
return this.send(JSON.stringify(message));
|
||||||
}
|
}
|
||||||
|
|
||||||
sendTerminalSize(cols: number, rows: number) {
|
sendTerminalSize(cols: number, rows: number) {
|
||||||
@ -145,9 +121,9 @@ export class TerminalApi extends WebSocketApi<TerminalEvents> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected _onMessage({ data, ...evt }: MessageEvent<ArrayBuffer>): void {
|
protected _onMessage({ data, ...evt }: MessageEvent<string>): void {
|
||||||
try {
|
try {
|
||||||
const message: TerminalMessage = deserialize(new Uint8Array(data));
|
const message = JSON.parse(data) as TerminalMessage;
|
||||||
|
|
||||||
switch (message.type) {
|
switch (message.type) {
|
||||||
case TerminalChannels.STDOUT:
|
case TerminalChannels.STDOUT:
|
||||||
|
|||||||
@ -8,6 +8,7 @@ import EventEmitter from "events";
|
|||||||
import type TypedEventEmitter from "typed-emitter";
|
import type TypedEventEmitter from "typed-emitter";
|
||||||
import type { Arguments } from "typed-emitter";
|
import type { Arguments } from "typed-emitter";
|
||||||
import { isDevelopment } from "../../common/vars";
|
import { isDevelopment } from "../../common/vars";
|
||||||
|
import { TerminalChannels, type TerminalMessage } from "../../common/terminal/channels";
|
||||||
|
|
||||||
interface WebsocketApiParams {
|
interface WebsocketApiParams {
|
||||||
/**
|
/**
|
||||||
@ -29,9 +30,9 @@ interface WebsocketApiParams {
|
|||||||
/**
|
/**
|
||||||
* The message for pinging the websocket
|
* The message for pinging the websocket
|
||||||
*
|
*
|
||||||
* @default "PING"
|
* @default "{type: \"ping\"}"
|
||||||
*/
|
*/
|
||||||
pingMessage?: string | ArrayBufferLike | Blob | ArrayBufferView;
|
pingMessage?: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If set to a number > 0, then the API will ping the socket on that interval.
|
* If set to a number > 0, then the API will ping the socket on that interval.
|
||||||
@ -65,10 +66,10 @@ export interface WebSocketEvents {
|
|||||||
type Defaulted<Params, DefaultParams extends keyof Params> = Required<Pick<Params, DefaultParams>> & Omit<Params, DefaultParams>;
|
type Defaulted<Params, DefaultParams extends keyof Params> = Required<Pick<Params, DefaultParams>> & Omit<Params, DefaultParams>;
|
||||||
|
|
||||||
export class WebSocketApi<Events extends WebSocketEvents> extends (EventEmitter as { new<T>(): TypedEventEmitter<T> })<Events> {
|
export class WebSocketApi<Events extends WebSocketEvents> extends (EventEmitter as { new<T>(): TypedEventEmitter<T> })<Events> {
|
||||||
protected socket?: WebSocket | null;
|
protected socket: WebSocket | null = null;
|
||||||
protected pendingCommands: (string | ArrayBufferLike | Blob | ArrayBufferView)[] = [];
|
protected pendingCommands: string[] = [];
|
||||||
protected reconnectTimer?: any;
|
protected reconnectTimer?: number;
|
||||||
protected pingTimer?: any;
|
protected pingTimer?: number;
|
||||||
protected params: Defaulted<WebsocketApiParams, keyof typeof WebSocketApi["defaultParams"]>;
|
protected params: Defaulted<WebsocketApiParams, keyof typeof WebSocketApi["defaultParams"]>;
|
||||||
|
|
||||||
@observable readyState = WebSocketApiState.PENDING;
|
@observable readyState = WebSocketApiState.PENDING;
|
||||||
@ -77,7 +78,7 @@ export class WebSocketApi<Events extends WebSocketEvents> extends (EventEmitter
|
|||||||
logging: isDevelopment,
|
logging: isDevelopment,
|
||||||
reconnectDelay: 10,
|
reconnectDelay: 10,
|
||||||
flushOnOpen: true,
|
flushOnOpen: true,
|
||||||
pingMessage: "PING",
|
pingMessage: JSON.stringify({ type: TerminalChannels.PING } as TerminalMessage),
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(params: WebsocketApiParams) {
|
constructor(params: WebsocketApiParams) {
|
||||||
@ -87,7 +88,7 @@ export class WebSocketApi<Events extends WebSocketEvents> extends (EventEmitter
|
|||||||
const { pingInterval } = this.params;
|
const { pingInterval } = this.params;
|
||||||
|
|
||||||
if (pingInterval) {
|
if (pingInterval) {
|
||||||
this.pingTimer = setInterval(() => this.ping(), pingInterval * 1000);
|
this.pingTimer = window.setInterval(() => this.ping(), pingInterval * 1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,7 +144,7 @@ export class WebSocketApi<Events extends WebSocketEvents> extends (EventEmitter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
send(command: string | ArrayBufferLike | Blob | ArrayBufferView) {
|
send(command: string) {
|
||||||
if (this.isConnected) {
|
if (this.isConnected) {
|
||||||
this.socket.send(command);
|
this.socket.send(command);
|
||||||
} else {
|
} else {
|
||||||
@ -186,7 +187,7 @@ export class WebSocketApi<Events extends WebSocketEvents> extends (EventEmitter
|
|||||||
|
|
||||||
this.writeLog("will reconnect in", `${reconnectDelay}s`);
|
this.writeLog("will reconnect in", `${reconnectDelay}s`);
|
||||||
|
|
||||||
this.reconnectTimer = setTimeout(() => this.connect(url), reconnectDelay * 1000);
|
this.reconnectTimer = window.setTimeout(() => this.connect(url), reconnectDelay * 1000);
|
||||||
this.readyState = WebSocketApiState.RECONNECTING;
|
this.readyState = WebSocketApiState.RECONNECTING;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -4,8 +4,8 @@
|
|||||||
*/
|
*/
|
||||||
import { getInjectable } from "@ogre-tools/injectable";
|
import { getInjectable } from "@ogre-tools/injectable";
|
||||||
import { when } from "mobx";
|
import { when } from "mobx";
|
||||||
|
import { TerminalChannels } from "../../../../common/terminal/channels";
|
||||||
import type { TerminalApi } from "../../../api/terminal-api";
|
import type { TerminalApi } from "../../../api/terminal-api";
|
||||||
import { TerminalChannels } from "../../../api/terminal-api";
|
|
||||||
import { noop } from "../../../utils";
|
import { noop } from "../../../utils";
|
||||||
import { Notifications } from "../../notifications";
|
import { Notifications } from "../../notifications";
|
||||||
import selectDockTabInjectable from "../dock/select-dock-tab.injectable";
|
import selectDockTabInjectable from "../dock/select-dock-tab.injectable";
|
||||||
|
|||||||
@ -9,7 +9,6 @@ import { Terminal as XTerm } from "xterm";
|
|||||||
import { FitAddon } from "xterm-addon-fit";
|
import { FitAddon } from "xterm-addon-fit";
|
||||||
import type { TabId } from "../dock/store";
|
import type { TabId } from "../dock/store";
|
||||||
import type { TerminalApi } from "../../../api/terminal-api";
|
import type { TerminalApi } from "../../../api/terminal-api";
|
||||||
import { TerminalChannels } from "../../../api/terminal-api";
|
|
||||||
import { ThemeStore } from "../../../theme.store";
|
import { ThemeStore } from "../../../theme.store";
|
||||||
import { disposer } from "../../../utils";
|
import { disposer } from "../../../utils";
|
||||||
import { isMac } from "../../../../common/vars";
|
import { isMac } from "../../../../common/vars";
|
||||||
@ -18,6 +17,7 @@ import { UserStore } from "../../../../common/user-store";
|
|||||||
import { clipboard } from "electron";
|
import { clipboard } from "electron";
|
||||||
import logger from "../../../../common/logger";
|
import logger from "../../../../common/logger";
|
||||||
import type { TerminalConfig } from "../../../../common/user-store/preferences-helpers";
|
import type { TerminalConfig } from "../../../../common/user-store/preferences-helpers";
|
||||||
|
import { TerminalChannels } from "../../../../common/terminal/channels";
|
||||||
|
|
||||||
export class Terminal {
|
export class Terminal {
|
||||||
private terminalConfig: TerminalConfig = UserStore.getInstance().terminalConfig;
|
private terminalConfig: TerminalConfig = UserStore.getInstance().terminalConfig;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user