@routr/location 2.0.5-alpha.2 → 2.0.5-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config/get_config.js +31 -33
- package/dist/config/schema.d.ts +12 -0
- package/dist/config/schema.js +13 -1
- package/dist/errors.js +29 -59
- package/dist/locator.js +42 -93
- package/dist/memory_store.js +23 -47
- package/dist/redis_store.d.ts +8 -0
- package/dist/redis_store.js +87 -0
- package/dist/runner.js +4 -4
- package/dist/service.js +38 -6
- package/dist/types.d.ts +15 -0
- package/dist/types.js +6 -1
- package/dist/utils.d.ts +3 -1
- package/dist/utils.js +65 -95
- package/package.json +5 -4
|
@@ -1,15 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __assign = (this && this.__assign) || function () {
|
|
3
|
-
__assign = Object.assign || function(t) {
|
|
4
|
-
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
5
|
-
s = arguments[i];
|
|
6
|
-
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
7
|
-
t[p] = s[p];
|
|
8
|
-
}
|
|
9
|
-
return t;
|
|
10
|
-
};
|
|
11
|
-
return __assign.apply(this, arguments);
|
|
12
|
-
};
|
|
13
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
14
3
|
if (k2 === undefined) k2 = k;
|
|
15
4
|
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
@@ -52,41 +41,50 @@ exports.getConfig = void 0;
|
|
|
52
41
|
* See the License for the specific language governing permissions and
|
|
53
42
|
* limitations under the License.
|
|
54
43
|
*/
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
44
|
+
const types_1 = require("../types");
|
|
45
|
+
const fs_1 = __importDefault(require("fs"));
|
|
46
|
+
const schema_1 = require("./schema");
|
|
47
|
+
const ajv_1 = __importDefault(require("ajv"));
|
|
48
|
+
const E = __importStar(require("fp-ts/Either"));
|
|
49
|
+
const errors_1 = require("../errors");
|
|
50
|
+
const ajv = new ajv_1.default();
|
|
51
|
+
const validate = ajv.compile(schema_1.schema);
|
|
52
|
+
const hasBadCombiniation = (backends) => backends.some((b) => b.balancingAlgorithm === types_1.LB_ALGORITHM.ROUND_ROBIN && b.sessionAffinity);
|
|
53
|
+
const hasBadAlgorithm = (backends) => backends.some((b) => b.balancingAlgorithm !== types_1.LB_ALGORITHM.ROUND_ROBIN
|
|
54
|
+
&& b.balancingAlgorithm !== types_1.LB_ALGORITHM.LEAST_SESSIONS);
|
|
55
|
+
const getConfig = (path) => {
|
|
56
|
+
var _a, _b, _c;
|
|
57
|
+
const c = JSON.parse(fs_1.default.readFileSync(path, "utf8"));
|
|
58
|
+
if (!validate(Object.assign({}, c))) {
|
|
66
59
|
return E.left(new errors_1.InvalidSchemaConfiguration(JSON.stringify(validate.errors[0].message)));
|
|
67
60
|
}
|
|
68
|
-
|
|
61
|
+
const config = c.spec;
|
|
69
62
|
if (config.backends) {
|
|
70
|
-
config.backends.map(
|
|
63
|
+
config.backends.map((b) => {
|
|
71
64
|
// Setting round-robin by default
|
|
72
65
|
b.balancingAlgorithm = b.balancingAlgorithm
|
|
73
66
|
? b.balancingAlgorithm : types_1.LB_ALGORITHM.ROUND_ROBIN;
|
|
74
67
|
return b;
|
|
75
68
|
});
|
|
76
|
-
|
|
77
|
-
return b.balancingAlgorithm === types_1.LB_ALGORITHM.ROUND_ROBIN && b.sessionAffinity;
|
|
78
|
-
});
|
|
79
|
-
var hasBadAlgorithm = config.backends.some(function (b) {
|
|
80
|
-
return b.balancingAlgorithm !== types_1.LB_ALGORITHM.ROUND_ROBIN
|
|
81
|
-
&& b.balancingAlgorithm !== types_1.LB_ALGORITHM.LEAST_SESSIONS;
|
|
82
|
-
});
|
|
83
|
-
if (hasBadCombiniation) {
|
|
69
|
+
if (hasBadCombiniation(config.backends)) {
|
|
84
70
|
return E.left(new errors_1.BadAlgorithmAndAffinityCombination());
|
|
85
71
|
}
|
|
86
|
-
if (hasBadAlgorithm) {
|
|
72
|
+
if (hasBadAlgorithm(config.backends)) {
|
|
87
73
|
return E.left(new errors_1.InvalidLoadBalancerAlgorithm());
|
|
88
74
|
}
|
|
89
75
|
}
|
|
76
|
+
if (!((_a = config === null || config === void 0 ? void 0 : config.cache) === null || _a === void 0 ? void 0 : _a.provider)) {
|
|
77
|
+
config.cache = {
|
|
78
|
+
provider: types_1.CACHE_PROVIDER.MEMORY
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
if (((_b = config === null || config === void 0 ? void 0 : config.cache) === null || _b === void 0 ? void 0 : _b.provider) === types_1.CACHE_PROVIDER.REDIS &&
|
|
82
|
+
!((_c = config === null || config === void 0 ? void 0 : config.cache) === null || _c === void 0 ? void 0 : _c.parameters)) {
|
|
83
|
+
config.cache = {
|
|
84
|
+
provider: types_1.CACHE_PROVIDER.REDIS,
|
|
85
|
+
parameters: "host=localhost,port=6379"
|
|
86
|
+
};
|
|
87
|
+
}
|
|
90
88
|
return E.right(config);
|
|
91
89
|
};
|
|
92
90
|
exports.getConfig = getConfig;
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -22,6 +22,18 @@ export declare const schema: {
|
|
|
22
22
|
description: string;
|
|
23
23
|
type: string;
|
|
24
24
|
};
|
|
25
|
+
cache: {
|
|
26
|
+
type: string;
|
|
27
|
+
properties: {
|
|
28
|
+
provider: {
|
|
29
|
+
enum: string[];
|
|
30
|
+
};
|
|
31
|
+
parameters: {
|
|
32
|
+
type: string;
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
required: string[];
|
|
36
|
+
};
|
|
25
37
|
backends: {
|
|
26
38
|
description: string;
|
|
27
39
|
type: string;
|
package/dist/config/schema.js
CHANGED
|
@@ -43,6 +43,18 @@ exports.schema = {
|
|
|
43
43
|
"description": "Ipv4 interface to accept request on",
|
|
44
44
|
"type": "string"
|
|
45
45
|
},
|
|
46
|
+
"cache": {
|
|
47
|
+
"type": "object",
|
|
48
|
+
"properties": {
|
|
49
|
+
"provider": {
|
|
50
|
+
"enum": ["memory", "redis"]
|
|
51
|
+
},
|
|
52
|
+
"parameters": {
|
|
53
|
+
"type": "string"
|
|
54
|
+
},
|
|
55
|
+
},
|
|
56
|
+
"required": ["provider"]
|
|
57
|
+
},
|
|
46
58
|
"backends": {
|
|
47
59
|
"description": "Optional SIP backends",
|
|
48
60
|
"type": "array",
|
|
@@ -54,7 +66,7 @@ exports.schema = {
|
|
|
54
66
|
"type": "string"
|
|
55
67
|
},
|
|
56
68
|
"balancingAlgorithm": {
|
|
57
|
-
"enum": ["
|
|
69
|
+
"enum": ["round-robin", "least-sessions"]
|
|
58
70
|
},
|
|
59
71
|
"sessionAffinity": {
|
|
60
72
|
"description": "Optional session affinity",
|
package/dist/errors.js
CHANGED
|
@@ -1,19 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __extends = (this && this.__extends) || (function () {
|
|
3
|
-
var extendStatics = function (d, b) {
|
|
4
|
-
extendStatics = Object.setPrototypeOf ||
|
|
5
|
-
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
6
|
-
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
7
|
-
return extendStatics(d, b);
|
|
8
|
-
};
|
|
9
|
-
return function (d, b) {
|
|
10
|
-
if (typeof b !== "function" && b !== null)
|
|
11
|
-
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
12
|
-
extendStatics(d, b);
|
|
13
|
-
function __() { this.constructor = d; }
|
|
14
|
-
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
15
|
-
};
|
|
16
|
-
})();
|
|
17
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
3
|
exports.InvalidLoadBalancerAlgorithm = exports.BadAlgorithmAndAffinityCombination = exports.InvalidSchemaConfiguration = exports.NotRoutesFoundForAOR = exports.UnsupportedSchema = void 0;
|
|
19
4
|
/*
|
|
@@ -34,58 +19,43 @@ exports.InvalidLoadBalancerAlgorithm = exports.BadAlgorithmAndAffinityCombinatio
|
|
|
34
19
|
* See the License for the specific language governing permissions and
|
|
35
20
|
* limitations under the License.
|
|
36
21
|
*/
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
_this.code = grpc.status.INVALID_ARGUMENT;
|
|
22
|
+
const grpc = require("@grpc/grpc-js");
|
|
23
|
+
class UnsupportedSchema extends Error {
|
|
24
|
+
constructor(aor) {
|
|
25
|
+
super(`aor ${aor} has an invalid schema, only "sip:" or "backend:" are allowed`);
|
|
26
|
+
this.code = grpc.status.INVALID_ARGUMENT;
|
|
43
27
|
// Set the prototype explicitly.
|
|
44
|
-
Object.setPrototypeOf(
|
|
45
|
-
return _this;
|
|
28
|
+
Object.setPrototypeOf(this, UnsupportedSchema.prototype);
|
|
46
29
|
}
|
|
47
|
-
|
|
48
|
-
}(Error));
|
|
30
|
+
}
|
|
49
31
|
exports.UnsupportedSchema = UnsupportedSchema;
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
Object.setPrototypeOf(_this, NotRoutesFoundForAOR.prototype);
|
|
56
|
-
return _this;
|
|
32
|
+
class NotRoutesFoundForAOR extends Error {
|
|
33
|
+
constructor(aor) {
|
|
34
|
+
super(`no routes found for aor ${aor}`);
|
|
35
|
+
this.code = grpc.status.NOT_FOUND;
|
|
36
|
+
Object.setPrototypeOf(this, NotRoutesFoundForAOR.prototype);
|
|
57
37
|
}
|
|
58
|
-
|
|
59
|
-
}(Error));
|
|
38
|
+
}
|
|
60
39
|
exports.NotRoutesFoundForAOR = NotRoutesFoundForAOR;
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
Object.setPrototypeOf(_this, InvalidSchemaConfiguration.prototype);
|
|
67
|
-
return _this;
|
|
40
|
+
class InvalidSchemaConfiguration extends Error {
|
|
41
|
+
constructor(msg) {
|
|
42
|
+
super(msg);
|
|
43
|
+
this.code = grpc.status.INVALID_ARGUMENT;
|
|
44
|
+
Object.setPrototypeOf(this, InvalidSchemaConfiguration.prototype);
|
|
68
45
|
}
|
|
69
|
-
|
|
70
|
-
}(Error));
|
|
46
|
+
}
|
|
71
47
|
exports.InvalidSchemaConfiguration = InvalidSchemaConfiguration;
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
Object.setPrototypeOf(_this, BadAlgorithmAndAffinityCombination.prototype);
|
|
77
|
-
return _this;
|
|
48
|
+
class BadAlgorithmAndAffinityCombination extends Error {
|
|
49
|
+
constructor() {
|
|
50
|
+
super("session affinity can not be combined with round-robin load balancing");
|
|
51
|
+
Object.setPrototypeOf(this, BadAlgorithmAndAffinityCombination.prototype);
|
|
78
52
|
}
|
|
79
|
-
|
|
80
|
-
}(Error));
|
|
53
|
+
}
|
|
81
54
|
exports.BadAlgorithmAndAffinityCombination = BadAlgorithmAndAffinityCombination;
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
Object.setPrototypeOf(_this, BadAlgorithmAndAffinityCombination.prototype);
|
|
87
|
-
return _this;
|
|
55
|
+
class InvalidLoadBalancerAlgorithm extends Error {
|
|
56
|
+
constructor() {
|
|
57
|
+
super("found invalid load balancing algorithm. must be round-robin or least-sessions");
|
|
58
|
+
Object.setPrototypeOf(this, BadAlgorithmAndAffinityCombination.prototype);
|
|
88
59
|
}
|
|
89
|
-
|
|
90
|
-
}(Error));
|
|
60
|
+
}
|
|
91
61
|
exports.InvalidLoadBalancerAlgorithm = InvalidLoadBalancerAlgorithm;
|
package/dist/locator.js
CHANGED
|
@@ -8,33 +8,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
13
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
-
function step(op) {
|
|
16
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
-
while (_) try {
|
|
18
|
-
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;
|
|
19
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
-
switch (op[0]) {
|
|
21
|
-
case 0: case 1: t = op; break;
|
|
22
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
-
default:
|
|
26
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
-
if (t[2]) _.ops.pop();
|
|
31
|
-
_.trys.pop(); continue;
|
|
32
|
-
}
|
|
33
|
-
op = body.call(thisArg, _);
|
|
34
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
12
|
/*
|
|
40
13
|
* Copyright (C) 2022 by Fonoster Inc (https://fonoster.com)
|
|
@@ -54,99 +27,75 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
54
27
|
* See the License for the specific language governing permissions and
|
|
55
28
|
* limitations under the License.
|
|
56
29
|
*/
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
30
|
+
const errors_1 = require("./errors");
|
|
31
|
+
const types_1 = require("./types");
|
|
32
|
+
const utils_1 = require("./utils");
|
|
33
|
+
class Locator {
|
|
61
34
|
// Should fail if any backend has sessionAffinity and round-robin
|
|
62
|
-
|
|
63
|
-
var _this = this;
|
|
64
|
-
if (backends === void 0) { backends = new Map(); }
|
|
35
|
+
constructor(store, backends = new Map()) {
|
|
65
36
|
this.store = store;
|
|
66
37
|
this.backends = backends;
|
|
67
38
|
this.rrCount = new Map();
|
|
68
39
|
this.affinityStore = new Map();
|
|
69
|
-
this.backends.forEach(
|
|
40
|
+
this.backends.forEach((value, key) => this.rrCount.set(key, 0));
|
|
70
41
|
}
|
|
71
|
-
|
|
42
|
+
addRoute(request) {
|
|
72
43
|
if (!request.aor.startsWith('sip:') &&
|
|
73
44
|
!request.aor.startsWith('backend:')) {
|
|
74
45
|
throw new errors_1.UnsupportedSchema(request.aor);
|
|
75
46
|
}
|
|
76
47
|
return this.store.put(request.aor, request.route);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
case 3:
|
|
92
|
-
_a = (_d.sent()) || [];
|
|
93
|
-
_d.label = 4;
|
|
94
|
-
case 4:
|
|
95
|
-
routes = _a;
|
|
96
|
-
if (!request.aor.startsWith('sip:')) return [3 /*break*/, 5];
|
|
97
|
-
return [2 /*return*/, routes];
|
|
98
|
-
case 5:
|
|
99
|
-
if (!request.aor.startsWith('backend:')) return [3 /*break*/, 9];
|
|
100
|
-
backend = this.backends.get(request.aor);
|
|
101
|
-
if (!backend) {
|
|
102
|
-
throw new errors_1.NotRoutesFoundForAOR(request.aor);
|
|
103
|
-
}
|
|
104
|
-
if (!!utils_1.hasAffinitySession(backend)) return [3 /*break*/, 6];
|
|
105
|
-
_b = [this.next(routes, backend)];
|
|
106
|
-
return [3 /*break*/, 8];
|
|
107
|
-
case 6:
|
|
108
|
-
_c = this.nextWithAffinity;
|
|
109
|
-
return [4 /*yield*/, routes];
|
|
110
|
-
case 7:
|
|
111
|
-
_b = [_c.apply(this, [_d.sent(), backend.sessionAffinity.ref])];
|
|
112
|
-
_d.label = 8;
|
|
113
|
-
case 8:
|
|
114
|
-
// If it has not affinity sesssion then get next
|
|
115
|
-
return [2 /*return*/, _b];
|
|
116
|
-
case 9: throw new errors_1.UnsupportedSchema(request.aor);
|
|
48
|
+
}
|
|
49
|
+
findRoutes(request) {
|
|
50
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
51
|
+
const routes = request.labels
|
|
52
|
+
? (yield this.store.get(request.aor))
|
|
53
|
+
.filter(utils_1.filterOnlyMatchingLabels(request.labels))
|
|
54
|
+
: (yield this.store.get(request.aor)) || [];
|
|
55
|
+
if (request.aor.startsWith('sip:')) {
|
|
56
|
+
return routes;
|
|
57
|
+
}
|
|
58
|
+
else if (request.aor.startsWith('backend:')) {
|
|
59
|
+
const backend = this.backends.get(request.aor);
|
|
60
|
+
if (!backend) {
|
|
61
|
+
throw new errors_1.NotRoutesFoundForAOR(request.aor);
|
|
117
62
|
}
|
|
118
|
-
|
|
63
|
+
// If it has not affinity sesssion then get next
|
|
64
|
+
return !utils_1.hasAffinitySession(backend)
|
|
65
|
+
? [this.next(routes, backend)]
|
|
66
|
+
: [this.nextWithAffinity(yield routes, backend.sessionAffinity.ref)];
|
|
67
|
+
}
|
|
68
|
+
throw new errors_1.UnsupportedSchema(request.aor);
|
|
119
69
|
});
|
|
120
|
-
}
|
|
121
|
-
|
|
70
|
+
}
|
|
71
|
+
removeRoutes(request) {
|
|
122
72
|
return this.store.delete(request.aor);
|
|
123
|
-
}
|
|
124
|
-
|
|
73
|
+
}
|
|
74
|
+
next(routes, backend) {
|
|
125
75
|
if (backend.balancingAlgorithm === types_1.LB_ALGORITHM.LEAST_SESSIONS) {
|
|
126
|
-
return routes.sort(
|
|
76
|
+
return routes.sort((r1, r2) => r1.sessionCount - r2.sessionCount)[0];
|
|
127
77
|
}
|
|
128
78
|
// Continues using round-robin
|
|
129
|
-
|
|
130
|
-
|
|
79
|
+
const nextPosition = this.rrCount.get(`backend:${backend.ref}`);
|
|
80
|
+
const result = routes[nextPosition];
|
|
131
81
|
if (nextPosition >= (routes.length - 1)) {
|
|
132
82
|
// Restarting round-robin counter
|
|
133
|
-
this.rrCount.set(
|
|
83
|
+
this.rrCount.set(`backend:${backend.ref}`, 0);
|
|
134
84
|
}
|
|
135
85
|
else {
|
|
136
|
-
this.rrCount.set(
|
|
86
|
+
this.rrCount.set(`backend:${backend.ref}`, nextPosition + 1);
|
|
137
87
|
}
|
|
138
88
|
return result;
|
|
139
|
-
}
|
|
89
|
+
}
|
|
140
90
|
// Backend with session affinity does not support round-robin
|
|
141
|
-
|
|
142
|
-
|
|
91
|
+
nextWithAffinity(routes, sessionAffinityRef) {
|
|
92
|
+
let route = this.affinityStore.get(sessionAffinityRef);
|
|
143
93
|
if (route) {
|
|
144
94
|
return route;
|
|
145
95
|
}
|
|
146
|
-
route = routes.sort(
|
|
96
|
+
route = routes.sort((r1, r2) => r1.sessionCount - r2.sessionCount)[0];
|
|
147
97
|
this.affinityStore.set(sessionAffinityRef, route);
|
|
148
98
|
return route;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
}());
|
|
99
|
+
}
|
|
100
|
+
}
|
|
152
101
|
exports.default = Locator;
|
package/dist/memory_store.js
CHANGED
|
@@ -1,49 +1,27 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __read = (this && this.__read) || function (o, n) {
|
|
3
|
-
var m = typeof Symbol === "function" && o[Symbol.iterator];
|
|
4
|
-
if (!m) return o;
|
|
5
|
-
var i = m.call(o), r, ar = [], e;
|
|
6
|
-
try {
|
|
7
|
-
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
|
|
8
|
-
}
|
|
9
|
-
catch (error) { e = { error: error }; }
|
|
10
|
-
finally {
|
|
11
|
-
try {
|
|
12
|
-
if (r && !r.done && (m = i["return"])) m.call(i);
|
|
13
|
-
}
|
|
14
|
-
finally { if (e) throw e.error; }
|
|
15
|
-
}
|
|
16
|
-
return ar;
|
|
17
|
-
};
|
|
18
|
-
var __spreadArray = (this && this.__spreadArray) || function (to, from) {
|
|
19
|
-
for (var i = 0, il = from.length, j = to.length; i < il; i++, j++)
|
|
20
|
-
to[j] = from[i];
|
|
21
|
-
return to;
|
|
22
|
-
};
|
|
23
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
if (maxCyclesBeforeCleanup === void 0) { maxCyclesBeforeCleanup = MAX_CYCLES_BEFORE_CLEANUP; }
|
|
3
|
+
const utils_1 = require("./utils");
|
|
4
|
+
const MAX_CYCLES_BEFORE_CLEANUP = 10000;
|
|
5
|
+
class MemoryStore {
|
|
6
|
+
constructor(maxCyclesBeforeCleanup = MAX_CYCLES_BEFORE_CLEANUP) {
|
|
29
7
|
this.collections = new Map();
|
|
30
8
|
this.maxCyclesBeforeCleanup = maxCyclesBeforeCleanup;
|
|
31
9
|
}
|
|
32
|
-
|
|
33
|
-
|
|
10
|
+
put(key, route) {
|
|
11
|
+
const routes = [...this.collections.get(key) || []];
|
|
34
12
|
// Avoids duplicate or expired routes
|
|
35
|
-
|
|
13
|
+
const filteredRoutes = routes
|
|
36
14
|
.filter(utils_1.expiredFilter)
|
|
37
|
-
.filter(
|
|
15
|
+
.filter(r => utils_1.duplicateFilter(r, route));
|
|
38
16
|
if (filteredRoutes.length > 0) {
|
|
39
|
-
this.collections.set(key,
|
|
17
|
+
this.collections.set(key, [route, ...filteredRoutes]);
|
|
40
18
|
}
|
|
41
19
|
else {
|
|
42
20
|
this.collections.set(key, [route]);
|
|
43
21
|
}
|
|
44
22
|
return;
|
|
45
|
-
}
|
|
46
|
-
|
|
23
|
+
}
|
|
24
|
+
get(key) {
|
|
47
25
|
// Cleanup every so often to avoid memory build up
|
|
48
26
|
this.cleanupCount++;
|
|
49
27
|
if (this.cleanupCount >= this.maxCyclesBeforeCleanup) {
|
|
@@ -51,27 +29,25 @@ var MemoryStore = /** @class */ (function () {
|
|
|
51
29
|
this.cleanup();
|
|
52
30
|
}
|
|
53
31
|
return Promise.resolve(this.collections.get(key) || []);
|
|
54
|
-
}
|
|
55
|
-
|
|
32
|
+
}
|
|
33
|
+
delete(key) {
|
|
56
34
|
this.collections.delete(key);
|
|
57
35
|
return;
|
|
58
|
-
}
|
|
59
|
-
|
|
36
|
+
}
|
|
37
|
+
size() {
|
|
60
38
|
return this.collections.size;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
var _this = this;
|
|
39
|
+
}
|
|
40
|
+
cleanup() {
|
|
64
41
|
// Remove any expired route from collection
|
|
65
|
-
this.collections.forEach(
|
|
66
|
-
|
|
42
|
+
this.collections.forEach((routes, key) => {
|
|
43
|
+
const filteredRoutes = routes.filter(utils_1.expiredFilter);
|
|
67
44
|
if (filteredRoutes.length > 0) {
|
|
68
|
-
|
|
45
|
+
this.collections.set(key, filteredRoutes);
|
|
69
46
|
}
|
|
70
47
|
else {
|
|
71
|
-
|
|
48
|
+
this.collections.delete(key);
|
|
72
49
|
}
|
|
73
50
|
});
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
}());
|
|
51
|
+
}
|
|
52
|
+
}
|
|
77
53
|
exports.default = MemoryStore;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ILocatorStore, RedisStoreConfig, Route } from "./types";
|
|
2
|
+
export default class RedisStore implements ILocatorStore {
|
|
3
|
+
client: any;
|
|
4
|
+
constructor(config?: RedisStoreConfig);
|
|
5
|
+
put(key: string, route: Route): Promise<void>;
|
|
6
|
+
get(key: string): Promise<Route[]>;
|
|
7
|
+
delete(key: string): Promise<void>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
12
|
+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
13
|
+
var m = o[Symbol.asyncIterator], i;
|
|
14
|
+
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
|
|
15
|
+
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
|
16
|
+
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
17
|
+
};
|
|
18
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
19
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
20
|
+
};
|
|
21
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
|
+
const redis_1 = require("redis");
|
|
23
|
+
const utils_1 = require("./utils");
|
|
24
|
+
const logger_1 = __importDefault(require("@fonoster/logger"));
|
|
25
|
+
class RedisStore {
|
|
26
|
+
constructor(config) {
|
|
27
|
+
this.client = config ? redis_1.createClient({ url: utils_1.getUrlString(config) }) : redis_1.createClient();
|
|
28
|
+
this.client.connect();
|
|
29
|
+
this.client.on('error', (err) => logger_1.default.error('redis client error: ', err));
|
|
30
|
+
}
|
|
31
|
+
put(key, route) {
|
|
32
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
33
|
+
// Formatted the key to ensure it is unique
|
|
34
|
+
logger_1.default.verbose(`${key}:${route.user}${route.host}${route.port}`);
|
|
35
|
+
yield this.client.set(`${key}:${route.user}${route.host}${route.port}`, JSON.stringify(route), {
|
|
36
|
+
EX: route.expires
|
|
37
|
+
});
|
|
38
|
+
return;
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
get(key) {
|
|
42
|
+
var e_1, _a;
|
|
43
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
44
|
+
const routes = [];
|
|
45
|
+
try {
|
|
46
|
+
for (var _b = __asyncValues(yield this.client.scanIterator({
|
|
47
|
+
CURSOR: 0,
|
|
48
|
+
MATCH: `${key}:*`
|
|
49
|
+
})), _c; _c = yield _b.next(), !_c.done;) {
|
|
50
|
+
const k = _c.value;
|
|
51
|
+
routes.push(JSON.parse(yield this.client.get(k)));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
55
|
+
finally {
|
|
56
|
+
try {
|
|
57
|
+
if (_c && !_c.done && (_a = _b.return)) yield _a.call(_b);
|
|
58
|
+
}
|
|
59
|
+
finally { if (e_1) throw e_1.error; }
|
|
60
|
+
}
|
|
61
|
+
return routes;
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
delete(key) {
|
|
65
|
+
var e_2, _a;
|
|
66
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
67
|
+
try {
|
|
68
|
+
for (var _b = __asyncValues(yield this.client.scanIterator({
|
|
69
|
+
CURSOR: 0,
|
|
70
|
+
MATCH: `${key}:*`
|
|
71
|
+
})), _c; _c = yield _b.next(), !_c.done;) {
|
|
72
|
+
const k = _c.value;
|
|
73
|
+
yield this.client.del(k);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
77
|
+
finally {
|
|
78
|
+
try {
|
|
79
|
+
if (_c && !_c.done && (_a = _b.return)) yield _a.call(_b);
|
|
80
|
+
}
|
|
81
|
+
finally { if (e_2) throw e_2.error; }
|
|
82
|
+
}
|
|
83
|
+
return;
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
exports.default = RedisStore;
|
package/dist/runner.js
CHANGED
|
@@ -22,10 +22,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
22
22
|
* See the License for the specific language governing permissions and
|
|
23
23
|
* limitations under the License.
|
|
24
24
|
*/
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
const logger_1 = __importDefault(require("@fonoster/logger"));
|
|
26
|
+
const service_1 = __importDefault(require("./service"));
|
|
27
|
+
const get_config_1 = require("./config/get_config");
|
|
28
|
+
const result = get_config_1.getConfig(process.env.CONFIG_PATH);
|
|
29
29
|
if (result._tag === 'Right') {
|
|
30
30
|
service_1.default(result.right);
|
|
31
31
|
}
|
package/dist/service.js
CHANGED
|
@@ -3,12 +3,44 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
/*
|
|
7
|
+
* Copyright (C) 2022 by Fonoster Inc (https://fonoster.com)
|
|
8
|
+
* http://github.com/fonoster/routr
|
|
9
|
+
*
|
|
10
|
+
* This file is part of Routr
|
|
11
|
+
*
|
|
12
|
+
* Licensed under the MIT License (the "License")
|
|
13
|
+
* you may not use this file except in compliance with
|
|
14
|
+
* the License. You may obtain a copy of the License at
|
|
15
|
+
*
|
|
16
|
+
* https://opensource.org/licenses/MIT
|
|
17
|
+
*
|
|
18
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
19
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
20
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
21
|
+
* See the License for the specific language governing permissions and
|
|
22
|
+
* limitations under the License.
|
|
23
|
+
*/
|
|
24
|
+
const types_1 = require("./types");
|
|
25
|
+
const common_1 = require("@routr/common");
|
|
26
|
+
const utils_1 = require("./utils");
|
|
27
|
+
const locator_1 = __importDefault(require("./locator"));
|
|
28
|
+
const memory_store_1 = __importDefault(require("./memory_store"));
|
|
29
|
+
const redis_store_1 = __importDefault(require("./redis_store"));
|
|
30
|
+
const logger_1 = __importDefault(require("@fonoster/logger"));
|
|
31
|
+
const allowedParameters = ["host", "port", "username", "password", "secure"];
|
|
10
32
|
function LocationService(config) {
|
|
11
|
-
|
|
12
|
-
|
|
33
|
+
const { bindAddr, cache } = config;
|
|
34
|
+
let store;
|
|
35
|
+
if (cache.provider === types_1.CACHE_PROVIDER.REDIS) {
|
|
36
|
+
store = new redis_store_1.default(utils_1.configFromString(cache.parameters, allowedParameters));
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
store = new memory_store_1.default();
|
|
40
|
+
}
|
|
41
|
+
const backends = new Map();
|
|
42
|
+
config.backends.forEach(b => backends.set(`backend:${b.ref}`, b));
|
|
43
|
+
common_1.createService(utils_1.getServiceInfo(bindAddr, new locator_1.default(store, backends)));
|
|
44
|
+
logger_1.default.info(`using ${cache.provider} as cache provider`);
|
|
13
45
|
}
|
|
14
46
|
exports.default = LocationService;
|
package/dist/types.d.ts
CHANGED
|
@@ -2,6 +2,10 @@ export declare enum LB_ALGORITHM {
|
|
|
2
2
|
ROUND_ROBIN = "round-robin",
|
|
3
3
|
LEAST_SESSIONS = "least-sessions"
|
|
4
4
|
}
|
|
5
|
+
export declare enum CACHE_PROVIDER {
|
|
6
|
+
MEMORY = "memory",
|
|
7
|
+
REDIS = "redis"
|
|
8
|
+
}
|
|
5
9
|
export interface ILocationService {
|
|
6
10
|
addRoute(request: AddRouteRequest): Promise<void>;
|
|
7
11
|
findRoutes(request: FindRoutesRequest): Promise<Route[]>;
|
|
@@ -49,4 +53,15 @@ export interface Backend {
|
|
|
49
53
|
export interface LocationConfig {
|
|
50
54
|
bindAddr: string;
|
|
51
55
|
backends?: Backend[];
|
|
56
|
+
cache?: {
|
|
57
|
+
provider: CACHE_PROVIDER;
|
|
58
|
+
parameters: string;
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
export interface RedisStoreConfig {
|
|
62
|
+
username?: string;
|
|
63
|
+
password?: string;
|
|
64
|
+
host: string;
|
|
65
|
+
port: number;
|
|
66
|
+
secure?: boolean;
|
|
52
67
|
}
|
package/dist/types.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.LB_ALGORITHM = void 0;
|
|
3
|
+
exports.CACHE_PROVIDER = exports.LB_ALGORITHM = void 0;
|
|
4
4
|
/*
|
|
5
5
|
* Copyright (C) 2022 by Fonoster Inc (https://fonoster.com)
|
|
6
6
|
* http://github.com/fonoster/routr
|
|
@@ -24,3 +24,8 @@ var LB_ALGORITHM;
|
|
|
24
24
|
LB_ALGORITHM["ROUND_ROBIN"] = "round-robin";
|
|
25
25
|
LB_ALGORITHM["LEAST_SESSIONS"] = "least-sessions";
|
|
26
26
|
})(LB_ALGORITHM = exports.LB_ALGORITHM || (exports.LB_ALGORITHM = {}));
|
|
27
|
+
var CACHE_PROVIDER;
|
|
28
|
+
(function (CACHE_PROVIDER) {
|
|
29
|
+
CACHE_PROVIDER["MEMORY"] = "memory";
|
|
30
|
+
CACHE_PROVIDER["REDIS"] = "redis";
|
|
31
|
+
})(CACHE_PROVIDER = exports.CACHE_PROVIDER || (exports.CACHE_PROVIDER = {}));
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Backend, ILocationService, Route } from "./types";
|
|
1
|
+
import { Backend, ILocationService, RedisStoreConfig, Route } from "./types";
|
|
2
2
|
import { ServiceInfo } from "@routr/common";
|
|
3
3
|
export declare const expiredFilter: (r: Route) => boolean;
|
|
4
4
|
export declare const duplicateFilter: (r1: Route, r2: Route) => boolean;
|
|
@@ -7,3 +7,5 @@ export declare const compareArrays: (arr: string[], target: string[]) => boolean
|
|
|
7
7
|
export declare const filterOnlyMatchingLabels: (requestLabels: Map<string, string>) => (route: Route) => boolean;
|
|
8
8
|
export declare const hasAffinitySession: (backend: Backend) => boolean;
|
|
9
9
|
export declare function getServiceInfo(bindAddr: string, locator: ILocationService): ServiceInfo;
|
|
10
|
+
export declare const configFromString: (params: string, allowedKeys: string[]) => Record<string, string | boolean>;
|
|
11
|
+
export declare const getUrlString: (config: RedisStoreConfig) => string;
|
package/dist/utils.js
CHANGED
|
@@ -8,67 +8,31 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
-
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
12
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
13
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
14
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
15
|
-
function step(op) {
|
|
16
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
17
|
-
while (_) try {
|
|
18
|
-
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;
|
|
19
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
20
|
-
switch (op[0]) {
|
|
21
|
-
case 0: case 1: t = op; break;
|
|
22
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
23
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
24
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
25
|
-
default:
|
|
26
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
27
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
28
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
29
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
30
|
-
if (t[2]) _.ops.pop();
|
|
31
|
-
_.trys.pop(); continue;
|
|
32
|
-
}
|
|
33
|
-
op = body.call(thisArg, _);
|
|
34
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
35
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
-
exports.getServiceInfo = exports.hasAffinitySession = exports.filterOnlyMatchingLabels = exports.compareArrays = exports.mergeKeyValue = exports.duplicateFilter = exports.expiredFilter = void 0;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
return (r.expires - (Date.now() - r.registeredOn) / 1000) > 0;
|
|
44
|
-
};
|
|
12
|
+
exports.getUrlString = exports.configFromString = exports.getServiceInfo = exports.hasAffinitySession = exports.filterOnlyMatchingLabels = exports.compareArrays = exports.mergeKeyValue = exports.duplicateFilter = exports.expiredFilter = void 0;
|
|
13
|
+
const common_1 = require("@routr/common");
|
|
14
|
+
const errors_1 = require("./errors");
|
|
15
|
+
const expiredFilter = (r) => (r.expires - (Date.now() - r.registeredOn) / 1000) > 0;
|
|
45
16
|
exports.expiredFilter = expiredFilter;
|
|
46
|
-
|
|
47
|
-
return !(r1.host === r2.host && r1.port === r2.port);
|
|
48
|
-
};
|
|
17
|
+
const duplicateFilter = (r1, r2) => !(r1.host === r2.host && r1.port === r2.port);
|
|
49
18
|
exports.duplicateFilter = duplicateFilter;
|
|
50
|
-
|
|
19
|
+
const mergeKeyValue = (map) => Array.from(map).map(l => l[0] + l[1]);
|
|
51
20
|
exports.mergeKeyValue = mergeKeyValue;
|
|
52
|
-
|
|
53
|
-
return target.every(function (v) { return arr.includes(v); }) && arr.length === target.length;
|
|
54
|
-
};
|
|
21
|
+
const compareArrays = (arr, target) => target.every(v => arr.includes(v)) && arr.length === target.length;
|
|
55
22
|
exports.compareArrays = compareArrays;
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
: false; };
|
|
60
|
-
};
|
|
23
|
+
const filterOnlyMatchingLabels = (requestLabels) => (route) => route.labels
|
|
24
|
+
? exports.compareArrays(exports.mergeKeyValue(requestLabels), exports.mergeKeyValue(route.labels))
|
|
25
|
+
: false;
|
|
61
26
|
exports.filterOnlyMatchingLabels = filterOnlyMatchingLabels;
|
|
62
|
-
|
|
27
|
+
const hasAffinitySession = (backend) => { var _a; return (_a = backend === null || backend === void 0 ? void 0 : backend.sessionAffinity) === null || _a === void 0 ? void 0 : _a.enabled; };
|
|
63
28
|
exports.hasAffinitySession = hasAffinitySession;
|
|
64
29
|
function getServiceInfo(bindAddr, locator) {
|
|
65
|
-
var _this = this;
|
|
66
30
|
return {
|
|
67
31
|
name: "location",
|
|
68
|
-
bindAddr
|
|
32
|
+
bindAddr,
|
|
69
33
|
service: common_1.LOCATION_OBJECT_PROTO.Location.service,
|
|
70
34
|
handlers: {
|
|
71
|
-
addRoute:
|
|
35
|
+
addRoute: (call, callback) => {
|
|
72
36
|
try {
|
|
73
37
|
locator.addRoute(call.request);
|
|
74
38
|
callback(null, {});
|
|
@@ -77,53 +41,59 @@ function getServiceInfo(bindAddr, locator) {
|
|
|
77
41
|
callback(e, null);
|
|
78
42
|
}
|
|
79
43
|
},
|
|
80
|
-
findRoutes:
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
}
|
|
102
|
-
})
|
|
103
|
-
removeRoutes: function (call, callback) { return __awaiter(_this, void 0, void 0, function () {
|
|
104
|
-
var _a, _b, e_2;
|
|
105
|
-
var _c;
|
|
106
|
-
return __generator(this, function (_d) {
|
|
107
|
-
switch (_d.label) {
|
|
108
|
-
case 0:
|
|
109
|
-
_d.trys.push([0, 2, , 3]);
|
|
110
|
-
_a = callback;
|
|
111
|
-
_b = [null];
|
|
112
|
-
_c = {};
|
|
113
|
-
return [4 /*yield*/, locator.findRoutes(call.request)];
|
|
114
|
-
case 1:
|
|
115
|
-
_a.apply(void 0, _b.concat([(_c.routes = _d.sent(),
|
|
116
|
-
_c)]));
|
|
117
|
-
return [3 /*break*/, 3];
|
|
118
|
-
case 2:
|
|
119
|
-
e_2 = _d.sent();
|
|
120
|
-
callback(e_2, null);
|
|
121
|
-
return [3 /*break*/, 3];
|
|
122
|
-
case 3: return [2 /*return*/];
|
|
123
|
-
}
|
|
124
|
-
});
|
|
125
|
-
}); }
|
|
44
|
+
findRoutes: (call, callback) => __awaiter(this, void 0, void 0, function* () {
|
|
45
|
+
try {
|
|
46
|
+
const routes = yield locator.findRoutes(call.request);
|
|
47
|
+
if (routes.length == 0)
|
|
48
|
+
throw new errors_1.NotRoutesFoundForAOR(call.request.aor);
|
|
49
|
+
callback(null, {
|
|
50
|
+
routes: routes
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
catch (e) {
|
|
54
|
+
callback(e, null);
|
|
55
|
+
}
|
|
56
|
+
}),
|
|
57
|
+
removeRoutes: (call, callback) => __awaiter(this, void 0, void 0, function* () {
|
|
58
|
+
try {
|
|
59
|
+
callback(null, {
|
|
60
|
+
routes: yield locator.findRoutes(call.request)
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
catch (e) {
|
|
64
|
+
callback(e, null);
|
|
65
|
+
}
|
|
66
|
+
})
|
|
126
67
|
}
|
|
127
68
|
};
|
|
128
69
|
}
|
|
129
70
|
exports.getServiceInfo = getServiceInfo;
|
|
71
|
+
const configFromString = (params, allowedKeys) => {
|
|
72
|
+
if (params.length === 0)
|
|
73
|
+
return {};
|
|
74
|
+
const parameters = {};
|
|
75
|
+
params.split(',').forEach(par => {
|
|
76
|
+
try {
|
|
77
|
+
const key = par.split('=')[0];
|
|
78
|
+
const value = par.split('=')[1];
|
|
79
|
+
if (allowedKeys.indexOf(key) === -1) {
|
|
80
|
+
throw `invalid parameter: ${key}`;
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
parameters[key] = value === "true" ? true : value;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
catch (e) {
|
|
87
|
+
throw new Error(`invalid parameters string: ${params}; should be something like 'host=localhost,port=6379'`);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
return parameters;
|
|
91
|
+
};
|
|
92
|
+
exports.configFromString = configFromString;
|
|
93
|
+
const getUrlString = (config) => {
|
|
94
|
+
return `redis${config.secure ? 's' : ''}`
|
|
95
|
+
+ `://${config.username ? config.username : ''}`
|
|
96
|
+
+ `${config.password ? ':' + config.password + '@' : ''}`
|
|
97
|
+
+ `${config.host}:${config.port}`;
|
|
98
|
+
};
|
|
99
|
+
exports.getUrlString = getUrlString;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@routr/location",
|
|
3
|
-
"version": "2.0.5-alpha.
|
|
3
|
+
"version": "2.0.5-alpha.3",
|
|
4
4
|
"description": "Creates and maintains a list of routes to all registered endpoints",
|
|
5
5
|
"author": "Pedro Sanders <psanders@fonoster.com>",
|
|
6
6
|
"homepage": "https://github.com/fonoster/routr#readme",
|
|
@@ -25,9 +25,10 @@
|
|
|
25
25
|
"access": "public"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@routr/common": "^2.0.5-alpha.
|
|
28
|
+
"@routr/common": "^2.0.5-alpha.3",
|
|
29
29
|
"ajv": "^6.12.6",
|
|
30
|
-
"fp-ts": "^2.11.8"
|
|
30
|
+
"fp-ts": "^2.11.8",
|
|
31
|
+
"redis": "^4.0.4"
|
|
31
32
|
},
|
|
32
33
|
"repository": {
|
|
33
34
|
"type": "git",
|
|
@@ -36,5 +37,5 @@
|
|
|
36
37
|
"bugs": {
|
|
37
38
|
"url": "https://github.com/fonoster/routr/issues"
|
|
38
39
|
},
|
|
39
|
-
"gitHead": "
|
|
40
|
+
"gitHead": "7d942466133a03f4bcfe0dc100f1a922b3ed14ad"
|
|
40
41
|
}
|