UNPKG

memcached-node

Version:
874 lines (873 loc) 42 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __assign = (this && this.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; Object.defineProperty(exports, "__esModule", { value: true }); var net = require("net"); var events_1 = require("events"); var async_1 = require("async"); var response_1 = require("./response"); var server_1 = require("./server"); var socket_1 = require("./socket"); var Hashring = require("hashring"); var error_1 = require("./error"); var Status; (function (Status) { Status["INIT"] = "INIT"; Status["CONNECTING"] = "CONNECTING"; Status["IDLE"] = "IDLE"; Status["RESEARVED"] = "RESEARVED"; Status["CLOSE"] = "CLOSE"; })(Status = exports.Status || (exports.Status = {})); exports.defaultConnectionOptions = { mode: "json", removeDeadServer: true, timeout: 3000, retry: true, retryLimit: 10, exponentialBackoff: true, }; var defaultStoreoptions = { isCompressed: false, expires: 0, mode: "string", }; var defaultRetriveoptions = { mode: "string", }; var Connection = /** @class */ (function (_super) { __extends(Connection, _super); function Connection(args, id, options) { if (id === void 0) { id = 0; } var _this = _super.call(this) || this; _this.id = 0; _this._servers = []; _this._sockets = []; _this.status = Status.INIT; _this.id = id; var servers = []; switch (Object.prototype.toString.call(args)) { case "[object Object]": var serverConfig = args; for (var url_1 in serverConfig) { var serverOptions = serverConfig[url_1]; servers.push(new server_1.Server(url_1, serverOptions)); } break; case "[object Array]": servers = args.map(function (url) { return new server_1.Server(url); }); break; default: var url = args; servers = [new server_1.Server(url)]; break; } _this._options = __assign(__assign({}, exports.defaultConnectionOptions), options); _this._servers = servers; _this._hashring = new Hashring(servers); _this._queue = async_1.queue(function (task, errCallBack) { return __awaiter(_this, void 0, void 0, function () { var url, socket, err, readData, _loop_1, this_1, _i, _a, command; return __generator(this, function (_b) { switch (_b.label) { case 0: url = task.location; socket = this._sockets.find(function (socket) { return socket.server.url === url; }); if (!socket) { err = new error_1.ConnectionError("no socket found for " + url, error_1.ConnectionErrorCode.ER_CONN_SOCKET_NOT_FOUND); errCallBack(err); return [2 /*return*/]; } readData = function (chunk) { if (socket) { socket.removeListener("data", readData); } task.callback(chunk); errCallBack(null); }; socket.on("data", readData); if (!socket) return [3 /*break*/, 4]; _loop_1 = function (command) { var fn; return __generator(this, function (_a) { switch (_a.label) { case 0: fn = function () { socket.write(Buffer.from(command, "utf8")); socket.write("\r\n"); }; if (!this_1._options.retry) return [3 /*break*/, 2]; return [4 /*yield*/, this_1._retry(fn, this_1._options.retryLimit)]; case 1: _a.sent(); return [3 /*break*/, 3]; case 2: fn(); _a.label = 3; case 3: return [2 /*return*/]; } }); }; this_1 = this; _i = 0, _a = task.commands; _b.label = 1; case 1: if (!(_i < _a.length)) return [3 /*break*/, 4]; command = _a[_i]; return [5 /*yield**/, _loop_1(command)]; case 2: _b.sent(); _b.label = 3; case 3: _i++; return [3 /*break*/, 1]; case 4: return [2 /*return*/]; } }); }); }); return _this; } Connection.prototype.connect = function (status) { return __awaiter(this, void 0, void 0, function () { var sockets; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: this.status = Status.CONNECTING; sockets = this._servers.map(function (server) { return _this._connect(server, status); }); return [4 /*yield*/, Promise.all(sockets)]; case 1: _a.sent(); return [2 /*return*/]; } }); }); }; Connection.prototype.join = function (args) { var _a; var _this = this; if (this.status === Status.CLOSE) { throw new error_1.ConnectionError("connection can't be added to close connection", error_1.ConnectionErrorCode.ER_CONN_CLOSED); } var servers = []; switch (Object.prototype.toString.call(args)) { case "[object Object]": var serverConfig = args; for (var url_2 in serverConfig) { var serverOptions = serverConfig[url_2]; servers.push(new server_1.Server(url_2, serverOptions)); } break; case "[object Array]": servers = args.map(function (url) { return new server_1.Server(url); }); break; default: var url = args; servers = [new server_1.Server(url)]; break; } (_a = this._servers).push.apply(_a, servers); servers.forEach(function (server) { _this._hashring.add(server.url); }); }; Connection.prototype.close = function (force) { // Memo(KeisukeYamashita): // // If the connection belongs to a connection pool, // make it to idle status for pooling. if (this.status !== Status.IDLE && this.status !== Status.RESEARVED) { throw new error_1.ConnectionError("can't close not open connection", error_1.ConnectionErrorCode.ER_CONN_NOT_OPEN); } if (this.id !== 0) { this._setStatus(force ? Status.CLOSE : Status.IDLE); return; } this._sockets.forEach(function (socket) { socket.remove(); socket.end(); }); this._setStatus(Status.CLOSE); this._hashring.end(); }; Connection.prototype.isReady = function () { return this.status === Status.IDLE || this.status === Status.RESEARVED; }; Connection.prototype.isIdle = function () { return this.status === Status.IDLE; }; Connection.prototype.get = function (keys, options) { return __awaiter(this, void 0, void 0, function () { var resps; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: options = __assign(__assign({}, defaultRetriveoptions), options); if (typeof keys === "string") { keys = [keys]; } return [4 /*yield*/, Promise.all(keys.map(function (key) { return __awaiter(_this, void 0, void 0, function () { var command, location, resp; return __generator(this, function (_a) { switch (_a.label) { case 0: command = "get " + key; location = this._hashring.get(key); return [4 /*yield*/, this._cmd("get", [command], location)]; case 1: resp = _a.sent(); switch (resp.code) { case response_1.ResponseCode.ERROR: case response_1.ResponseCode.SERVER_ERROR: case response_1.ResponseCode.CLIENT_ERROR: throw new Error("error"); default: return [2 /*return*/, this._deserialize(options.mode, resp)]; } return [2 /*return*/]; } }); }); }))]; case 1: resps = _a.sent(); return [2 /*return*/, this._mergeMultiGet(resps)]; } }); }); }; Connection.prototype.gets = function (keys, options) { return __awaiter(this, void 0, void 0, function () { var resps; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: options = __assign(__assign({}, defaultRetriveoptions), options); if (typeof keys === "string") { keys = [keys]; } return [4 /*yield*/, Promise.all(keys.map(function (key) { return __awaiter(_this, void 0, void 0, function () { var command, location, resp; return __generator(this, function (_a) { switch (_a.label) { case 0: command = "gets " + key; location = this._hashring.get(key); return [4 /*yield*/, this._cmd("gets", [command], location)]; case 1: resp = _a.sent(); switch (resp.code) { case response_1.ResponseCode.ERROR: case response_1.ResponseCode.SERVER_ERROR: case response_1.ResponseCode.CLIENT_ERROR: throw new Error("error"); default: return [2 /*return*/, this._deserialize(options.mode, resp)]; } return [2 /*return*/]; } }); }); }))]; case 1: resps = _a.sent(); return [2 /*return*/, this._mergeMultiGet(resps)]; } }); }); }; Connection.prototype.set = function (key, value, options) { return __awaiter(this, void 0, void 0, function () { var serializedValue, byteSize, command, location, resp; return __generator(this, function (_a) { switch (_a.label) { case 0: options = __assign(__assign({}, defaultStoreoptions), options); serializedValue = this._serialize(options === null || options === void 0 ? void 0 : options.mode, value); byteSize = Buffer.byteLength(serializedValue, "utf8"); command = "set " + key + " " + ((options === null || options === void 0 ? void 0 : options.isCompressed) ? 1 : 0) + " " + (options === null || options === void 0 ? void 0 : options.expires) + " " + byteSize; location = this._hashring.get(key); return [4 /*yield*/, this._cmd("set", [command, serializedValue], location)]; case 1: resp = _a.sent(); switch (resp.code) { case response_1.ResponseCode.EXISTS: case response_1.ResponseCode.STORED: case response_1.ResponseCode.NOT_STORED: return [2 /*return*/, resp]; default: throw new Error("error"); } return [2 /*return*/]; } }); }); }; Connection.prototype.add = function (key, value, options) { return __awaiter(this, void 0, void 0, function () { var serializedValue, byteSize, command, location, resp; return __generator(this, function (_a) { switch (_a.label) { case 0: options = __assign(__assign({}, defaultStoreoptions), options); serializedValue = this._serialize(options === null || options === void 0 ? void 0 : options.mode, value); byteSize = Buffer.byteLength(serializedValue, "utf8"); command = "add " + key + " " + (options.isCompressed ? 1 : 0) + " " + options.expires + " " + byteSize; location = this._hashring.get(key); return [4 /*yield*/, this._cmd("add", [command, serializedValue], location)]; case 1: resp = _a.sent(); switch (resp.code) { case response_1.ResponseCode.EXISTS: case response_1.ResponseCode.STORED: case response_1.ResponseCode.NOT_STORED: return [2 /*return*/, resp]; default: throw new Error("error"); } return [2 /*return*/]; } }); }); }; Connection.prototype.append = function (key, value, options) { return __awaiter(this, void 0, void 0, function () { var serializedValue, byteSize, command, location, resp; return __generator(this, function (_a) { switch (_a.label) { case 0: options = __assign(__assign({}, defaultStoreoptions), options); serializedValue = this._serialize(options === null || options === void 0 ? void 0 : options.mode, value); byteSize = Buffer.byteLength(serializedValue, "utf8"); command = "append " + key + " " + (options.isCompressed ? 1 : 0) + " " + options.expires + " " + byteSize; location = this._hashring.get(key); return [4 /*yield*/, this._cmd("append", [command, serializedValue], location)]; case 1: resp = _a.sent(); switch (resp.code) { case response_1.ResponseCode.STORED: case response_1.ResponseCode.NOT_STORED: return [2 /*return*/, resp]; default: throw new Error("error"); } return [2 /*return*/]; } }); }); }; Connection.prototype.prepend = function (key, value, options) { return __awaiter(this, void 0, void 0, function () { var serializedValue, byteSize, command, location, resp; return __generator(this, function (_a) { switch (_a.label) { case 0: options = __assign(__assign({}, defaultStoreoptions), options); serializedValue = this._serialize(options === null || options === void 0 ? void 0 : options.mode, value); byteSize = Buffer.byteLength(serializedValue, "utf8"); command = "prepend " + key + " " + (options.isCompressed ? 1 : 0) + " " + options.expires + " " + byteSize; location = this._hashring.get(key); return [4 /*yield*/, this._cmd("prepend", [command, serializedValue], location)]; case 1: resp = _a.sent(); switch (resp.code) { case response_1.ResponseCode.STORED: case response_1.ResponseCode.NOT_STORED: return [2 /*return*/, resp]; default: throw new Error("error"); } return [2 /*return*/]; } }); }); }; Connection.prototype.replace = function (key, value, options) { return __awaiter(this, void 0, void 0, function () { var serializedValue, byteSize, command, location, resp; return __generator(this, function (_a) { switch (_a.label) { case 0: options = __assign(__assign({}, defaultStoreoptions), options); serializedValue = this._serialize(options === null || options === void 0 ? void 0 : options.mode, value); byteSize = Buffer.byteLength(serializedValue, "utf8"); command = "replace " + key + " " + (options.isCompressed ? 1 : 0) + " " + options.expires + " " + byteSize; location = this._hashring.get(key); return [4 /*yield*/, this._cmd("replace", [command, serializedValue], location)]; case 1: resp = _a.sent(); switch (resp.code) { case response_1.ResponseCode.STORED: case response_1.ResponseCode.NOT_STORED: return [2 /*return*/, this._deserialize(options.mode, resp)]; default: throw new Error("error"); } return [2 /*return*/]; } }); }); }; Connection.prototype.cas = function (key, value, casId, options) { return __awaiter(this, void 0, void 0, function () { var serializedValue, byteSize, command, location, resp; return __generator(this, function (_a) { switch (_a.label) { case 0: options = __assign(__assign({}, defaultStoreoptions), options); serializedValue = this._serialize(options === null || options === void 0 ? void 0 : options.mode, value); byteSize = Buffer.byteLength(serializedValue, "utf8"); command = "cas " + key + " " + (options.isCompressed ? 1 : 0) + " " + options.expires + " " + byteSize + " " + casId; location = this._hashring.get(key); return [4 /*yield*/, this._cmd("cas", [command, serializedValue], location)]; case 1: resp = _a.sent(); switch (resp.code) { case response_1.ResponseCode.EXISTS: case response_1.ResponseCode.STORED: case response_1.ResponseCode.NOT_STORED: return [2 /*return*/, resp]; default: throw new Error("error"); } return [2 /*return*/]; } }); }); }; Connection.prototype.gat = function (keys, expire, options) { return __awaiter(this, void 0, void 0, function () { var resps; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: options = __assign(__assign({}, defaultRetriveoptions), options); if (typeof keys === "string") { keys = [keys]; } return [4 /*yield*/, Promise.all(keys.map(function (key) { return __awaiter(_this, void 0, void 0, function () { var command, location, resp; return __generator(this, function (_a) { switch (_a.label) { case 0: command = "gat " + expire + " " + key; location = this._hashring.get(key); return [4 /*yield*/, this._cmd("gat", [command], location)]; case 1: resp = _a.sent(); switch (resp.code) { case response_1.ResponseCode.ERROR: case response_1.ResponseCode.SERVER_ERROR: case response_1.ResponseCode.CLIENT_ERROR: throw new Error("error"); default: return [2 /*return*/, this._deserialize(options.mode, resp)]; } return [2 /*return*/]; } }); }); }))]; case 1: resps = _a.sent(); return [2 /*return*/, this._mergeMultiGet(resps)]; } }); }); }; Connection.prototype.gats = function (keys, expire, options) { return __awaiter(this, void 0, void 0, function () { var resps; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: options = __assign(__assign({}, defaultRetriveoptions), options); if (typeof keys === "string") { keys = [keys]; } return [4 /*yield*/, Promise.all(keys.map(function (key) { return __awaiter(_this, void 0, void 0, function () { var command, location, resp; return __generator(this, function (_a) { switch (_a.label) { case 0: command = "gats " + expire + " " + key; location = this._hashring.get(key); return [4 /*yield*/, this._cmd("gats", [command], location)]; case 1: resp = _a.sent(); switch (resp.code) { case response_1.ResponseCode.ERROR: case response_1.ResponseCode.SERVER_ERROR: case response_1.ResponseCode.CLIENT_ERROR: throw new Error("error"); default: return [2 /*return*/, this._deserialize(options.mode, resp)]; } return [2 /*return*/]; } }); }); }))]; case 1: resps = _a.sent(); return [2 /*return*/, this._mergeMultiGet(resps)]; } }); }); }; Connection.prototype.delete = function (key) { return __awaiter(this, void 0, void 0, function () { var command, location, resp; return __generator(this, function (_a) { switch (_a.label) { case 0: command = "delete " + key; location = this._hashring.get(key); return [4 /*yield*/, this._cmd("delete", [command], location)]; case 1: resp = _a.sent(); switch (resp.code) { case response_1.ResponseCode.DELETED: case response_1.ResponseCode.NOT_FOUND: return [2 /*return*/, resp]; default: throw new Error("error"); } return [2 /*return*/]; } }); }); }; Connection.prototype.remove = function (url) { this._hashring.remove(url); if (this._sockets.length === 0) { this._setStatus(Status.CLOSE); this.emit("close", this); } }; Connection.prototype.touch = function (key, expire) { return __awaiter(this, void 0, void 0, function () { var command, location, resp; return __generator(this, function (_a) { switch (_a.label) { case 0: command = "touch " + key + " " + expire; location = this._hashring.get(key); return [4 /*yield*/, this._cmd("touch", [command], location)]; case 1: resp = _a.sent(); switch (resp.code) { case response_1.ResponseCode.TOUCHED: case response_1.ResponseCode.NOT_FOUND: return [2 /*return*/, resp]; default: throw new Error("error"); } return [2 /*return*/]; } }); }); }; Connection.prototype.stats = function () { return __awaiter(this, void 0, void 0, function () { var command, results, resp; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: command = "stats"; return [4 /*yield*/, Promise.all(this._servers.map(function (server) { return __awaiter(_this, void 0, void 0, function () { var location, resp; return __generator(this, function (_a) { switch (_a.label) { case 0: location = server.url; return [4 /*yield*/, this._cmd(command, [command], location)]; case 1: resp = _a.sent(); return [2 /*return*/, { location: location, resp: resp }]; } }); }); }))]; case 1: results = _a.sent(); resp = { code: response_1.ResponseCode.END, stats: {}, }; results.forEach(function (r) { switch (r.resp.code) { case response_1.ResponseCode.END: break; default: throw new Error("error"); } var statsu = r.resp.stats; resp.stats[r.location] = statsu; }); return [2 /*return*/, resp]; } }); }); }; Connection.prototype._connect = function (server, status) { return __awaiter(this, void 0, void 0, function () { var _this = this; return __generator(this, function (_a) { return [2 /*return*/, new Promise(function (resolve, reject) { var connectOptions = { host: server.host, port: server.port, timeout: _this._options.timeout, }; var socket = net.connect(connectOptions); var memSocket = new socket_1.MemcachedSocket(socket, server); memSocket.on("error", function (err) { reject(err); if (_this.listeners("error").length > 0) { _this.emit("error", err, server); } }); memSocket.on("timeout", function () { reject(new error_1.ConnectionError("timeout", error_1.ConnectionErrorCode.ER_CONN_TIMEOUT)); if (_this.listeners("timeout").length > 0) { _this.emit("timeout", server); } }); memSocket.on("close", function () { return _this._handleSocketClose(server); }); memSocket.on("connect", function () { _this._setStatus(status || Status.RESEARVED); _this._sockets.push(memSocket); resolve(); }); })]; }); }); }; Connection.prototype._cmd = function (command, commands, location) { return __awaiter(this, void 0, void 0, function () { var _this = this; return __generator(this, function (_a) { return [2 /*return*/, new Promise(function (resolve, reject) { _this._queue.push({ commands: commands, location: location, callback: function (chunk) { var code = response_1.parseResponseCode(chunk); if (command === "stats") { var stats = response_1.parseStatResponse(chunk); resolve({ code: code, stats: stats }); return; } var data = response_1.parseResponse(chunk); resolve({ code: code, data: data }); }, }, function (err) { if (err) reject(err); }); })]; }); }); }; Connection.prototype._handleSocketClose = function (server) { this._remove(server); if (this._sockets.length === 0) { this._setStatus(Status.CLOSE); if (this.listeners("close").length > 0) { this.emit("close", this); } } }; Connection.prototype._mergeMultiGet = function (resps) { var result = { code: response_1.ResponseCode.END, data: {}, }; resps.forEach(function (resp) { if (resp.code !== response_1.ResponseCode.END) { throw new Error("not all end with END"); } Object.keys(resp.data).forEach(function (key) { var value = resp.data[key]; result.data[key] = value; }); }); return result; }; // Connection's internal remove will emit the 'drop' event Connection.prototype._remove = function (server) { var url; if (typeof server === "string") { url = server; } else { url = server.url; } if (this._options.removeDeadServer) { this._hashring.remove(url); this._sockets = this._sockets.filter(function (socket) { return socket.server.url !== url; }); if (this.listeners("drop").length > 0) { this.emit("drop", this, server); } } }; Connection.prototype._retry = function (fn, retryLimit) { return __awaiter(this, void 0, void 0, function () { var attemp, err, wait, funcErr_1; var _this = this; return __generator(this, function (_a) { switch (_a.label) { case 0: attemp = 0; wait = function (attempt) { var waitSec = _this._options.exponentialBackoff ? function () { return 100; } : function (attempt) { return Math.pow(2, attempt); }; return new Promise(function (resolve) { setTimeout(function () { resolve(); }, waitSec(attempt)); }); }; _a.label = 1; case 1: if (!true) return [3 /*break*/, 7]; if (attemp >= retryLimit) { throw err; } _a.label = 2; case 2: _a.trys.push([2, 4, , 6]); return [4 /*yield*/, fn()]; case 3: return [2 /*return*/, _a.sent()]; case 4: funcErr_1 = _a.sent(); err = funcErr_1; return [4 /*yield*/, wait()]; case 5: _a.sent(); attemp++; return [3 /*break*/, 6]; case 6: return [3 /*break*/, 1]; case 7: return [2 /*return*/]; } }); }); }; Connection.prototype._serialize = function (mode, value) { if (mode === void 0) { mode = "string"; } if (mode === "string" && typeof value === "string") { return value; } switch (mode) { case "json": return JSON.stringify(value); default: throw new Error("not supported serialize mode " + mode + " with Objects"); } }; Connection.prototype._deserialize = function (mode, resp) { if (mode === void 0) { mode = "string"; } if (mode === "string") { return resp; } Object.keys(resp.data).forEach(function (key) { var data = resp.data[key]; var value; switch (mode) { case "json": value = JSON.parse(data.value); break; default: throw new Error("not supported serialize mode " + mode + " with Objects"); } resp.data[key].value = value; }); return resp; }; Connection.prototype._setStatus = function (newStatus) { var oldStatus = this.status; this.status = newStatus; if (this.listeners("changeStatus").length > 0) { this.emit("changeStatus", this.id, newStatus, oldStatus); } }; return Connection; }(events_1.EventEmitter)); exports.Connection = Connection; function createConnection(args, options) { return new Connection(args, 0, options); } exports.createConnection = createConnection;