javascript-typescript-langserver
Version:
Implementation of the Language Server Protocol for JavaScript and TypeScript
70 lines • 3.23 kB
JavaScript
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
;