memcached-node
Version:
Node.js client for memcached
874 lines (873 loc) • 42 kB
JavaScript
"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;