@routr/location 2.0.5-alpha.9 → 2.0.6-alpha.1
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/client.d.ts +33 -0
- package/dist/client.js +66 -8
- package/dist/config/get_config.d.ts +1 -1
- package/dist/config/get_config.js +10 -5
- package/dist/config/schema.d.ts +1 -10
- package/dist/config/schema.js +45 -54
- package/dist/errors.d.ts +37 -1
- package/dist/errors.js +61 -2
- package/dist/helper.d.ts +1 -2
- package/dist/helper.js +25 -4
- package/dist/index.d.ts +3 -1
- package/dist/index.js +9 -1
- package/dist/location.d.ts +12 -0
- package/dist/location.js +33 -15
- package/dist/memory_store.d.ts +13 -0
- package/dist/memory_store.js +18 -3
- package/dist/redis_store.d.ts +14 -2
- package/dist/redis_store.js +20 -8
- package/dist/runner.js +10 -5
- package/dist/service.d.ts +5 -0
- package/dist/service.js +11 -5
- package/dist/tracer.d.ts +7 -0
- package/dist/tracer.js +53 -0
- package/dist/types.d.ts +2 -5
- package/dist/utils.d.ts +3 -6
- package/dist/utils.js +33 -23
- package/package.json +13 -4
package/dist/client.d.ts
CHANGED
|
@@ -1,14 +1,47 @@
|
|
|
1
1
|
import { AddRouteRequest, FindRoutesRequest, ILocationService, RemoveRoutesRequest } from "./types";
|
|
2
2
|
import { Route } from "@routr/common";
|
|
3
|
+
/**
|
|
4
|
+
* Location client
|
|
5
|
+
*/
|
|
3
6
|
export default class Location implements ILocationService {
|
|
4
7
|
location: any;
|
|
5
8
|
config: {
|
|
6
9
|
addr: string;
|
|
7
10
|
};
|
|
11
|
+
/**
|
|
12
|
+
* Create a new Location client.
|
|
13
|
+
*
|
|
14
|
+
* @param {object} config - Location client config
|
|
15
|
+
* @param {string} config.addr - Location service address
|
|
16
|
+
*/
|
|
8
17
|
constructor(config: {
|
|
9
18
|
addr: string;
|
|
10
19
|
});
|
|
20
|
+
/**
|
|
21
|
+
* Add a route to the location service.
|
|
22
|
+
*
|
|
23
|
+
* @param {AddRouteRequest} request - Add route request
|
|
24
|
+
* @param {string} request.aor - AOR of the route
|
|
25
|
+
* @param {Route} request.route - Route to add
|
|
26
|
+
* @return {Promise<void>}
|
|
27
|
+
*/
|
|
11
28
|
addRoute(request: AddRouteRequest): Promise<void>;
|
|
29
|
+
/**
|
|
30
|
+
* Add a route to the location service.
|
|
31
|
+
*
|
|
32
|
+
* @param {FindRoutesResponse} request - Request to find routes
|
|
33
|
+
* @param {string} request.aor - AOR of the route
|
|
34
|
+
* @param {Map<string, string>} request.labels - Optional Route labels
|
|
35
|
+
* @param {string} request.sessionAffinityRef - Optiona session affinity ref
|
|
36
|
+
* @return {Promise<void>}
|
|
37
|
+
*/
|
|
12
38
|
findRoutes(request: FindRoutesRequest): Promise<Route[]>;
|
|
39
|
+
/**
|
|
40
|
+
* Add a route to the location service.
|
|
41
|
+
*
|
|
42
|
+
* @param {RemoveRoutesRequest} request - Remove routes request
|
|
43
|
+
* @param {string} request.aor - AOR of the route
|
|
44
|
+
* @return {Promise<void>}
|
|
45
|
+
*/
|
|
13
46
|
removeRoutes(request: RemoveRoutesRequest): Promise<void>;
|
|
14
47
|
}
|
package/dist/client.js
CHANGED
|
@@ -1,4 +1,27 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
2
25
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
26
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
27
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -10,32 +33,67 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
33
|
};
|
|
11
34
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
35
|
const common_1 = require("@routr/common");
|
|
13
|
-
const grpc = require("@grpc/grpc-js");
|
|
14
|
-
|
|
36
|
+
const grpc = __importStar(require("@grpc/grpc-js"));
|
|
37
|
+
const container = (self, request, name) => {
|
|
15
38
|
return new Promise((resolve, reject) => {
|
|
16
39
|
self.location[name](request, (err, response) => {
|
|
17
40
|
if ((err === null || err === void 0 ? void 0 : err.code) === grpc.status.UNAVAILABLE) {
|
|
18
|
-
return reject(new common_1.ServiceUnavailableError(
|
|
41
|
+
return reject(new common_1.ServiceUnavailableError(self.config.addr));
|
|
19
42
|
}
|
|
20
43
|
resolve(response);
|
|
21
44
|
});
|
|
22
45
|
});
|
|
23
|
-
}
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Location client
|
|
49
|
+
*/
|
|
24
50
|
class Location {
|
|
51
|
+
/**
|
|
52
|
+
* Create a new Location client.
|
|
53
|
+
*
|
|
54
|
+
* @param {object} config - Location client config
|
|
55
|
+
* @param {string} config.addr - Location service address
|
|
56
|
+
*/
|
|
25
57
|
constructor(config) {
|
|
26
58
|
this.config = config;
|
|
27
|
-
|
|
28
|
-
|
|
59
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
60
|
+
this.location = new common_1.LOCATION_OBJECT_PROTO.Location(config.addr, grpc.credentials.createInsecure());
|
|
29
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* Add a route to the location service.
|
|
64
|
+
*
|
|
65
|
+
* @param {AddRouteRequest} request - Add route request
|
|
66
|
+
* @param {string} request.aor - AOR of the route
|
|
67
|
+
* @param {Route} request.route - Route to add
|
|
68
|
+
* @return {Promise<void>}
|
|
69
|
+
*/
|
|
30
70
|
addRoute(request) {
|
|
31
71
|
return container(this, request, this.addRoute.name);
|
|
32
72
|
}
|
|
73
|
+
/**
|
|
74
|
+
* Add a route to the location service.
|
|
75
|
+
*
|
|
76
|
+
* @param {FindRoutesResponse} request - Request to find routes
|
|
77
|
+
* @param {string} request.aor - AOR of the route
|
|
78
|
+
* @param {Map<string, string>} request.labels - Optional Route labels
|
|
79
|
+
* @param {string} request.sessionAffinityRef - Optiona session affinity ref
|
|
80
|
+
* @return {Promise<void>}
|
|
81
|
+
*/
|
|
33
82
|
findRoutes(request) {
|
|
34
|
-
var _a;
|
|
83
|
+
var _a, _b;
|
|
35
84
|
return __awaiter(this, void 0, void 0, function* () {
|
|
36
|
-
return (
|
|
85
|
+
return (
|
|
86
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
87
|
+
(_b = (_a = ((yield container(this, request, this.findRoutes.name)))) === null || _a === void 0 ? void 0 : _a.routes) !== null && _b !== void 0 ? _b : []);
|
|
37
88
|
});
|
|
38
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Add a route to the location service.
|
|
92
|
+
*
|
|
93
|
+
* @param {RemoveRoutesRequest} request - Remove routes request
|
|
94
|
+
* @param {string} request.aor - AOR of the route
|
|
95
|
+
* @return {Promise<void>}
|
|
96
|
+
*/
|
|
39
97
|
removeRoutes(request) {
|
|
40
98
|
return container(this, request, this.removeRoutes.name);
|
|
41
99
|
}
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
@@ -49,9 +53,9 @@ const E = __importStar(require("fp-ts/Either"));
|
|
|
49
53
|
const errors_1 = require("../errors");
|
|
50
54
|
const ajv = new ajv_1.default();
|
|
51
55
|
const validate = ajv.compile(schema_1.schema);
|
|
52
|
-
const hasBadCombiniation = (backends) => backends.some((b) => b.balancingAlgorithm === types_1.LB_ALGORITHM.ROUND_ROBIN && b.
|
|
53
|
-
const hasBadAlgorithm = (backends) => backends.some((b) => b.balancingAlgorithm !== types_1.LB_ALGORITHM.ROUND_ROBIN
|
|
54
|
-
|
|
56
|
+
const hasBadCombiniation = (backends) => backends.some((b) => b.balancingAlgorithm === types_1.LB_ALGORITHM.ROUND_ROBIN && b.withSessionAffinity);
|
|
57
|
+
const hasBadAlgorithm = (backends) => backends.some((b) => b.balancingAlgorithm !== types_1.LB_ALGORITHM.ROUND_ROBIN &&
|
|
58
|
+
b.balancingAlgorithm !== types_1.LB_ALGORITHM.LEAST_SESSIONS);
|
|
55
59
|
const getConfig = (path) => {
|
|
56
60
|
var _a, _b, _c;
|
|
57
61
|
const c = JSON.parse(fs_1.default.readFileSync(path, "utf8"));
|
|
@@ -63,7 +67,8 @@ const getConfig = (path) => {
|
|
|
63
67
|
config.backends.map((b) => {
|
|
64
68
|
// Setting round-robin by default
|
|
65
69
|
b.balancingAlgorithm = b.balancingAlgorithm
|
|
66
|
-
? b.balancingAlgorithm
|
|
70
|
+
? b.balancingAlgorithm
|
|
71
|
+
: types_1.LB_ALGORITHM.ROUND_ROBIN;
|
|
67
72
|
return b;
|
|
68
73
|
});
|
|
69
74
|
if (hasBadCombiniation(config.backends)) {
|
package/dist/config/schema.d.ts
CHANGED
|
@@ -47,18 +47,9 @@ export declare const schema: {
|
|
|
47
47
|
balancingAlgorithm: {
|
|
48
48
|
enum: string[];
|
|
49
49
|
};
|
|
50
|
-
|
|
50
|
+
withSessionAffinity: {
|
|
51
51
|
description: string;
|
|
52
52
|
type: string;
|
|
53
|
-
properties: {
|
|
54
|
-
enabled: {
|
|
55
|
-
type: string;
|
|
56
|
-
};
|
|
57
|
-
ref: {
|
|
58
|
-
type: string;
|
|
59
|
-
};
|
|
60
|
-
};
|
|
61
|
-
required: string[];
|
|
62
53
|
};
|
|
63
54
|
};
|
|
64
55
|
required: string[];
|
package/dist/config/schema.js
CHANGED
|
@@ -20,72 +20,63 @@ exports.schema = void 0;
|
|
|
20
20
|
* limitations under the License.
|
|
21
21
|
*/
|
|
22
22
|
exports.schema = {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
23
|
+
$id: "https://json-schema.org/draft/2020-12/schema",
|
|
24
|
+
title: "Location Service configuration",
|
|
25
|
+
description: "Configuration for an instance of the Location Service",
|
|
26
|
+
type: "object",
|
|
27
|
+
properties: {
|
|
28
|
+
kind: {
|
|
29
|
+
enum: ["Location", "location"]
|
|
30
30
|
},
|
|
31
|
-
|
|
32
|
-
|
|
31
|
+
apiVersion: {
|
|
32
|
+
enum: ["v2draft1"]
|
|
33
33
|
},
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
metadata: {
|
|
35
|
+
description: "Resource metadata",
|
|
36
|
+
type: "object"
|
|
37
37
|
},
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
38
|
+
spec: {
|
|
39
|
+
description: "Operations spec for Location",
|
|
40
|
+
type: "object",
|
|
41
|
+
properties: {
|
|
42
|
+
bindAddr: {
|
|
43
|
+
description: "Ipv4 interface to accept request on",
|
|
44
|
+
type: "string"
|
|
45
45
|
},
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
},
|
|
52
|
-
"parameters": {
|
|
53
|
-
"type": "string"
|
|
46
|
+
cache: {
|
|
47
|
+
type: "object",
|
|
48
|
+
properties: {
|
|
49
|
+
provider: {
|
|
50
|
+
enum: ["memory", "redis"]
|
|
54
51
|
},
|
|
52
|
+
parameters: {
|
|
53
|
+
type: "string"
|
|
54
|
+
}
|
|
55
55
|
},
|
|
56
|
-
|
|
56
|
+
required: ["provider"]
|
|
57
57
|
},
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
backends: {
|
|
59
|
+
description: "Optional SIP backends",
|
|
60
|
+
type: "array",
|
|
61
|
+
items: {
|
|
62
|
+
type: "object"
|
|
63
63
|
},
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
},
|
|
68
|
-
"balancingAlgorithm": {
|
|
69
|
-
"enum": ["round-robin", "least-sessions"]
|
|
64
|
+
properties: {
|
|
65
|
+
ref: {
|
|
66
|
+
type: "string"
|
|
70
67
|
},
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
"type": "object",
|
|
74
|
-
"properties": {
|
|
75
|
-
"enabled": {
|
|
76
|
-
"type": "boolean"
|
|
77
|
-
},
|
|
78
|
-
"ref": {
|
|
79
|
-
"type": "string"
|
|
80
|
-
}
|
|
81
|
-
},
|
|
82
|
-
"required": ["ref"]
|
|
68
|
+
balancingAlgorithm: {
|
|
69
|
+
enum: ["round-robin", "least-sessions"]
|
|
83
70
|
},
|
|
71
|
+
withSessionAffinity: {
|
|
72
|
+
description: "Optional session affinity",
|
|
73
|
+
type: "boolean"
|
|
74
|
+
}
|
|
84
75
|
},
|
|
85
|
-
|
|
86
|
-
}
|
|
76
|
+
required: ["ref"]
|
|
77
|
+
}
|
|
87
78
|
}
|
|
88
79
|
}
|
|
89
80
|
},
|
|
90
|
-
|
|
81
|
+
required: ["kind", "spec", "apiVersion"]
|
|
91
82
|
};
|
package/dist/errors.d.ts
CHANGED
|
@@ -1,23 +1,59 @@
|
|
|
1
|
-
import grpc
|
|
1
|
+
import * as grpc from "@grpc/grpc-js";
|
|
2
2
|
export declare type LocationError = UnsupportedSchema | NotRoutesFoundForAOR;
|
|
3
3
|
export declare type InvalidConfiguration = BadAlgorithmAndAffinityCombination | InvalidSchemaConfiguration;
|
|
4
|
+
/**
|
|
5
|
+
* Error thrown when the location service returns an unsupported schema.
|
|
6
|
+
*/
|
|
4
7
|
export declare class UnsupportedSchema extends Error {
|
|
5
8
|
code: grpc.status;
|
|
9
|
+
/**
|
|
10
|
+
* Create a new UnsupportedSchema error.
|
|
11
|
+
*
|
|
12
|
+
* @param {string} aor - The AOR that was requested
|
|
13
|
+
*/
|
|
6
14
|
constructor(aor: string);
|
|
7
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* Error thrown when the location service returns no routes for the AOR.
|
|
18
|
+
*/
|
|
8
19
|
export declare class NotRoutesFoundForAOR extends Error {
|
|
9
20
|
code: number;
|
|
21
|
+
/**
|
|
22
|
+
* Create a new NotRoutesFoundForAOR error.
|
|
23
|
+
*
|
|
24
|
+
* @param {string} aor - The AOR that was requested
|
|
25
|
+
*/
|
|
10
26
|
constructor(aor: string);
|
|
11
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Error thrown when the location finds a bad configuration.
|
|
30
|
+
*/
|
|
12
31
|
export declare class InvalidSchemaConfiguration extends Error {
|
|
13
32
|
code: grpc.status;
|
|
33
|
+
/**
|
|
34
|
+
* Create a new InvalidSchemaConfiguration error.
|
|
35
|
+
*
|
|
36
|
+
* @param {string} msg - Message from the validation error
|
|
37
|
+
*/
|
|
14
38
|
constructor(msg: string);
|
|
15
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Error thrown when the location finds incompatible algorithm and session affinity.
|
|
42
|
+
*/
|
|
16
43
|
export declare class BadAlgorithmAndAffinityCombination extends Error {
|
|
17
44
|
code: grpc.status;
|
|
45
|
+
/**
|
|
46
|
+
* Create a new BadAlgorithmAndAffinityCombination error.
|
|
47
|
+
*/
|
|
18
48
|
constructor();
|
|
19
49
|
}
|
|
50
|
+
/**
|
|
51
|
+
* Error thrown when the location finds an invalid balancing algorithm.
|
|
52
|
+
*/
|
|
20
53
|
export declare class InvalidLoadBalancerAlgorithm extends Error {
|
|
21
54
|
code: grpc.status;
|
|
55
|
+
/**
|
|
56
|
+
* Create a new InvalidLoadBalancerAlgorithm error.
|
|
57
|
+
*/
|
|
22
58
|
constructor();
|
|
23
59
|
}
|
package/dist/errors.js
CHANGED
|
@@ -1,4 +1,27 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
2
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
26
|
exports.InvalidLoadBalancerAlgorithm = exports.BadAlgorithmAndAffinityCombination = exports.InvalidSchemaConfiguration = exports.NotRoutesFoundForAOR = exports.UnsupportedSchema = void 0;
|
|
4
27
|
/*
|
|
@@ -19,8 +42,16 @@ exports.InvalidLoadBalancerAlgorithm = exports.BadAlgorithmAndAffinityCombinatio
|
|
|
19
42
|
* See the License for the specific language governing permissions and
|
|
20
43
|
* limitations under the License.
|
|
21
44
|
*/
|
|
22
|
-
const grpc = require("@grpc/grpc-js");
|
|
45
|
+
const grpc = __importStar(require("@grpc/grpc-js"));
|
|
46
|
+
/**
|
|
47
|
+
* Error thrown when the location service returns an unsupported schema.
|
|
48
|
+
*/
|
|
23
49
|
class UnsupportedSchema extends Error {
|
|
50
|
+
/**
|
|
51
|
+
* Create a new UnsupportedSchema error.
|
|
52
|
+
*
|
|
53
|
+
* @param {string} aor - The AOR that was requested
|
|
54
|
+
*/
|
|
24
55
|
constructor(aor) {
|
|
25
56
|
super(`aor ${aor} has an invalid schema, only "sip:" or "backend:" are allowed`);
|
|
26
57
|
this.code = grpc.status.INVALID_ARGUMENT;
|
|
@@ -29,15 +60,31 @@ class UnsupportedSchema extends Error {
|
|
|
29
60
|
}
|
|
30
61
|
}
|
|
31
62
|
exports.UnsupportedSchema = UnsupportedSchema;
|
|
63
|
+
/**
|
|
64
|
+
* Error thrown when the location service returns no routes for the AOR.
|
|
65
|
+
*/
|
|
32
66
|
class NotRoutesFoundForAOR extends Error {
|
|
67
|
+
/**
|
|
68
|
+
* Create a new NotRoutesFoundForAOR error.
|
|
69
|
+
*
|
|
70
|
+
* @param {string} aor - The AOR that was requested
|
|
71
|
+
*/
|
|
33
72
|
constructor(aor) {
|
|
34
|
-
super(`no routes found for aor ${aor}`);
|
|
73
|
+
super(`no routes found for aor: ${aor}`);
|
|
35
74
|
this.code = grpc.status.NOT_FOUND;
|
|
36
75
|
Object.setPrototypeOf(this, NotRoutesFoundForAOR.prototype);
|
|
37
76
|
}
|
|
38
77
|
}
|
|
39
78
|
exports.NotRoutesFoundForAOR = NotRoutesFoundForAOR;
|
|
79
|
+
/**
|
|
80
|
+
* Error thrown when the location finds a bad configuration.
|
|
81
|
+
*/
|
|
40
82
|
class InvalidSchemaConfiguration extends Error {
|
|
83
|
+
/**
|
|
84
|
+
* Create a new InvalidSchemaConfiguration error.
|
|
85
|
+
*
|
|
86
|
+
* @param {string} msg - Message from the validation error
|
|
87
|
+
*/
|
|
41
88
|
constructor(msg) {
|
|
42
89
|
super(msg);
|
|
43
90
|
this.code = grpc.status.INVALID_ARGUMENT;
|
|
@@ -45,14 +92,26 @@ class InvalidSchemaConfiguration extends Error {
|
|
|
45
92
|
}
|
|
46
93
|
}
|
|
47
94
|
exports.InvalidSchemaConfiguration = InvalidSchemaConfiguration;
|
|
95
|
+
/**
|
|
96
|
+
* Error thrown when the location finds incompatible algorithm and session affinity.
|
|
97
|
+
*/
|
|
48
98
|
class BadAlgorithmAndAffinityCombination extends Error {
|
|
99
|
+
/**
|
|
100
|
+
* Create a new BadAlgorithmAndAffinityCombination error.
|
|
101
|
+
*/
|
|
49
102
|
constructor() {
|
|
50
103
|
super("session affinity can not be combined with round-robin load balancing");
|
|
51
104
|
Object.setPrototypeOf(this, BadAlgorithmAndAffinityCombination.prototype);
|
|
52
105
|
}
|
|
53
106
|
}
|
|
54
107
|
exports.BadAlgorithmAndAffinityCombination = BadAlgorithmAndAffinityCombination;
|
|
108
|
+
/**
|
|
109
|
+
* Error thrown when the location finds an invalid balancing algorithm.
|
|
110
|
+
*/
|
|
55
111
|
class InvalidLoadBalancerAlgorithm extends Error {
|
|
112
|
+
/**
|
|
113
|
+
* Create a new InvalidLoadBalancerAlgorithm error.
|
|
114
|
+
*/
|
|
56
115
|
constructor() {
|
|
57
116
|
super("found invalid load balancing algorithm. must be round-robin or least-sessions");
|
|
58
117
|
Object.setPrototypeOf(this, BadAlgorithmAndAffinityCombination.prototype);
|
package/dist/helper.d.ts
CHANGED
package/dist/helper.js
CHANGED
|
@@ -1,8 +1,26 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createRoute = void 0;
|
|
4
|
+
/*
|
|
5
|
+
* Copyright (C) 2022 by Fonoster Inc (https://fonoster.com)
|
|
6
|
+
* http://github.com/fonoster/routr
|
|
7
|
+
*
|
|
8
|
+
* This file is part of Routr
|
|
9
|
+
*
|
|
10
|
+
* Licensed under the MIT License (the "License")
|
|
11
|
+
* you may not use this file except in compliance with
|
|
12
|
+
* the License. You may obtain a copy of the License at
|
|
13
|
+
*
|
|
14
|
+
* https://opensource.org/licenses/MIT
|
|
15
|
+
*
|
|
16
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
17
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
18
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
19
|
+
* See the License for the specific language governing permissions and
|
|
20
|
+
* limitations under the License.
|
|
21
|
+
*/
|
|
22
|
+
const common_1 = require("@routr/common");
|
|
4
23
|
const processor_1 = require("@routr/processor");
|
|
5
|
-
const processor_2 = require("@routr/processor");
|
|
6
24
|
// TODO: Before finalizing this, consider using the old approach of saving the rport
|
|
7
25
|
// and received values (like here:
|
|
8
26
|
// https://github.com/fonoster/routr/blob/59bc98af86078088aede7e658c0d82a19fa18fa4/mod/registrar/utils.js#L87)
|
|
@@ -11,15 +29,18 @@ const processor_2 = require("@routr/processor");
|
|
|
11
29
|
// and https://github.com/fonoster/routr/blob/ee5d339888344013939d06c734385f17f0cd75c2/mod/registrar/utils.js#L131
|
|
12
30
|
const createRoute = (request) => {
|
|
13
31
|
const uri = request.message.contact.address.uri;
|
|
32
|
+
const sessionCount = processor_1.Extensions.getHeaderValue(request, common_1.CommonTypes.ExtraHeader.SESSION_COUNT)
|
|
33
|
+
? parseInt(processor_1.Extensions.getHeaderValue(request, common_1.CommonTypes.ExtraHeader.SESSION_COUNT))
|
|
34
|
+
: -1;
|
|
14
35
|
return {
|
|
15
36
|
edgePortRef: request.edgePortRef,
|
|
16
37
|
user: uri.user,
|
|
17
38
|
host: uri.host,
|
|
18
39
|
port: uri.port,
|
|
19
|
-
transport: uri.
|
|
40
|
+
transport: uri.transportParam,
|
|
20
41
|
registeredOn: Date.now(),
|
|
21
|
-
sessionCount
|
|
22
|
-
expires:
|
|
42
|
+
sessionCount,
|
|
43
|
+
expires: processor_1.Target.getTargetExpires(request),
|
|
23
44
|
listeningPoint: request.listeningPoint
|
|
24
45
|
};
|
|
25
46
|
};
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
3
|
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
5
9
|
}) : (function(o, m, k, k2) {
|
|
6
10
|
if (k2 === undefined) k2 = k;
|
|
7
11
|
o[k2] = m[k];
|
|
@@ -18,6 +22,9 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
18
22
|
__setModuleDefault(result, mod);
|
|
19
23
|
return result;
|
|
20
24
|
};
|
|
25
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
26
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
27
|
+
};
|
|
21
28
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
22
29
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
23
30
|
};
|
|
@@ -45,3 +52,4 @@ const client_1 = __importDefault(require("./client"));
|
|
|
45
52
|
exports.LocationClient = client_1.default;
|
|
46
53
|
exports.Helper = __importStar(require("./helper"));
|
|
47
54
|
exports.Utils = __importStar(require("./utils"));
|
|
55
|
+
__exportStar(require("./errors"), exports);
|
package/dist/location.d.ts
CHANGED
|
@@ -1,13 +1,25 @@
|
|
|
1
1
|
import { AddRouteRequest, Backend, FindRoutesRequest, ILocationService, ILocatorStore, RemoveRoutesRequest } from "./types";
|
|
2
2
|
import { Route } from "@routr/common";
|
|
3
|
+
/**
|
|
4
|
+
* A locator store that uses the location service to find routes for AORs.
|
|
5
|
+
*/
|
|
3
6
|
export default class Location implements ILocationService {
|
|
4
7
|
private store;
|
|
5
8
|
private backends;
|
|
6
9
|
private rrCount;
|
|
7
10
|
private affinityStore;
|
|
11
|
+
/**
|
|
12
|
+
* Creates a new Location service. Should fail if any backend has sessionAffinity and round-robin
|
|
13
|
+
*
|
|
14
|
+
* @param {ILocatorStore} store - The store to use for the location service
|
|
15
|
+
* @param {Map<string, Backend>} backends - The backends to use for the location service
|
|
16
|
+
*/
|
|
8
17
|
constructor(store: ILocatorStore, backends?: Map<string, Backend>);
|
|
18
|
+
/** @inheritdoc */
|
|
9
19
|
addRoute(request: AddRouteRequest): Promise<void>;
|
|
20
|
+
/** @inheritdoc */
|
|
10
21
|
findRoutes(request: FindRoutesRequest): Promise<Route[]>;
|
|
22
|
+
/** @inheritdoc */
|
|
11
23
|
removeRoutes(request: RemoveRoutesRequest): Promise<void>;
|
|
12
24
|
private next;
|
|
13
25
|
private nextWithAffinity;
|
package/dist/location.js
CHANGED
|
@@ -30,8 +30,21 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
30
30
|
const errors_1 = require("./errors");
|
|
31
31
|
const types_1 = require("./types");
|
|
32
32
|
const utils_1 = require("./utils");
|
|
33
|
+
var AOR_SCHEME;
|
|
34
|
+
(function (AOR_SCHEME) {
|
|
35
|
+
AOR_SCHEME["SIP"] = "sip:";
|
|
36
|
+
AOR_SCHEME["BACKEND"] = "backend:";
|
|
37
|
+
})(AOR_SCHEME || (AOR_SCHEME = {}));
|
|
38
|
+
/**
|
|
39
|
+
* A locator store that uses the location service to find routes for AORs.
|
|
40
|
+
*/
|
|
33
41
|
class Location {
|
|
34
|
-
|
|
42
|
+
/**
|
|
43
|
+
* Creates a new Location service. Should fail if any backend has sessionAffinity and round-robin
|
|
44
|
+
*
|
|
45
|
+
* @param {ILocatorStore} store - The store to use for the location service
|
|
46
|
+
* @param {Map<string, Backend>} backends - The backends to use for the location service
|
|
47
|
+
*/
|
|
35
48
|
constructor(store, backends = new Map()) {
|
|
36
49
|
this.store = store;
|
|
37
50
|
this.backends = backends;
|
|
@@ -39,55 +52,60 @@ class Location {
|
|
|
39
52
|
this.affinityStore = new Map();
|
|
40
53
|
this.backends.forEach((value, key) => this.rrCount.set(key, 0));
|
|
41
54
|
}
|
|
55
|
+
/** @inheritdoc */
|
|
42
56
|
addRoute(request) {
|
|
43
|
-
if (!request.aor.startsWith(
|
|
44
|
-
!request.aor.startsWith(
|
|
57
|
+
if (!request.aor.startsWith(AOR_SCHEME.SIP) &&
|
|
58
|
+
!request.aor.startsWith(AOR_SCHEME.BACKEND)) {
|
|
45
59
|
throw new errors_1.UnsupportedSchema(request.aor);
|
|
46
60
|
}
|
|
47
61
|
return this.store.put(request.aor, request.route);
|
|
48
62
|
}
|
|
63
|
+
/** @inheritdoc */
|
|
49
64
|
findRoutes(request) {
|
|
65
|
+
var _a;
|
|
50
66
|
return __awaiter(this, void 0, void 0, function* () {
|
|
51
67
|
const routes = request.labels
|
|
52
|
-
? (yield this.store.get(request.aor))
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
if (request.aor.startsWith('sip:')) {
|
|
68
|
+
? (yield this.store.get(request.aor)).filter((0, utils_1.filterOnlyMatchingLabels)(request.labels))
|
|
69
|
+
: (_a = (yield this.store.get(request.aor))) !== null && _a !== void 0 ? _a : [];
|
|
70
|
+
if (request.aor.startsWith(AOR_SCHEME.SIP)) {
|
|
56
71
|
return routes;
|
|
57
72
|
}
|
|
58
|
-
else if (request.aor.startsWith(
|
|
73
|
+
else if (request.aor.startsWith(AOR_SCHEME.BACKEND)) {
|
|
59
74
|
const backend = this.backends.get(request.aor);
|
|
60
75
|
if (!backend) {
|
|
61
76
|
throw new errors_1.NotRoutesFoundForAOR(request.aor);
|
|
62
77
|
}
|
|
63
78
|
// If it has not affinity sesssion then get next
|
|
64
|
-
return
|
|
65
|
-
? [this.
|
|
66
|
-
: [this.
|
|
79
|
+
return backend.withSessionAffinity
|
|
80
|
+
? [this.nextWithAffinity(routes, request.sessionAffinityRef)]
|
|
81
|
+
: [this.next(routes, backend)];
|
|
67
82
|
}
|
|
68
83
|
throw new errors_1.UnsupportedSchema(request.aor);
|
|
69
84
|
});
|
|
70
85
|
}
|
|
86
|
+
/** @inheritdoc */
|
|
71
87
|
removeRoutes(request) {
|
|
72
88
|
return this.store.delete(request.aor);
|
|
73
89
|
}
|
|
90
|
+
// eslint-disable-next-line require-jsdoc
|
|
74
91
|
next(routes, backend) {
|
|
75
92
|
if (backend.balancingAlgorithm === types_1.LB_ALGORITHM.LEAST_SESSIONS) {
|
|
76
93
|
return routes.sort((r1, r2) => r1.sessionCount - r2.sessionCount)[0];
|
|
77
94
|
}
|
|
78
95
|
// Continues using round-robin
|
|
79
|
-
const nextPosition = this.rrCount.get(
|
|
96
|
+
const nextPosition = this.rrCount.get(`${AOR_SCHEME.BACKEND}${backend.ref}`);
|
|
80
97
|
const result = routes[nextPosition];
|
|
81
|
-
if (nextPosition >=
|
|
98
|
+
if (nextPosition >= routes.length - 1) {
|
|
82
99
|
// Restarting round-robin counter
|
|
83
|
-
this.rrCount.set(
|
|
100
|
+
this.rrCount.set(`${AOR_SCHEME.BACKEND}${backend.ref}`, 0);
|
|
84
101
|
}
|
|
85
102
|
else {
|
|
86
|
-
this.rrCount.set(
|
|
103
|
+
this.rrCount.set(`${AOR_SCHEME.BACKEND}${backend.ref}`, nextPosition + 1);
|
|
87
104
|
}
|
|
88
105
|
return result;
|
|
89
106
|
}
|
|
90
107
|
// Backend with session affinity does not support round-robin
|
|
108
|
+
// eslint-disable-next-line require-jsdoc
|
|
91
109
|
nextWithAffinity(routes, sessionAffinityRef) {
|
|
92
110
|
let route = this.affinityStore.get(sessionAffinityRef);
|
|
93
111
|
if (route) {
|
package/dist/memory_store.d.ts
CHANGED
|
@@ -1,13 +1,26 @@
|
|
|
1
1
|
import { Route } from "@routr/common";
|
|
2
2
|
import { ILocatorStore } from "./types";
|
|
3
|
+
/**
|
|
4
|
+
* In-memory store for the locator service.
|
|
5
|
+
*/
|
|
3
6
|
export default class MemoryStore implements ILocatorStore {
|
|
4
7
|
private collections;
|
|
5
8
|
private cleanupCount;
|
|
6
9
|
private maxCyclesBeforeCleanup;
|
|
10
|
+
/**
|
|
11
|
+
* Creates a new in-memory store.
|
|
12
|
+
*
|
|
13
|
+
* @param {number} maxCyclesBeforeCleanup - Maximum number of cycles before cleanup
|
|
14
|
+
*/
|
|
7
15
|
constructor(maxCyclesBeforeCleanup?: number);
|
|
16
|
+
/** @inheritdoc */
|
|
8
17
|
put(key: string, route: Route): Promise<void>;
|
|
18
|
+
/** @inheritdoc */
|
|
9
19
|
get(key: string): Promise<Route[]>;
|
|
20
|
+
/** @inheritdoc */
|
|
10
21
|
delete(key: string): Promise<void>;
|
|
22
|
+
/** @inheritdoc */
|
|
11
23
|
size(): number;
|
|
24
|
+
/** @inheritdoc */
|
|
12
25
|
cleanup(): void;
|
|
13
26
|
}
|
package/dist/memory_store.js
CHANGED
|
@@ -2,17 +2,27 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const utils_1 = require("./utils");
|
|
4
4
|
const MAX_CYCLES_BEFORE_CLEANUP = 10000;
|
|
5
|
+
/**
|
|
6
|
+
* In-memory store for the locator service.
|
|
7
|
+
*/
|
|
5
8
|
class MemoryStore {
|
|
9
|
+
/**
|
|
10
|
+
* Creates a new in-memory store.
|
|
11
|
+
*
|
|
12
|
+
* @param {number} maxCyclesBeforeCleanup - Maximum number of cycles before cleanup
|
|
13
|
+
*/
|
|
6
14
|
constructor(maxCyclesBeforeCleanup = MAX_CYCLES_BEFORE_CLEANUP) {
|
|
7
15
|
this.collections = new Map();
|
|
8
16
|
this.maxCyclesBeforeCleanup = maxCyclesBeforeCleanup;
|
|
9
17
|
}
|
|
18
|
+
/** @inheritdoc */
|
|
10
19
|
put(key, route) {
|
|
11
|
-
|
|
20
|
+
var _a;
|
|
21
|
+
const routes = [...((_a = this.collections.get(key)) !== null && _a !== void 0 ? _a : [])];
|
|
12
22
|
// Avoids duplicate or expired routes
|
|
13
23
|
const filteredRoutes = routes
|
|
14
24
|
.filter(utils_1.expiredFilter)
|
|
15
|
-
.filter(r => utils_1.duplicateFilter(r, route));
|
|
25
|
+
.filter((r) => (0, utils_1.duplicateFilter)(r, route));
|
|
16
26
|
if (filteredRoutes.length > 0) {
|
|
17
27
|
this.collections.set(key, [route, ...filteredRoutes]);
|
|
18
28
|
}
|
|
@@ -21,22 +31,27 @@ class MemoryStore {
|
|
|
21
31
|
}
|
|
22
32
|
return;
|
|
23
33
|
}
|
|
34
|
+
/** @inheritdoc */
|
|
24
35
|
get(key) {
|
|
36
|
+
var _a;
|
|
25
37
|
// Cleanup every so often to avoid memory build up
|
|
26
38
|
this.cleanupCount++;
|
|
27
39
|
if (this.cleanupCount >= this.maxCyclesBeforeCleanup) {
|
|
28
40
|
this.cleanupCount = 0;
|
|
29
41
|
this.cleanup();
|
|
30
42
|
}
|
|
31
|
-
return Promise.resolve(this.collections.get(key)
|
|
43
|
+
return Promise.resolve(((_a = this.collections.get(key)) !== null && _a !== void 0 ? _a : []).filter(utils_1.expiredFilter));
|
|
32
44
|
}
|
|
45
|
+
/** @inheritdoc */
|
|
33
46
|
delete(key) {
|
|
34
47
|
this.collections.delete(key);
|
|
35
48
|
return;
|
|
36
49
|
}
|
|
50
|
+
/** @inheritdoc */
|
|
37
51
|
size() {
|
|
38
52
|
return this.collections.size;
|
|
39
53
|
}
|
|
54
|
+
/** @inheritdoc */
|
|
40
55
|
cleanup() {
|
|
41
56
|
// Remove any expired route from collection
|
|
42
57
|
this.collections.forEach((routes, key) => {
|
package/dist/redis_store.d.ts
CHANGED
|
@@ -1,9 +1,21 @@
|
|
|
1
1
|
import { Route } from "@routr/common";
|
|
2
|
-
import { ILocatorStore
|
|
2
|
+
import { ILocatorStore } from "./types";
|
|
3
|
+
import { Redis } from "@routr/common";
|
|
4
|
+
/**
|
|
5
|
+
* Redis store for the locator service.
|
|
6
|
+
*/
|
|
3
7
|
export default class RedisStore implements ILocatorStore {
|
|
4
8
|
client: any;
|
|
5
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Creates a new redis store.
|
|
11
|
+
*
|
|
12
|
+
* @param {Redis.RedisStoreConfig} config - Optional store config
|
|
13
|
+
*/
|
|
14
|
+
constructor(config?: Redis.RedisStoreConfig);
|
|
15
|
+
/** @inheritdoc */
|
|
6
16
|
put(key: string, route: Route): Promise<void>;
|
|
17
|
+
/** @inheritdoc */
|
|
7
18
|
get(key: string): Promise<Route[]>;
|
|
19
|
+
/** @inheritdoc */
|
|
8
20
|
delete(key: string): Promise<void>;
|
|
9
21
|
}
|
package/dist/redis_store.js
CHANGED
|
@@ -15,34 +15,44 @@ var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
|
15
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
16
|
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
17
17
|
};
|
|
18
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
19
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
20
|
-
};
|
|
21
18
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
19
|
const redis_1 = require("redis");
|
|
23
|
-
const
|
|
24
|
-
const logger_1 =
|
|
20
|
+
const common_1 = require("@routr/common");
|
|
21
|
+
const logger_1 = require("@fonoster/logger");
|
|
22
|
+
const logger = (0, logger_1.getLogger)({ service: "location", filePath: __filename });
|
|
23
|
+
/**
|
|
24
|
+
* Redis store for the locator service.
|
|
25
|
+
*/
|
|
25
26
|
class RedisStore {
|
|
27
|
+
/**
|
|
28
|
+
* Creates a new redis store.
|
|
29
|
+
*
|
|
30
|
+
* @param {Redis.RedisStoreConfig} config - Optional store config
|
|
31
|
+
*/
|
|
26
32
|
constructor(config) {
|
|
27
|
-
this.client = config
|
|
33
|
+
this.client = config
|
|
34
|
+
? (0, redis_1.createClient)({ url: common_1.Redis.getRedisUrlFromConfig(config) })
|
|
35
|
+
: (0, redis_1.createClient)();
|
|
28
36
|
this.client.connect();
|
|
29
|
-
this.client.on(
|
|
37
|
+
this.client.on("error", (err) => logger.error("redis client error: ", err));
|
|
30
38
|
}
|
|
39
|
+
/** @inheritdoc */
|
|
31
40
|
put(key, route) {
|
|
32
41
|
return __awaiter(this, void 0, void 0, function* () {
|
|
33
42
|
// Formatted the key to ensure it is unique
|
|
34
|
-
logger_1.default.verbose(`${key}:${route.user}${route.host}${route.port}`);
|
|
35
43
|
yield this.client.set(`${key}:${route.user}${route.host}${route.port}`, JSON.stringify(route), {
|
|
36
44
|
EX: route.expires
|
|
37
45
|
});
|
|
38
46
|
return;
|
|
39
47
|
});
|
|
40
48
|
}
|
|
49
|
+
/** @inheritdoc */
|
|
41
50
|
get(key) {
|
|
42
51
|
var e_1, _a;
|
|
43
52
|
return __awaiter(this, void 0, void 0, function* () {
|
|
44
53
|
const routes = [];
|
|
45
54
|
try {
|
|
55
|
+
// eslint-disable-next-line no-loops/no-loops
|
|
46
56
|
for (var _b = __asyncValues(yield this.client.scanIterator({
|
|
47
57
|
CURSOR: 0,
|
|
48
58
|
MATCH: `${key}:*`
|
|
@@ -61,10 +71,12 @@ class RedisStore {
|
|
|
61
71
|
return routes;
|
|
62
72
|
});
|
|
63
73
|
}
|
|
74
|
+
/** @inheritdoc */
|
|
64
75
|
delete(key) {
|
|
65
76
|
var e_2, _a;
|
|
66
77
|
return __awaiter(this, void 0, void 0, function* () {
|
|
67
78
|
try {
|
|
79
|
+
// eslint-disable-next-line no-loops/no-loops
|
|
68
80
|
for (var _b = __asyncValues(yield this.client.scanIterator({
|
|
69
81
|
CURSOR: 0,
|
|
70
82
|
MATCH: `${key}:*`
|
package/dist/runner.js
CHANGED
|
@@ -22,13 +22,18 @@ 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
|
-
|
|
25
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
26
|
+
require("./tracer").init("dispatcher");
|
|
26
27
|
const service_1 = __importDefault(require("./service"));
|
|
27
28
|
const get_config_1 = require("./config/get_config");
|
|
28
|
-
const
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
const common_1 = require("@routr/common");
|
|
30
|
+
const logger_1 = require("@fonoster/logger");
|
|
31
|
+
const logger = (0, logger_1.getLogger)({ service: "location", filePath: __filename });
|
|
32
|
+
common_1.Assertions.assertEnvsAreSet(["CONFIG_PATH"]);
|
|
33
|
+
const result = (0, get_config_1.getConfig)(process.env.CONFIG_PATH);
|
|
34
|
+
if (result._tag === "Right") {
|
|
35
|
+
(0, service_1.default)(result.right);
|
|
31
36
|
}
|
|
32
37
|
else {
|
|
33
|
-
|
|
38
|
+
logger.error(result.left);
|
|
34
39
|
}
|
package/dist/service.d.ts
CHANGED
package/dist/service.js
CHANGED
|
@@ -27,20 +27,26 @@ const utils_1 = require("./utils");
|
|
|
27
27
|
const location_1 = __importDefault(require("./location"));
|
|
28
28
|
const memory_store_1 = __importDefault(require("./memory_store"));
|
|
29
29
|
const redis_store_1 = __importDefault(require("./redis_store"));
|
|
30
|
-
const logger_1 =
|
|
30
|
+
const logger_1 = require("@fonoster/logger");
|
|
31
|
+
const logger = (0, logger_1.getLogger)({ service: "location", filePath: __filename });
|
|
31
32
|
const allowedParameters = ["host", "port", "username", "password", "secure"];
|
|
33
|
+
/**
|
|
34
|
+
* Creates a new locator service.
|
|
35
|
+
*
|
|
36
|
+
* @param {LocationConfig} config - Service configuration
|
|
37
|
+
*/
|
|
32
38
|
function LocationService(config) {
|
|
33
39
|
const { bindAddr, cache } = config;
|
|
34
40
|
let store;
|
|
35
41
|
if (cache.provider === types_1.CACHE_PROVIDER.REDIS) {
|
|
36
|
-
store = new redis_store_1.default(utils_1.configFromString(cache.parameters, allowedParameters));
|
|
42
|
+
store = new redis_store_1.default((0, utils_1.configFromString)(cache.parameters, allowedParameters));
|
|
37
43
|
}
|
|
38
44
|
else {
|
|
39
45
|
store = new memory_store_1.default();
|
|
40
46
|
}
|
|
41
47
|
const backends = new Map();
|
|
42
|
-
config.backends.forEach(b => backends.set(`backend:${b.ref}`, b));
|
|
43
|
-
common_1.createService(utils_1.getServiceInfo(bindAddr, new location_1.default(store, backends)));
|
|
44
|
-
|
|
48
|
+
config.backends.forEach((b) => backends.set(`backend:${b.ref}`, b));
|
|
49
|
+
(0, common_1.createService)((0, utils_1.getServiceInfo)(bindAddr, new location_1.default(store, backends)));
|
|
50
|
+
logger.info(`using ${cache.provider} as cache provider`);
|
|
45
51
|
}
|
|
46
52
|
exports.default = LocationService;
|
package/dist/tracer.d.ts
ADDED
package/dist/tracer.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.init = void 0;
|
|
7
|
+
/*
|
|
8
|
+
* Copyright (C) 2022 by Fonoster Inc (https://fonoster.com)
|
|
9
|
+
* http://github.com/fonoster/routr
|
|
10
|
+
*
|
|
11
|
+
* This file is part of Routr
|
|
12
|
+
*
|
|
13
|
+
* Licensed under the MIT License (the "License")
|
|
14
|
+
* you may not use this file except in compliance with
|
|
15
|
+
* the License. You may obtain a copy of the License at
|
|
16
|
+
*
|
|
17
|
+
* https://opensource.org/licenses/MIT
|
|
18
|
+
*
|
|
19
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
20
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
21
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
22
|
+
* See the License for the specific language governing permissions and
|
|
23
|
+
* limitations under the License.
|
|
24
|
+
*/
|
|
25
|
+
const api_1 = __importDefault(require("@opentelemetry/api"));
|
|
26
|
+
const instrumentation_1 = require("@opentelemetry/instrumentation");
|
|
27
|
+
const sdk_trace_node_1 = require("@opentelemetry/sdk-trace-node");
|
|
28
|
+
const resources_1 = require("@opentelemetry/resources");
|
|
29
|
+
const semantic_conventions_1 = require("@opentelemetry/semantic-conventions");
|
|
30
|
+
const sdk_trace_base_1 = require("@opentelemetry/sdk-trace-base");
|
|
31
|
+
const exporter_jaeger_1 = require("@opentelemetry/exporter-jaeger");
|
|
32
|
+
const instrumentation_grpc_1 = require("@opentelemetry/instrumentation-grpc");
|
|
33
|
+
/**
|
|
34
|
+
* This function registers the instrumentations for the service.
|
|
35
|
+
*
|
|
36
|
+
* @param {string} serviceName - The name of the service.
|
|
37
|
+
* @return {Tracer} The tracer object.
|
|
38
|
+
*/
|
|
39
|
+
function init(serviceName) {
|
|
40
|
+
const provider = new sdk_trace_node_1.NodeTracerProvider({
|
|
41
|
+
resource: new resources_1.Resource({
|
|
42
|
+
[semantic_conventions_1.SemanticResourceAttributes.SERVICE_NAME]: serviceName
|
|
43
|
+
})
|
|
44
|
+
});
|
|
45
|
+
const exporter = new exporter_jaeger_1.JaegerExporter();
|
|
46
|
+
provider.addSpanProcessor(new sdk_trace_base_1.SimpleSpanProcessor(exporter));
|
|
47
|
+
provider.register();
|
|
48
|
+
(0, instrumentation_1.registerInstrumentations)({
|
|
49
|
+
instrumentations: [new instrumentation_grpc_1.GrpcInstrumentation()]
|
|
50
|
+
});
|
|
51
|
+
return api_1.default.trace.getTracer("routr-tracer");
|
|
52
|
+
}
|
|
53
|
+
exports.init = init;
|
package/dist/types.d.ts
CHANGED
|
@@ -35,17 +35,14 @@ export interface RemoveRoutesRequest {
|
|
|
35
35
|
export interface Backend {
|
|
36
36
|
ref: string;
|
|
37
37
|
balancingAlgorithm?: LB_ALGORITHM;
|
|
38
|
-
|
|
39
|
-
enabled: boolean;
|
|
40
|
-
ref: string;
|
|
41
|
-
};
|
|
38
|
+
withSessionAffinity?: boolean;
|
|
42
39
|
}
|
|
43
40
|
export interface LocationConfig {
|
|
44
41
|
bindAddr: string;
|
|
45
42
|
backends?: Backend[];
|
|
46
43
|
cache?: {
|
|
47
44
|
provider: CACHE_PROVIDER;
|
|
48
|
-
parameters
|
|
45
|
+
parameters?: string;
|
|
49
46
|
};
|
|
50
47
|
}
|
|
51
48
|
export interface RedisStoreConfig {
|
package/dist/utils.d.ts
CHANGED
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
import { Route } from "@routr/common";
|
|
2
|
-
import {
|
|
3
|
-
import { Backend, ILocationService, RedisStoreConfig } from "./types";
|
|
1
|
+
import { Route, ServiceInfo } from "@routr/common";
|
|
2
|
+
import { ILocationService } from "./types";
|
|
4
3
|
export declare const expiredFilter: (r: Route) => boolean;
|
|
5
4
|
export declare const duplicateFilter: (r1: Route, r2: Route) => boolean;
|
|
6
5
|
export declare const mergeKeyValue: (map: Map<string, string>) => string[];
|
|
7
6
|
export declare const compareArrays: (arr: string[], target: string[]) => boolean;
|
|
8
7
|
export declare const filterOnlyMatchingLabels: (requestLabels: Map<string, string>) => (route: Route) => boolean;
|
|
9
|
-
export declare const
|
|
10
|
-
export declare function getServiceInfo(bindAddr: string, locator: ILocationService): ServiceInfo;
|
|
8
|
+
export declare const getServiceInfo: (bindAddr: string, locator: ILocationService) => ServiceInfo;
|
|
11
9
|
export declare const configFromString: (params: string, allowedKeys: string[]) => Record<string, string | boolean>;
|
|
12
|
-
export declare const getUrlString: (config: RedisStoreConfig) => string;
|
package/dist/utils.js
CHANGED
|
@@ -9,27 +9,44 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.
|
|
12
|
+
exports.configFromString = exports.getServiceInfo = exports.filterOnlyMatchingLabels = exports.compareArrays = exports.mergeKeyValue = exports.duplicateFilter = exports.expiredFilter = void 0;
|
|
13
|
+
/*
|
|
14
|
+
* Copyright (C) 2022 by Fonoster Inc (https://fonoster.com)
|
|
15
|
+
* http://github.com/fonoster/routr
|
|
16
|
+
*
|
|
17
|
+
* This file is part of Routr
|
|
18
|
+
*
|
|
19
|
+
* Licensed under the MIT License (the "License")
|
|
20
|
+
* you may not use this file except in compliance with
|
|
21
|
+
* the License. You may obtain a copy of the License at
|
|
22
|
+
*
|
|
23
|
+
* https://opensource.org/licenses/MIT
|
|
24
|
+
*
|
|
25
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
26
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
27
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
28
|
+
* See the License for the specific language governing permissions and
|
|
29
|
+
* limitations under the License.
|
|
30
|
+
*/
|
|
13
31
|
const common_1 = require("@routr/common");
|
|
14
32
|
const errors_1 = require("./errors");
|
|
15
|
-
const expiredFilter = (r) =>
|
|
33
|
+
const expiredFilter = (r) => r.expires - (Date.now() - r.registeredOn) / 1000 > 0;
|
|
16
34
|
exports.expiredFilter = expiredFilter;
|
|
17
35
|
const duplicateFilter = (r1, r2) => !(r1.host === r2.host && r1.port === r2.port);
|
|
18
36
|
exports.duplicateFilter = duplicateFilter;
|
|
19
|
-
const mergeKeyValue = (map) => Array.from(map).map(l => l[0] + l[1]);
|
|
37
|
+
const mergeKeyValue = (map) => Array.from(map).map((l) => l[0] + l[1]);
|
|
20
38
|
exports.mergeKeyValue = mergeKeyValue;
|
|
21
|
-
const compareArrays = (arr, target) => target.every(v => arr.includes(v)) && arr.length === target.length;
|
|
39
|
+
const compareArrays = (arr, target) => target.every((v) => arr.includes(v)) && arr.length === target.length;
|
|
22
40
|
exports.compareArrays = compareArrays;
|
|
23
41
|
const filterOnlyMatchingLabels = (requestLabels) => (route) => route.labels
|
|
24
|
-
? exports.compareArrays(exports.mergeKeyValue(requestLabels), exports.mergeKeyValue(route.labels))
|
|
42
|
+
? (0, exports.compareArrays)((0, exports.mergeKeyValue)(requestLabels), (0, exports.mergeKeyValue)(route.labels))
|
|
25
43
|
: false;
|
|
26
44
|
exports.filterOnlyMatchingLabels = filterOnlyMatchingLabels;
|
|
27
|
-
const
|
|
28
|
-
exports.hasAffinitySession = hasAffinitySession;
|
|
29
|
-
function getServiceInfo(bindAddr, locator) {
|
|
45
|
+
const getServiceInfo = (bindAddr, locator) => {
|
|
30
46
|
return {
|
|
31
47
|
name: "location",
|
|
32
48
|
bindAddr,
|
|
49
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
33
50
|
service: common_1.LOCATION_OBJECT_PROTO.Location.service,
|
|
34
51
|
handlers: {
|
|
35
52
|
addRoute: (call, callback) => {
|
|
@@ -41,10 +58,10 @@ function getServiceInfo(bindAddr, locator) {
|
|
|
41
58
|
callback(e, null);
|
|
42
59
|
}
|
|
43
60
|
},
|
|
44
|
-
findRoutes: (call, callback) => __awaiter(
|
|
61
|
+
findRoutes: (call, callback) => __awaiter(void 0, void 0, void 0, function* () {
|
|
45
62
|
try {
|
|
46
63
|
const routes = yield locator.findRoutes(call.request);
|
|
47
|
-
if (routes.length
|
|
64
|
+
if (routes.length === 0)
|
|
48
65
|
throw new errors_1.NotRoutesFoundForAOR(call.request.aor);
|
|
49
66
|
callback(null, {
|
|
50
67
|
routes: routes
|
|
@@ -54,7 +71,7 @@ function getServiceInfo(bindAddr, locator) {
|
|
|
54
71
|
callback(e, null);
|
|
55
72
|
}
|
|
56
73
|
}),
|
|
57
|
-
removeRoutes: (call, callback) => __awaiter(
|
|
74
|
+
removeRoutes: (call, callback) => __awaiter(void 0, void 0, void 0, function* () {
|
|
58
75
|
try {
|
|
59
76
|
callback(null, {
|
|
60
77
|
routes: yield locator.findRoutes(call.request)
|
|
@@ -66,18 +83,18 @@ function getServiceInfo(bindAddr, locator) {
|
|
|
66
83
|
})
|
|
67
84
|
}
|
|
68
85
|
};
|
|
69
|
-
}
|
|
86
|
+
};
|
|
70
87
|
exports.getServiceInfo = getServiceInfo;
|
|
71
88
|
const configFromString = (params, allowedKeys) => {
|
|
72
89
|
if (params.length === 0)
|
|
73
90
|
return {};
|
|
74
91
|
const parameters = {};
|
|
75
|
-
params.split(
|
|
92
|
+
params.split(",").forEach((par) => {
|
|
76
93
|
try {
|
|
77
|
-
const key = par.split(
|
|
78
|
-
const value = par.split(
|
|
94
|
+
const key = par.split("=")[0];
|
|
95
|
+
const value = par.split("=")[1];
|
|
79
96
|
if (allowedKeys.indexOf(key) === -1) {
|
|
80
|
-
throw `invalid parameter: ${key}
|
|
97
|
+
throw new Error(`invalid parameter: ${key}`);
|
|
81
98
|
}
|
|
82
99
|
else {
|
|
83
100
|
parameters[key] = value === "true" ? true : value;
|
|
@@ -90,10 +107,3 @@ const configFromString = (params, allowedKeys) => {
|
|
|
90
107
|
return parameters;
|
|
91
108
|
};
|
|
92
109
|
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.
|
|
3
|
+
"version": "2.0.6-alpha.1",
|
|
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,18 @@
|
|
|
25
25
|
"access": "public"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
+
"@fonoster/logger": "0.3.18",
|
|
28
29
|
"@grpc/grpc-js": "^1.5.9",
|
|
29
|
-
"@
|
|
30
|
-
"@
|
|
30
|
+
"@opentelemetry/api": "^1.0.4",
|
|
31
|
+
"@opentelemetry/exporter-jaeger": "^1.0.4",
|
|
32
|
+
"@opentelemetry/instrumentation": "^0.27.0",
|
|
33
|
+
"@opentelemetry/instrumentation-grpc": "^0.27.0",
|
|
34
|
+
"@opentelemetry/resources": "^1.0.4",
|
|
35
|
+
"@opentelemetry/sdk-trace-base": "^1.0.4",
|
|
36
|
+
"@opentelemetry/sdk-trace-node": "^1.0.4",
|
|
37
|
+
"@opentelemetry/semantic-conventions": "^1.0.4",
|
|
38
|
+
"@routr/common": "^2.0.6-alpha.1",
|
|
39
|
+
"@routr/processor": "^2.0.6-alpha.1",
|
|
31
40
|
"ajv": "^6.12.6",
|
|
32
41
|
"fp-ts": "^2.11.8",
|
|
33
42
|
"redis": "^4.0.4"
|
|
@@ -39,5 +48,5 @@
|
|
|
39
48
|
"bugs": {
|
|
40
49
|
"url": "https://github.com/fonoster/routr/issues"
|
|
41
50
|
},
|
|
42
|
-
"gitHead": "
|
|
51
|
+
"gitHead": "389513636bbac9ab7ffbe14f1b8ecdb5bb93bad4"
|
|
43
52
|
}
|