Skip to content

Commit 1746f4b

Browse files
committed
factor out socket-event-sending
1 parent 9f991d3 commit 1746f4b

3 files changed

Lines changed: 67 additions & 46 deletions

File tree

src/server/editorServices.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1441,7 +1441,9 @@ namespace ts.server {
14411441
}
14421442
this.seenProjects.set(projectKey, true);
14431443

1444-
if (!this.eventHandler) return;
1444+
if (!this.eventHandler) {
1445+
return;
1446+
}
14451447

14461448
const data: ProjectInfoTelemetryEventData = {
14471449
projectId: this.host.createHash(projectKey),

src/server/server.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace ts.server {
66
host: ServerHost;
77
cancellationToken: ServerCancellationToken;
88
canUseEvents: boolean;
9-
eventPort: number;
9+
eventPort?: number;
1010
useSingleInferredProject: boolean;
1111
useInferredProjectPerProjectRoot: boolean;
1212
disableAutomaticTypingAcquisition: boolean;
@@ -872,7 +872,7 @@ namespace ts.server {
872872
cancellationToken = nullCancellationToken;
873873
}
874874

875-
let eventPort: number;
875+
let eventPort: number | undefined;
876876
{
877877
const str = findArgument("--eventPort");
878878
const v = str && parseInt(str);

src/server/session.ts

Lines changed: 62 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -115,10 +115,6 @@ namespace ts.server {
115115
project: Project;
116116
}
117117

118-
export interface EventSender {
119-
event<T>(payload: T, eventName: string): void;
120-
}
121-
122118
function allEditsBeforePos(edits: ts.TextChange[], pos: number) {
123119
for (const edit of edits) {
124120
if (textSpanEnd(edit.span) >= pos) {
@@ -253,6 +249,55 @@ namespace ts.server {
253249
}
254250
}
255251

252+
export type Event = <T>(body: T, eventName: string) => void;
253+
254+
export interface EventSender {
255+
event: Event;
256+
}
257+
258+
class SocketEventSender implements EventSender {
259+
private host: ServerHost;
260+
private logger: Logger;
261+
private eventPort: number;
262+
private eventSocket: NodeSocket;
263+
private socketEventQueue: { body: any, eventName: string }[] | undefined;
264+
265+
constructor(host: ServerHost, logger: Logger, eventPort: number) {
266+
this.host = host;
267+
this.logger = logger;
268+
this.eventPort = eventPort;
269+
270+
const s = net.connect({ port: this.eventPort }, () => {
271+
this.eventSocket = s;
272+
if (this.socketEventQueue) {
273+
// flush queue.
274+
for (const event of this.socketEventQueue) {
275+
this.writeToEventSocket(event.body, event.eventName);
276+
}
277+
this.socketEventQueue = undefined;
278+
}
279+
});
280+
}
281+
282+
public event<T>(body: T, eventName: string): void {
283+
if (!this.eventSocket) {
284+
if (this.logger.hasLevel(LogLevel.verbose)) {
285+
this.logger.info(`eventPort: event "${eventName}" queued, but socket not yet initialized`);
286+
}
287+
(this.socketEventQueue || (this.socketEventQueue = [])).push({ body, eventName });
288+
return;
289+
}
290+
else {
291+
Debug.assert(this.socketEventQueue === undefined);
292+
this.writeToEventSocket(body, eventName);
293+
}
294+
}
295+
296+
private writeToEventSocket(body: any, eventName: string): void {
297+
this.eventSocket.write(formatMessage({ seq: 0, type: "event", event: eventName, body: body }, this.logger, Buffer.byteLength, this.host.newLine), "utf8");
298+
}
299+
}
300+
256301
export interface SessionOptions {
257302
host: ServerHost;
258303
cancellationToken: ServerCancellationToken;
@@ -262,9 +307,13 @@ namespace ts.server {
262307
byteLength: (buf: string, encoding?: string) => number;
263308
hrtime: (start?: number[]) => number[];
264309
logger: Logger;
310+
/**
311+
* If falsy, all events are suppressed.
312+
*/
265313
canUseEvents: boolean;
266314
/**
267-
* If defined, the Session will send events through `eventPort` instead of stdout.
315+
* If defined, specifies the socket to send events to the client.
316+
* Otherwise, events are sent through the host.
268317
*/
269318
eventPort?: number;
270319
eventHandler?: ProjectServiceEventHandler;
@@ -276,6 +325,8 @@ namespace ts.server {
276325
}
277326

278327
export class Session implements EventSender {
328+
public readonly event: Event;
329+
279330
private readonly gcTimer: GcTimer;
280331
protected projectService: ProjectService;
281332
private changeSeq = 0;
@@ -292,10 +343,7 @@ namespace ts.server {
292343

293344
private canUseEvents: boolean;
294345
private eventPort: number | undefined;
295-
private eventSocket: NodeSocket;
296346
private eventHandler: ProjectServiceEventHandler;
297-
public readonly event: EventSender["event"];
298-
private socketEventQueue: { info: any, eventName: string}[] | undefined;
299347

300348
constructor(opts: SessionOptions) {
301349
this.host = opts.host;
@@ -308,43 +356,18 @@ namespace ts.server {
308356
this.canUseEvents = opts.canUseEvents;
309357

310358
const { throttleWaitMilliseconds } = opts;
311-
312-
if (!this.canUseEvents) {
313-
this.event = noop;
314-
}
315-
else if (this.eventPort) {
316-
const s = net.connect({ port: this.eventPort }, () => {
317-
this.eventSocket = s;
318-
if (this.socketEventQueue) {
319-
// flush queue.
320-
for (const event of this.socketEventQueue) {
321-
this.writeToEventSocket(event.info, event.eventName);
322-
}
323-
this.socketEventQueue = undefined;
324-
}
325-
});
326-
327-
this.event = function <T>(info: T, eventName: string) {
328-
if (!this.eventSocket) {
329-
if (this.logger.hasLevel(LogLevel.verbose)) {
330-
this.logger.info(`eventPort: event queued, but socket not yet initialized`);
331-
}
332-
(this.socketEventQueue || (this.socketEventQueue = [])).push({ info, eventName });
333-
return;
334-
}
335-
else {
336-
Debug.assert(this.socketEventQueue === undefined);
337-
this.writeToEventSocket(info, eventName);
338-
}
339-
};
359+
360+
if (this.eventPort && this.canUseEvents) {
361+
const eventSender = new SocketEventSender(this.host, this.logger, this.eventPort);
362+
this.event = eventSender.event;
340363
}
341364
else {
342-
this.event = function <T>(info: T, eventName: string) {
365+
this.event = function <T>(body: T, eventName: string): void {
343366
const ev: protocol.Event = {
344367
seq: 0,
345368
type: "event",
346369
event: eventName,
347-
body: info
370+
body
348371
};
349372
this.send(ev);
350373
};
@@ -380,10 +403,6 @@ namespace ts.server {
380403
this.gcTimer = new GcTimer(this.host, /*delay*/ 7000, this.logger);
381404
}
382405

383-
private writeToEventSocket(info: any, eventName: string): void {
384-
this.eventSocket.write(formatMessage({ seq: 0, type: "event", event: eventName, body: info }, this.logger, Buffer.byteLength, this.host.newLine), "utf8");
385-
}
386-
387406
private sendRequestCompletedEvent(requestId: number): void {
388407
this.event<protocol.RequestCompletedEventBody>({ request_seq: requestId }, "requestCompleted");
389408
}

0 commit comments

Comments
 (0)