Keep a maximum number of connections instead of a timeout
There's no way to actually know if those clients have gone away, so it seems it might be better to base it on whether the user has connected again with new clients to determine if the old clients are now invalid.
This commit is contained in:
parent
12e608468b
commit
1164801376
|
@ -12,47 +12,53 @@ import { uriTransformerPath } from "vs/server/src/util";
|
||||||
import { IExtHostReadyMessage } from "vs/workbench/services/extensions/common/extensionHostProtocol";
|
import { IExtHostReadyMessage } from "vs/workbench/services/extensions/common/extensionHostProtocol";
|
||||||
|
|
||||||
export abstract class Connection {
|
export abstract class Connection {
|
||||||
protected readonly _onClose = new Emitter<void>();
|
private readonly _onClose = new Emitter<void>();
|
||||||
public readonly onClose = this._onClose.event;
|
public readonly onClose = this._onClose.event;
|
||||||
protected disposed: boolean = false;
|
private disposed = false;
|
||||||
public constructor(protected protocol: Protocol) {}
|
private _offline: number | undefined;
|
||||||
|
|
||||||
|
public constructor(protected protocol: Protocol) {
|
||||||
|
protocol.onClose(() => this.dispose()); // Explicit close.
|
||||||
|
protocol.onSocketClose(() => this._offline = Date.now()); // Might reconnect.
|
||||||
|
}
|
||||||
|
|
||||||
|
public get offline(): number | undefined {
|
||||||
|
return this._offline;
|
||||||
|
}
|
||||||
|
|
||||||
|
public reconnect(socket: ISocket, buffer: VSBuffer): void {
|
||||||
|
this._offline = undefined;
|
||||||
|
this.doReconnect(socket, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public dispose(): void {
|
||||||
|
if (!this.disposed) {
|
||||||
|
this.disposed = true;
|
||||||
|
this.doDispose();
|
||||||
|
this._onClose.fire();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set up the connection on a new socket.
|
* Set up the connection on a new socket.
|
||||||
*/
|
*/
|
||||||
public abstract reconnect(socket: ISocket, buffer: VSBuffer): void;
|
protected abstract doReconnect(socket: ISocket, buffer: VSBuffer): void;
|
||||||
protected abstract dispose(): void;
|
protected abstract doDispose(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used for all the IPC channels.
|
* Used for all the IPC channels.
|
||||||
*/
|
*/
|
||||||
export class ManagementConnection extends Connection {
|
export class ManagementConnection extends Connection {
|
||||||
private timeout: NodeJS.Timeout | undefined;
|
protected doDispose(): void {
|
||||||
private readonly wait = 1000 * 60;
|
|
||||||
|
|
||||||
public constructor(protocol: Protocol) {
|
|
||||||
super(protocol);
|
|
||||||
protocol.onClose(() => this.dispose());
|
|
||||||
protocol.onSocketClose(() => {
|
|
||||||
this.timeout = setTimeout(() => this.dispose(), this.wait);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public reconnect(socket: ISocket, buffer: VSBuffer): void {
|
|
||||||
clearTimeout(this.timeout as any); // Not sure why the type doesn't work.
|
|
||||||
this.protocol.beginAcceptReconnection(socket, buffer);
|
|
||||||
this.protocol.endAcceptReconnection();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected dispose(): void {
|
|
||||||
if (!this.disposed) {
|
|
||||||
clearTimeout(this.timeout as any); // Not sure why the type doesn't work.
|
|
||||||
this.disposed = true;
|
|
||||||
this.protocol.sendDisconnect();
|
this.protocol.sendDisconnect();
|
||||||
this.protocol.dispose();
|
this.protocol.dispose();
|
||||||
this.protocol.getSocket().end();
|
this.protocol.getSocket().end();
|
||||||
this._onClose.fire();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected doReconnect(socket: ISocket, buffer: VSBuffer): void {
|
||||||
|
this.protocol.beginAcceptReconnection(socket, buffer);
|
||||||
|
this.protocol.endAcceptReconnection();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,18 +76,14 @@ export class ExtensionHostConnection extends Connection {
|
||||||
this.protocol.getUnderlyingSocket().pause();
|
this.protocol.getUnderlyingSocket().pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected dispose(): void {
|
protected doDispose(): void {
|
||||||
if (!this.disposed) {
|
|
||||||
this.disposed = true;
|
|
||||||
if (this.process) {
|
if (this.process) {
|
||||||
this.process.kill();
|
this.process.kill();
|
||||||
}
|
}
|
||||||
this.protocol.getSocket().end();
|
this.protocol.getSocket().end();
|
||||||
this._onClose.fire();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public reconnect(socket: ISocket, buffer: VSBuffer): void {
|
protected doReconnect(socket: ISocket, buffer: VSBuffer): void {
|
||||||
// This is just to set the new socket.
|
// This is just to set the new socket.
|
||||||
this.protocol.beginAcceptReconnection(socket, null);
|
this.protocol.beginAcceptReconnection(socket, null);
|
||||||
this.protocol.dispose();
|
this.protocol.dispose();
|
||||||
|
|
|
@ -426,6 +426,7 @@ export class MainServer extends Server {
|
||||||
public readonly onDidClientConnect = this._onDidClientConnect.event;
|
public readonly onDidClientConnect = this._onDidClientConnect.event;
|
||||||
private readonly ipc = new IPCServer(this.onDidClientConnect);
|
private readonly ipc = new IPCServer(this.onDidClientConnect);
|
||||||
|
|
||||||
|
private readonly maxOfflineConnections = 5;
|
||||||
private readonly connections = new Map<ConnectionType, Map<string, Connection>>();
|
private readonly connections = new Map<ConnectionType, Map<string, Connection>>();
|
||||||
|
|
||||||
private readonly services = new ServiceCollection();
|
private readonly services = new ServiceCollection();
|
||||||
|
@ -586,6 +587,7 @@ export class MainServer extends Server {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
connections.set(token, connection);
|
connections.set(token, connection);
|
||||||
|
this.disposeOldOfflineConnections();
|
||||||
connection.onClose(() => connections.delete(token));
|
connection.onClose(() => connections.delete(token));
|
||||||
break;
|
break;
|
||||||
case ConnectionType.Tunnel: return protocol.tunnel();
|
case ConnectionType.Tunnel: return protocol.tunnel();
|
||||||
|
@ -593,6 +595,16 @@ export class MainServer extends Server {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private disposeOldOfflineConnections(): void {
|
||||||
|
this.connections.forEach((connections) => {
|
||||||
|
const offline = Array.from(connections.values())
|
||||||
|
.filter((connection) => typeof connection.offline !== "undefined");
|
||||||
|
for (let i = 0, max = offline.length - this.maxOfflineConnections; i < max; ++i) {
|
||||||
|
offline[i].dispose();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private async initializeServices(args: ParsedArgs): Promise<void> {
|
private async initializeServices(args: ParsedArgs): Promise<void> {
|
||||||
const environmentService = new EnvironmentService(args, process.execPath);
|
const environmentService = new EnvironmentService(args, process.execPath);
|
||||||
const logService = new SpdLogService(RemoteExtensionLogFileName, environmentService.logsPath, getLogLevel(environmentService));
|
const logService = new SpdLogService(RemoteExtensionLogFileName, environmentService.logsPath, getLogLevel(environmentService));
|
||||||
|
|
Loading…
Reference in New Issue