UNPKG

javascript-typescript-langserver

Version:

Implementation of the Language Server Protocol for JavaScript and TypeScript

70 lines 3.23 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const cluster = require("cluster"); const net = require("net"); const messages_1 = require("vscode-jsonrpc/lib/messages"); const connection_1 = require("./connection"); const lang_handler_1 = require("./lang-handler"); const logging_1 = require("./logging"); const typescript_service_1 = require("./typescript-service"); /** * Creates a Logger prefixed with master or worker ID * * @param logger An optional logger to wrap, e.g. to write to a logfile. Defaults to STDIO */ function createClusterLogger(logger = new logging_1.StdioLogger()) { return new logging_1.PrefixedLogger(logger, cluster.isMaster ? 'master' : `wrkr ${cluster.worker.id}`); } exports.createClusterLogger = createClusterLogger; /** * Starts up a cluster of worker processes that listen on the same TCP socket. * Crashing workers are restarted automatically. * * @param options * @param createLangHandler Factory function that is called for each new connection */ function serve(options, createLangHandler = (remoteClient) => new typescript_service_1.TypeScriptService(remoteClient)) { const logger = options.logger || createClusterLogger(); if (options.clusterSize > 1 && cluster.isMaster) { logger.log(`Spawning ${options.clusterSize} workers`); cluster.on('online', worker => { logger.log(`Worker ${worker.id} (PID ${worker.process.pid}) online`); }); cluster.on('exit', (worker, code, signal) => { const baseLogMessage = `Worker ${worker.id} (PID ${worker.process.pid}) exited from signal ${signal} with code ${code}`; if (!worker.exitedAfterDisconnect) { logger.error(`${baseLogMessage}, restarting`); cluster.fork(); return; } logger.info(`${baseLogMessage}, not restarting since exit was voluntary`); }); for (let i = 0; i < options.clusterSize; ++i) { cluster.fork(); } } else { let counter = 1; const server = net.createServer(socket => { const id = counter++; logger.log(`Connection ${id} accepted`); const messageEmitter = new connection_1.MessageEmitter(socket, options); const messageWriter = new connection_1.MessageWriter(socket, options); const remoteClient = new lang_handler_1.RemoteLanguageClient(messageEmitter, messageWriter); // Add exit notification handler to close the socket on exit messageEmitter.on('message', message => { if (messages_1.isNotificationMessage(message) && message.method === 'exit') { socket.end(); socket.destroy(); logger.log(`Connection ${id} closed (exit notification)`); } }); connection_1.registerLanguageHandler(messageEmitter, messageWriter, createLangHandler(remoteClient), options); }); server.listen(options.lspPort, () => { logger.info(`Listening for incoming LSP connections on ${options.lspPort}`); }); } } exports.serve = serve; //# sourceMappingURL=server.js.map