Cleaning up ts server logic
Getting ready to have worker based TS servers instead of ones that use a process - Use standard error handler instead of having separate reader error - Move all process based server logic into own file (`serverProcess`)
This commit is contained in:
parent
a155fcf762
commit
00a0a77785
5 changed files with 57 additions and 51 deletions
|
@ -43,8 +43,9 @@ class FakeServerProcess implements TsServerProcess {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onData(_handler: any) { /* noop */ }
|
||||||
on(_name: any, _handler: any) { /* noop */ }
|
onError(_handler: any) { /* noop */ }
|
||||||
|
onExit(_handler: any) { /* noop */ }
|
||||||
|
|
||||||
kill(): void { /* noop */ }
|
kill(): void { /* noop */ }
|
||||||
|
|
||||||
|
|
|
@ -4,19 +4,17 @@
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import * as stream from 'stream';
|
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import type * as Proto from '../protocol';
|
import type * as Proto from '../protocol';
|
||||||
|
import { EventName } from '../protocol.const';
|
||||||
|
import { CallbackMap } from '../tsServer/callbackMap';
|
||||||
|
import { RequestItem, RequestQueue, RequestQueueingType } from '../tsServer/requestQueue';
|
||||||
|
import { TypeScriptServerError } from '../tsServer/serverError';
|
||||||
import { ServerResponse, TypeScriptRequests } from '../typescriptService';
|
import { ServerResponse, TypeScriptRequests } from '../typescriptService';
|
||||||
import { Disposable } from '../utils/dispose';
|
import { Disposable } from '../utils/dispose';
|
||||||
import { TelemetryReporter } from '../utils/telemetry';
|
import { TelemetryReporter } from '../utils/telemetry';
|
||||||
import Tracer from '../utils/tracer';
|
import Tracer from '../utils/tracer';
|
||||||
import { TypeScriptVersion } from '../utils/versionProvider';
|
import { TypeScriptVersion } from '../utils/versionProvider';
|
||||||
import { Reader } from '../utils/wireProtocol';
|
|
||||||
import { CallbackMap } from './callbackMap';
|
|
||||||
import { RequestItem, RequestQueue, RequestQueueingType } from './requestQueue';
|
|
||||||
import { TypeScriptServerError } from './serverError';
|
|
||||||
import { EventName } from '../protocol.const';
|
|
||||||
|
|
||||||
export interface OngoingRequestCanceller {
|
export interface OngoingRequestCanceller {
|
||||||
tryCancelOngoingRequest(seq: number): boolean;
|
tryCancelOngoingRequest(seq: number): boolean;
|
||||||
|
@ -47,7 +45,6 @@ export interface ITypeScriptServer {
|
||||||
readonly onEvent: vscode.Event<Proto.Event>;
|
readonly onEvent: vscode.Event<Proto.Event>;
|
||||||
readonly onExit: vscode.Event<any>;
|
readonly onExit: vscode.Event<any>;
|
||||||
readonly onError: vscode.Event<any>;
|
readonly onError: vscode.Event<any>;
|
||||||
readonly onReaderError: vscode.Event<Error>;
|
|
||||||
|
|
||||||
readonly tsServerLogFile: string | undefined;
|
readonly tsServerLogFile: string | undefined;
|
||||||
|
|
||||||
|
@ -65,17 +62,17 @@ export interface TsServerDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TsServerProcess {
|
export interface TsServerProcess {
|
||||||
readonly stdout: stream.Readable;
|
|
||||||
write(serverRequest: Proto.Request): void;
|
write(serverRequest: Proto.Request): void;
|
||||||
|
|
||||||
on(name: 'exit', handler: (code: number | null) => void): void;
|
onData(handler: (data: Proto.Response) => void): void;
|
||||||
on(name: 'error', handler: (error: Error) => void): void;
|
onExit(handler: (code: number | null) => void): void;
|
||||||
|
onError(handler: (error: Error) => void): void;
|
||||||
|
|
||||||
kill(): void;
|
kill(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export class ProcessBasedTsServer extends Disposable implements ITypeScriptServer {
|
export class ProcessBasedTsServer extends Disposable implements ITypeScriptServer {
|
||||||
private readonly _reader: Reader<Proto.Response>;
|
|
||||||
private readonly _requestQueue = new RequestQueue();
|
private readonly _requestQueue = new RequestQueue();
|
||||||
private readonly _callbacks = new CallbackMap<Proto.Response>();
|
private readonly _callbacks = new CallbackMap<Proto.Response>();
|
||||||
private readonly _pendingResponses = new Set<number>();
|
private readonly _pendingResponses = new Set<number>();
|
||||||
|
@ -90,14 +87,17 @@ export class ProcessBasedTsServer extends Disposable implements ITypeScriptServe
|
||||||
private readonly _tracer: Tracer,
|
private readonly _tracer: Tracer,
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
this._reader = this._register(new Reader<Proto.Response>(this._process.stdout!));
|
|
||||||
this._reader.onData(msg => this.dispatchMessage(msg));
|
|
||||||
|
|
||||||
this._process.on('exit', code => {
|
this._process.onData(msg => {
|
||||||
|
this.dispatchMessage(msg);
|
||||||
|
});
|
||||||
|
|
||||||
|
this._process.onExit(code => {
|
||||||
this._onExit.fire(code);
|
this._onExit.fire(code);
|
||||||
this._callbacks.destroy('server exited');
|
this._callbacks.destroy('server exited');
|
||||||
});
|
});
|
||||||
this._process.on('error', error => {
|
|
||||||
|
this._process.onError(error => {
|
||||||
this._onError.fire(error);
|
this._onError.fire(error);
|
||||||
this._callbacks.destroy('server errored');
|
this._callbacks.destroy('server errored');
|
||||||
});
|
});
|
||||||
|
@ -112,8 +112,6 @@ export class ProcessBasedTsServer extends Disposable implements ITypeScriptServe
|
||||||
private readonly _onError = this._register(new vscode.EventEmitter<any>());
|
private readonly _onError = this._register(new vscode.EventEmitter<any>());
|
||||||
public readonly onError = this._onError.event;
|
public readonly onError = this._onError.event;
|
||||||
|
|
||||||
public get onReaderError() { return this._reader.onError; }
|
|
||||||
|
|
||||||
public get tsServerLogFile() { return this._tsServerLogFile; }
|
public get tsServerLogFile() { return this._tsServerLogFile; }
|
||||||
|
|
||||||
private write(serverRequest: Proto.Request) {
|
private write(serverRequest: Proto.Request) {
|
||||||
|
@ -439,8 +437,6 @@ export class GetErrRoutingTsServer extends Disposable implements ITypeScriptServ
|
||||||
private readonly _onError = this._register(new vscode.EventEmitter<any>());
|
private readonly _onError = this._register(new vscode.EventEmitter<any>());
|
||||||
public readonly onError = this._onError.event;
|
public readonly onError = this._onError.event;
|
||||||
|
|
||||||
public get onReaderError() { return this.mainServer.onReaderError; }
|
|
||||||
|
|
||||||
public get tsServerLogFile() { return this.mainServer.tsServerLogFile; }
|
public get tsServerLogFile() { return this.mainServer.tsServerLogFile; }
|
||||||
|
|
||||||
public kill(): void {
|
public kill(): void {
|
||||||
|
@ -577,8 +573,6 @@ export class SyntaxRoutingTsServer extends Disposable implements ITypeScriptServ
|
||||||
private readonly _onError = this._register(new vscode.EventEmitter<any>());
|
private readonly _onError = this._register(new vscode.EventEmitter<any>());
|
||||||
public readonly onError = this._onError.event;
|
public readonly onError = this._onError.event;
|
||||||
|
|
||||||
public get onReaderError() { return this.semanticServer.onReaderError; }
|
|
||||||
|
|
||||||
public get tsServerLogFile() { return this.semanticServer.tsServerLogFile; }
|
public get tsServerLogFile() { return this.semanticServer.tsServerLogFile; }
|
||||||
|
|
||||||
public kill(): void {
|
public kill(): void {
|
||||||
|
|
|
@ -3,11 +3,8 @@
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
import * as child_process from 'child_process';
|
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import * as stream from 'stream';
|
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import type * as Proto from '../protocol';
|
|
||||||
import { ClientCapabilities, ClientCapability } from '../typescriptService';
|
import { ClientCapabilities, ClientCapability } from '../typescriptService';
|
||||||
import API from '../utils/api';
|
import API from '../utils/api';
|
||||||
import { SeparateSyntaxServerConfiguration, TsServerLogLevel, TypeScriptServiceConfiguration } from '../utils/configuration';
|
import { SeparateSyntaxServerConfiguration, TsServerLogLevel, TypeScriptServiceConfiguration } from '../utils/configuration';
|
||||||
|
@ -16,10 +13,11 @@ import LogDirectoryProvider from '../utils/logDirectoryProvider';
|
||||||
import Logger from '../utils/logger';
|
import Logger from '../utils/logger';
|
||||||
import { TypeScriptPluginPathsProvider } from '../utils/pluginPathsProvider';
|
import { TypeScriptPluginPathsProvider } from '../utils/pluginPathsProvider';
|
||||||
import { PluginManager } from '../utils/plugins';
|
import { PluginManager } from '../utils/plugins';
|
||||||
|
import { ChildServerProcess } from '../utils/serverProcess';
|
||||||
import { TelemetryReporter } from '../utils/telemetry';
|
import { TelemetryReporter } from '../utils/telemetry';
|
||||||
import Tracer from '../utils/tracer';
|
import Tracer from '../utils/tracer';
|
||||||
import { TypeScriptVersion, TypeScriptVersionProvider } from '../utils/versionProvider';
|
import { TypeScriptVersion, TypeScriptVersionProvider } from '../utils/versionProvider';
|
||||||
import { GetErrRoutingTsServer, ITypeScriptServer, PipeRequestCanceller, ProcessBasedTsServer, SyntaxRoutingTsServer, TsServerDelegate, TsServerProcess } from './server';
|
import { GetErrRoutingTsServer, ITypeScriptServer, PipeRequestCanceller, ProcessBasedTsServer, SyntaxRoutingTsServer, TsServerDelegate } from './server';
|
||||||
|
|
||||||
const enum ServerKind {
|
const enum ServerKind {
|
||||||
Main = 'main',
|
Main = 'main',
|
||||||
|
@ -269,25 +267,3 @@ export class TypeScriptServerSpawner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChildServerProcess implements TsServerProcess {
|
|
||||||
|
|
||||||
public constructor(
|
|
||||||
private readonly _process: child_process.ChildProcess,
|
|
||||||
) { }
|
|
||||||
|
|
||||||
get stdout(): stream.Readable { return this._process.stdout!; }
|
|
||||||
|
|
||||||
write(serverRequest: Proto.Request): void {
|
|
||||||
this._process.stdin!.write(JSON.stringify(serverRequest) + '\r\n', 'utf8');
|
|
||||||
}
|
|
||||||
|
|
||||||
on(name: 'exit', handler: (code: number | null) => void): void;
|
|
||||||
on(name: 'error', handler: (error: Error) => void): void;
|
|
||||||
on(name: any, handler: any) {
|
|
||||||
this._process.on(name, handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
kill(): void {
|
|
||||||
this._process.kill();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -424,7 +424,6 @@ export default class TypeScriptServiceClient extends Disposable implements IType
|
||||||
this.isRestarting = false;
|
this.isRestarting = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
handle.onReaderError(error => this.error('ReaderError', error));
|
|
||||||
handle.onEvent(event => this.dispatchEvent(event));
|
handle.onEvent(event => this.dispatchEvent(event));
|
||||||
|
|
||||||
if (apiVersion.gte(API.v300)) {
|
if (apiVersion.gte(API.v300)) {
|
||||||
|
|
|
@ -3,8 +3,11 @@
|
||||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||||
*--------------------------------------------------------------------------------------------*/
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import { ChildProcess } from 'child_process';
|
||||||
import * as stream from 'stream';
|
import * as stream from 'stream';
|
||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
|
import type * as Proto from '../protocol';
|
||||||
|
import { TsServerProcess } from '../tsServer/server';
|
||||||
import { Disposable } from './dispose';
|
import { Disposable } from './dispose';
|
||||||
|
|
||||||
const defaultSize: number = 8192;
|
const defaultSize: number = 8192;
|
||||||
|
@ -80,7 +83,7 @@ class ProtocolBuffer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class Reader<T> extends Disposable {
|
class Reader<T> extends Disposable {
|
||||||
|
|
||||||
private readonly buffer: ProtocolBuffer = new ProtocolBuffer();
|
private readonly buffer: ProtocolBuffer = new ProtocolBuffer();
|
||||||
private nextMessageLength: number = -1;
|
private nextMessageLength: number = -1;
|
||||||
|
@ -123,3 +126,36 @@ export class Reader<T> extends Disposable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class ChildServerProcess extends Disposable implements TsServerProcess {
|
||||||
|
private readonly _reader: Reader<Proto.Response>;
|
||||||
|
|
||||||
|
public constructor(
|
||||||
|
private readonly _process: ChildProcess,
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
this._reader = this._register(new Reader<Proto.Response>(this._process.stdout!));
|
||||||
|
}
|
||||||
|
|
||||||
|
write(serverRequest: Proto.Request): void {
|
||||||
|
this._process.stdin!.write(JSON.stringify(serverRequest) + '\r\n', 'utf8');
|
||||||
|
}
|
||||||
|
|
||||||
|
onData(handler: (data: Proto.Response) => void): void {
|
||||||
|
this._reader.onData(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
onExit(handler: (code: number | null) => void): void {
|
||||||
|
this._process.on('exit', handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
onError(handler: (err: Error) => void): void {
|
||||||
|
this._process.on('error', handler);
|
||||||
|
this._reader.onError(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
kill(): void {
|
||||||
|
this._process.kill();
|
||||||
|
this._reader.dispose();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue