@proteinjs/service 1.0.32 → 1.1.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/CHANGELOG.md +22 -0
- package/dist/src/Service.d.ts +11 -1
- package/dist/src/Service.d.ts.map +1 -1
- package/dist/src/Service.js +7 -2
- package/dist/src/Service.js.map +1 -1
- package/dist/src/ServiceClient.d.ts +2 -1
- package/dist/src/ServiceClient.d.ts.map +1 -1
- package/dist/src/ServiceClient.js +38 -4
- package/dist/src/ServiceClient.js.map +1 -1
- package/dist/src/ServiceRouter.js +2 -2
- package/dist/src/ServiceRouter.js.map +1 -1
- package/package.json +2 -2
- package/src/Service.ts +25 -2
- package/src/ServiceClient.ts +20 -3
- package/src/ServiceRouter.ts +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,28 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [1.1.1](https://github.com/proteinjs/service/compare/@proteinjs/service@1.1.0...@proteinjs/service@1.1.1) (2024-09-10)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* move retry logic into ServiceClient. send 400s in ServiceRouter if there is an error in the routing. ([742aa15](https://github.com/proteinjs/service/commit/742aa15ce505f115e94093fc96e6cac811aaf83e))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# [1.1.0](https://github.com/proteinjs/service/compare/@proteinjs/service@1.0.32...@proteinjs/service@1.1.0) (2024-09-09)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
### Features
|
|
21
|
+
|
|
22
|
+
* Add retry functionality to serviceFactory with configurable retries per method. Implement RetryConfig type and logic to handle retries for specified service methods. ([cc9627f](https://github.com/proteinjs/service/commit/cc9627fe12aa40920764e0fa2debc1547881b887))
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
6
28
|
## [1.0.32](https://github.com/proteinjs/service/compare/@proteinjs/service@1.0.31...@proteinjs/service@1.0.32) (2024-08-30)
|
|
7
29
|
|
|
8
30
|
|
package/dist/src/Service.d.ts
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import { SerializableFunction, NotFunction } from '@proteinjs/serializer';
|
|
2
2
|
import { Loadable } from '@proteinjs/reflection';
|
|
3
3
|
import { Debouncer } from '@proteinjs/util';
|
|
4
|
+
type RemoveIndex<T> = {
|
|
5
|
+
[K in keyof T as string extends K ? never : number extends K ? never : symbol extends K ? never : K]: T[K];
|
|
6
|
+
};
|
|
7
|
+
type KeysWithoutIndexSignature<T> = keyof RemoveIndex<T>;
|
|
8
|
+
type Diff<T, U> = T extends U ? never : T;
|
|
9
|
+
type KeysWithoutService<T extends Service> = Diff<KeysWithoutIndexSignature<T>, KeysWithoutIndexSignature<Service>>;
|
|
10
|
+
type RetryConfig<T extends Service> = {
|
|
11
|
+
[K in KeysWithoutService<T>]?: number;
|
|
12
|
+
};
|
|
4
13
|
export interface Service extends Loadable {
|
|
5
14
|
serviceMetadata?: {
|
|
6
15
|
auth?: {
|
|
@@ -30,5 +39,6 @@ export interface Service extends Loadable {
|
|
|
30
39
|
* @param debouncer optionally pass in an instance of debouncer if you want to limit service client calls
|
|
31
40
|
* @returns a function that creates a Service
|
|
32
41
|
*/
|
|
33
|
-
export declare const serviceFactory: <T extends Service>(serviceInterfaceQualifiedName: string, debouncer?: Debouncer) => () => T;
|
|
42
|
+
export declare const serviceFactory: <T extends Service>(serviceInterfaceQualifiedName: string, debouncer?: Debouncer, retryConfig?: RetryConfig<T> | undefined) => () => T;
|
|
43
|
+
export {};
|
|
34
44
|
//# sourceMappingURL=Service.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Service.d.ts","sourceRoot":"","sources":["../../src/Service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAC1E,OAAO,EAAE,QAAQ,EAAoB,MAAM,uBAAuB,CAAC;AAEnE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,MAAM,WAAW,OAAQ,SAAQ,QAAQ;IACvC,eAAe,CAAC,EAAE;QAChB,IAAI,CAAC,EAAE;YACL,2HAA2H;YAC3H,MAAM,CAAC,EAAE,OAAO,CAAC;YACjB,kIAAkI;YAClI,QAAQ,CAAC,EAAE,OAAO,CAAC;YACnB,8HAA8H;YAC9H,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;YACjB;;;;;eAKG;YACH,SAAS,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC;SAC1D,CAAC;QACF,uFAAuF;QACvF,UAAU,CAAC,EAAE,OAAO,CAAC;KACtB,CAAC;IACF,CAAC,IAAI,EAAE,MAAM,GAAG,oBAAoB,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;CACzD;AAED;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,qDACM,MAAM,cACzB,SAAS,
|
|
1
|
+
{"version":3,"file":"Service.d.ts","sourceRoot":"","sources":["../../src/Service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAC1E,OAAO,EAAE,QAAQ,EAAoB,MAAM,uBAAuB,CAAC;AAEnE,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,KAAK,WAAW,CAAC,CAAC,IAAI;KACnB,CAAC,IAAI,MAAM,CAAC,IAAI,MAAM,SAAS,CAAC,GAAG,KAAK,GAAG,MAAM,SAAS,CAAC,GAAG,KAAK,GAAG,MAAM,SAAS,CAAC,GAAG,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;CAC3G,CAAC;AACF,KAAK,yBAAyB,CAAC,CAAC,IAAI,MAAM,WAAW,CAAC,CAAC,CAAC,CAAC;AAGzD,KAAK,IAAI,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;AAG1C,KAAK,kBAAkB,CAAC,CAAC,SAAS,OAAO,IAAI,IAAI,CAAC,yBAAyB,CAAC,CAAC,CAAC,EAAE,yBAAyB,CAAC,OAAO,CAAC,CAAC,CAAC;AAEpH,KAAK,WAAW,CAAC,CAAC,SAAS,OAAO,IAAI;KACnC,CAAC,IAAI,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM;CACtC,CAAC;AAEF,MAAM,WAAW,OAAQ,SAAQ,QAAQ;IACvC,eAAe,CAAC,EAAE;QAChB,IAAI,CAAC,EAAE;YACL,2HAA2H;YAC3H,MAAM,CAAC,EAAE,OAAO,CAAC;YACjB,kIAAkI;YAClI,QAAQ,CAAC,EAAE,OAAO,CAAC;YACnB,8HAA8H;YAC9H,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;YACjB;;;;;eAKG;YACH,SAAS,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC;SAC1D,CAAC;QACF,uFAAuF;QACvF,UAAU,CAAC,EAAE,OAAO,CAAC;KACtB,CAAC;IACF,CAAC,IAAI,EAAE,MAAM,GAAG,oBAAoB,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;CACzD;AAED;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,qDACM,MAAM,cACzB,SAAS,sDAqBtB,CAAC"}
|
package/dist/src/Service.js
CHANGED
|
@@ -10,14 +10,19 @@ var ServiceClient_1 = require("./ServiceClient");
|
|
|
10
10
|
* @param debouncer optionally pass in an instance of debouncer if you want to limit service client calls
|
|
11
11
|
* @returns a function that creates a Service
|
|
12
12
|
*/
|
|
13
|
-
var serviceFactory = function (serviceInterfaceQualifiedName, debouncer) {
|
|
13
|
+
var serviceFactory = function (serviceInterfaceQualifiedName, debouncer, retryConfig) {
|
|
14
14
|
return function () {
|
|
15
15
|
var service = {};
|
|
16
16
|
var serviceInterface = reflection_1.SourceRepository.get().interface(serviceInterfaceQualifiedName);
|
|
17
17
|
for (var _i = 0, _a = serviceInterface.methods; _i < _a.length; _i++) {
|
|
18
18
|
var method = _a[_i];
|
|
19
19
|
var servicePath = "/service/".concat(serviceInterface.qualifiedName, "/").concat(method.name);
|
|
20
|
-
var
|
|
20
|
+
var retryCount = 0;
|
|
21
|
+
if (retryConfig && method.name in retryConfig) {
|
|
22
|
+
var methodName = method.name;
|
|
23
|
+
retryCount = retryConfig[methodName];
|
|
24
|
+
}
|
|
25
|
+
var serviceClient = new ServiceClient_1.ServiceClient(servicePath, method, debouncer, retryCount);
|
|
21
26
|
service[method.name] = serviceClient.send.bind(serviceClient);
|
|
22
27
|
}
|
|
23
28
|
return service;
|
package/dist/src/Service.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Service.js","sourceRoot":"","sources":["../../src/Service.ts"],"names":[],"mappings":";;;AACA,oDAAmE;AACnE,iDAAgD;
|
|
1
|
+
{"version":3,"file":"Service.js","sourceRoot":"","sources":["../../src/Service.ts"],"names":[],"mappings":";;;AACA,oDAAmE;AACnE,iDAAgD;AAyChD;;;;;;GAMG;AACI,IAAM,cAAc,GAAG,UAC5B,6BAAqC,EACrC,SAAqB,EACrB,WAA4B;IAE5B,OAAO;QACL,IAAM,OAAO,GAAQ,EAAE,CAAC;QACxB,IAAM,gBAAgB,GAAG,6BAAgB,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,6BAA6B,CAAC,CAAC;QACzF,KAAqB,UAAwB,EAAxB,KAAA,gBAAgB,CAAC,OAAO,EAAxB,cAAwB,EAAxB,IAAwB,EAAE;YAA1C,IAAM,MAAM,SAAA;YACf,IAAM,WAAW,GAAG,mBAAY,gBAAgB,CAAC,aAAa,cAAI,MAAM,CAAC,IAAI,CAAE,CAAC;YAEhF,IAAI,UAAU,GAAG,CAAC,CAAC;YACnB,IAAI,WAAW,IAAI,MAAM,CAAC,IAAI,IAAI,WAAW,EAAE;gBAC7C,IAAM,UAAU,GAAG,MAAM,CAAC,IAA6B,CAAC;gBACxD,UAAU,GAAG,WAAW,CAAC,UAAU,CAAE,CAAC;aACvC;YAED,IAAM,aAAa,GAAG,IAAI,6BAAa,CAAC,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;YACpF,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;SAC/D;QAED,OAAO,OAAO,CAAC;IACjB,CAAC,CAAC;AACJ,CAAC,CAAC;AAvBW,QAAA,cAAc,kBAuBzB"}
|
|
@@ -4,8 +4,9 @@ export declare class ServiceClient {
|
|
|
4
4
|
private servicePath;
|
|
5
5
|
private serviceMethod;
|
|
6
6
|
private debouncer?;
|
|
7
|
+
private retryCount;
|
|
7
8
|
private static requestCounter;
|
|
8
|
-
constructor(servicePath: string, serviceMethod: Method, debouncer?: Debouncer | undefined);
|
|
9
|
+
constructor(servicePath: string, serviceMethod: Method, debouncer?: Debouncer | undefined, retryCount?: number);
|
|
9
10
|
send(...args: any[]): Promise<any>;
|
|
10
11
|
private _send;
|
|
11
12
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServiceClient.d.ts","sourceRoot":"","sources":["../../src/ServiceClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAE/C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C,qBAAa,aAAa;IAItB,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"ServiceClient.d.ts","sourceRoot":"","sources":["../../src/ServiceClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAC;AAE/C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAG5C,qBAAa,aAAa;IAItB,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,aAAa;IACrB,OAAO,CAAC,SAAS,CAAC;IAClB,OAAO,CAAC,UAAU;IANpB,OAAO,CAAC,MAAM,CAAC,cAAc,CAAK;gBAGxB,WAAW,EAAE,MAAM,EACnB,aAAa,EAAE,MAAM,EACrB,SAAS,CAAC,uBAAW,EACrB,UAAU,GAAE,MAAU;IAG1B,IAAI,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC;YA0C1B,KAAK;CAsBpB"}
|
|
@@ -40,10 +40,12 @@ exports.ServiceClient = void 0;
|
|
|
40
40
|
var serializer_1 = require("@proteinjs/serializer");
|
|
41
41
|
var isVoidReturnType_1 = require("./isVoidReturnType");
|
|
42
42
|
var ServiceClient = /** @class */ (function () {
|
|
43
|
-
function ServiceClient(servicePath, serviceMethod, debouncer) {
|
|
43
|
+
function ServiceClient(servicePath, serviceMethod, debouncer, retryCount) {
|
|
44
|
+
if (retryCount === void 0) { retryCount = 0; }
|
|
44
45
|
this.servicePath = servicePath;
|
|
45
46
|
this.serviceMethod = serviceMethod;
|
|
46
47
|
this.debouncer = debouncer;
|
|
48
|
+
this.retryCount = retryCount;
|
|
47
49
|
}
|
|
48
50
|
ServiceClient.prototype.send = function () {
|
|
49
51
|
var args = [];
|
|
@@ -51,7 +53,7 @@ var ServiceClient = /** @class */ (function () {
|
|
|
51
53
|
args[_i] = arguments[_i];
|
|
52
54
|
}
|
|
53
55
|
return __awaiter(this, void 0, void 0, function () {
|
|
54
|
-
var sendRequest;
|
|
56
|
+
var sendRequest, executeWithRetry, executeRequest;
|
|
55
57
|
var _this = this;
|
|
56
58
|
return __generator(this, function (_a) {
|
|
57
59
|
sendRequest = function () { return __awaiter(_this, void 0, void 0, function () {
|
|
@@ -76,11 +78,43 @@ var ServiceClient = /** @class */ (function () {
|
|
|
76
78
|
}
|
|
77
79
|
});
|
|
78
80
|
}); };
|
|
81
|
+
executeWithRetry = function (fn) { return __awaiter(_this, void 0, void 0, function () {
|
|
82
|
+
var maxAttempts, attempt, error_1;
|
|
83
|
+
return __generator(this, function (_a) {
|
|
84
|
+
switch (_a.label) {
|
|
85
|
+
case 0:
|
|
86
|
+
maxAttempts = 1 + this.retryCount;
|
|
87
|
+
attempt = 0;
|
|
88
|
+
_a.label = 1;
|
|
89
|
+
case 1:
|
|
90
|
+
if (!(attempt < maxAttempts)) return [3 /*break*/, 7];
|
|
91
|
+
_a.label = 2;
|
|
92
|
+
case 2:
|
|
93
|
+
_a.trys.push([2, 4, , 6]);
|
|
94
|
+
return [4 /*yield*/, fn()];
|
|
95
|
+
case 3: return [2 /*return*/, _a.sent()];
|
|
96
|
+
case 4:
|
|
97
|
+
error_1 = _a.sent();
|
|
98
|
+
if (attempt === maxAttempts - 1) {
|
|
99
|
+
throw error_1;
|
|
100
|
+
}
|
|
101
|
+
return [4 /*yield*/, new Promise(function (resolve) { return setTimeout(resolve, 1000); })];
|
|
102
|
+
case 5:
|
|
103
|
+
_a.sent(); // 1 second delay before retry
|
|
104
|
+
return [3 /*break*/, 6];
|
|
105
|
+
case 6:
|
|
106
|
+
attempt++;
|
|
107
|
+
return [3 /*break*/, 1];
|
|
108
|
+
case 7: return [2 /*return*/];
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
}); };
|
|
112
|
+
executeRequest = this.retryCount > 0 ? executeWithRetry : function (fn) { return fn(); };
|
|
79
113
|
if (this.debouncer) {
|
|
80
|
-
this.debouncer.debounce(sendRequest);
|
|
114
|
+
return [2 /*return*/, this.debouncer.debounce(function () { return executeRequest(sendRequest); })];
|
|
81
115
|
}
|
|
82
116
|
else {
|
|
83
|
-
return [2 /*return*/, sendRequest
|
|
117
|
+
return [2 /*return*/, executeRequest(sendRequest)];
|
|
84
118
|
}
|
|
85
119
|
return [2 /*return*/];
|
|
86
120
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServiceClient.js","sourceRoot":"","sources":["../../src/ServiceClient.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,oDAAmD;AAEnD,uDAAsD;AAEtD;IAGE,uBACU,WAAmB,EACnB,aAAqB,EACrB,SAAqB;
|
|
1
|
+
{"version":3,"file":"ServiceClient.js","sourceRoot":"","sources":["../../src/ServiceClient.ts"],"names":[],"mappings":"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"}
|
|
@@ -80,7 +80,7 @@ var ServiceRouter = /** @class */ (function () {
|
|
|
80
80
|
if (!serviceExecutor) {
|
|
81
81
|
error = "Unable to find service matching path: ".concat(request.path);
|
|
82
82
|
this.logger.error({ message: error });
|
|
83
|
-
response.send({ error: error });
|
|
83
|
+
response.status(404).send({ error: error });
|
|
84
84
|
return [2 /*return*/];
|
|
85
85
|
}
|
|
86
86
|
_a.label = 1;
|
|
@@ -98,7 +98,7 @@ var ServiceRouter = /** @class */ (function () {
|
|
|
98
98
|
this.logger.error({ error: error_1 });
|
|
99
99
|
errorMessage = 'Internal server error';
|
|
100
100
|
}
|
|
101
|
-
response.send({ error: errorMessage });
|
|
101
|
+
response.status(400).send({ error: errorMessage });
|
|
102
102
|
return [3 /*break*/, 4];
|
|
103
103
|
case 4: return [2 /*return*/];
|
|
104
104
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ServiceRouter.js","sourceRoot":"","sources":["../../src/ServiceRouter.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,oDAAoE;AACpE,qDAAkE;AAClE,wCAA+C;AAC/C,4CAA2C;AAE3C,SAAS,cAAc,CAAC,KAAc;IACpC,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,MAAM,IAAI,KAAK,IAAK,KAAsB,CAAC,IAAI,KAAK,cAAc,CAClH,CAAC;AACJ,CAAC;AAED;IAAA;QACU,WAAM,GAAG,IAAI,eAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC;QAE7D,SAAI,GAAG,WAAW,CAAC;QACnB,WAAM,GAAW,MAAM,CAAC;IA4C1B,CAAC;IA1CS,6CAAqB,GAA7B;QACE,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE;YAC5B,IAAI,CAAC,kBAAkB,GAAG,EAAE,CAAC;YAC7B,IAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,6BAAgB,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,4BAA4B,CAAC,CAAC,CAAC;YACxG,KAA0B,UAAY,EAAZ,6BAAY,EAAZ,0BAAY,EAAZ,IAAY,EAAE;gBAAnC,IAAM,WAAW,qBAAA;gBACpB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,2BAAoB,WAAW,CAAC,aAAa,CAAE,EAAE,CAAC,CAAC;gBAC/E,IAAI,CAAC,IAAA,mBAAY,EAAC,WAAW,EAAE,sBAAS,CAAC,EAAE;oBACzC,SAAS;iBACV;gBAED,IAAM,OAAO,GAAG,6BAAgB,CAAC,GAAG,EAAE,CAAC,MAAM,CAAU,WAAW,CAAC,aAAa,CAAC,CAAC;gBAClF,KAAqB,UAAkC,EAAlC,KAAC,WAAyB,CAAC,OAAO,EAAlC,cAAkC,EAAlC,IAAkC,EAAE;oBAApD,IAAM,MAAM,SAAA;oBACf,IAAM,WAAW,GAAG,mBAAY,WAAW,CAAC,aAAa,cAAI,MAAM,CAAC,IAAI,CAAE,CAAC;oBAC3E,IAAI,CAAC,kBAAkB,CAAC,WAAW,CAAC,GAAG,IAAI,iCAAe,CAAC,OAAO,EAAE,WAAwB,EAAE,MAAM,CAAC,CAAC;iBACvG;aACF;SACF;QAED,OAAO,IAAI,CAAC,kBAAkB,CAAC;IACjC,CAAC;IAEK,iCAAS,GAAf,UAAgB,OAAY,EAAE,QAAa;;;;;;wBACnC,eAAe,GAAG,IAAI,CAAC,qBAAqB,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;wBACnE,IAAI,CAAC,eAAe,EAAE;4BACd,KAAK,GAAG,gDAAyC,OAAO,CAAC,IAAI,CAAE,CAAC;4BACtE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;4BACtC,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,OAAA,EAAE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"ServiceRouter.js","sourceRoot":"","sources":["../../src/ServiceRouter.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,oDAAoE;AACpE,qDAAkE;AAClE,wCAA+C;AAC/C,4CAA2C;AAE3C,SAAS,cAAc,CAAC,KAAc;IACpC,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,MAAM,IAAI,KAAK,IAAK,KAAsB,CAAC,IAAI,KAAK,cAAc,CAClH,CAAC;AACJ,CAAC;AAED;IAAA;QACU,WAAM,GAAG,IAAI,eAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,CAAC;QAE7D,SAAI,GAAG,WAAW,CAAC;QACnB,WAAM,GAAW,MAAM,CAAC;IA4C1B,CAAC;IA1CS,6CAAqB,GAA7B;QACE,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE;YAC5B,IAAI,CAAC,kBAAkB,GAAG,EAAE,CAAC;YAC7B,IAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,6BAAgB,CAAC,GAAG,EAAE,CAAC,cAAc,CAAC,4BAA4B,CAAC,CAAC,CAAC;YACxG,KAA0B,UAAY,EAAZ,6BAAY,EAAZ,0BAAY,EAAZ,IAAY,EAAE;gBAAnC,IAAM,WAAW,qBAAA;gBACpB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,2BAAoB,WAAW,CAAC,aAAa,CAAE,EAAE,CAAC,CAAC;gBAC/E,IAAI,CAAC,IAAA,mBAAY,EAAC,WAAW,EAAE,sBAAS,CAAC,EAAE;oBACzC,SAAS;iBACV;gBAED,IAAM,OAAO,GAAG,6BAAgB,CAAC,GAAG,EAAE,CAAC,MAAM,CAAU,WAAW,CAAC,aAAa,CAAC,CAAC;gBAClF,KAAqB,UAAkC,EAAlC,KAAC,WAAyB,CAAC,OAAO,EAAlC,cAAkC,EAAlC,IAAkC,EAAE;oBAApD,IAAM,MAAM,SAAA;oBACf,IAAM,WAAW,GAAG,mBAAY,WAAW,CAAC,aAAa,cAAI,MAAM,CAAC,IAAI,CAAE,CAAC;oBAC3E,IAAI,CAAC,kBAAkB,CAAC,WAAW,CAAC,GAAG,IAAI,iCAAe,CAAC,OAAO,EAAE,WAAwB,EAAE,MAAM,CAAC,CAAC;iBACvG;aACF;SACF;QAED,OAAO,IAAI,CAAC,kBAAkB,CAAC;IACjC,CAAC;IAEK,iCAAS,GAAf,UAAgB,OAAY,EAAE,QAAa;;;;;;wBACnC,eAAe,GAAG,IAAI,CAAC,qBAAqB,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;wBACnE,IAAI,CAAC,eAAe,EAAE;4BACd,KAAK,GAAG,gDAAyC,OAAO,CAAC,IAAI,CAAE,CAAC;4BACtE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;4BACtC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,OAAA,EAAE,CAAC,CAAC;4BACrC,sBAAO;yBACR;;;;wBAG0B,qBAAM,eAAe,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,EAAA;;wBAA9D,gBAAgB,GAAG,SAA2C;wBACpE,QAAQ,CAAC,IAAI,CAAC,EAAE,gBAAgB,kBAAA,EAAE,CAAC,CAAC;;;;wBAEhC,YAAY,GAAG,OAAK,CAAC,OAAO,CAAC;wBACjC,IAAI,CAAC,cAAc,CAAC,OAAK,CAAC,EAAE;4BAC1B,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,SAAA,EAAE,CAAC,CAAC;4BAC7B,YAAY,GAAG,uBAAuB,CAAC;yBACxC;wBACD,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC;;;;;;KAEtD;IACH,oBAAC;AAAD,CAAC,AAhDD,IAgDC;AAhDY,sCAAa"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@proteinjs/service",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "Service api",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -43,5 +43,5 @@
|
|
|
43
43
|
},
|
|
44
44
|
"main": "./dist/generated/index.js",
|
|
45
45
|
"types": "./dist/generated/index.d.ts",
|
|
46
|
-
"gitHead": "
|
|
46
|
+
"gitHead": "9e03cddf33d8d7d2becba67275e19adb67adaaf4"
|
|
47
47
|
}
|
package/src/Service.ts
CHANGED
|
@@ -3,6 +3,21 @@ import { Loadable, SourceRepository } from '@proteinjs/reflection';
|
|
|
3
3
|
import { ServiceClient } from './ServiceClient';
|
|
4
4
|
import { Debouncer } from '@proteinjs/util';
|
|
5
5
|
|
|
6
|
+
type RemoveIndex<T> = {
|
|
7
|
+
[K in keyof T as string extends K ? never : number extends K ? never : symbol extends K ? never : K]: T[K];
|
|
8
|
+
};
|
|
9
|
+
type KeysWithoutIndexSignature<T> = keyof RemoveIndex<T>;
|
|
10
|
+
|
|
11
|
+
// Get keys of T that are not in U
|
|
12
|
+
type Diff<T, U> = T extends U ? never : T;
|
|
13
|
+
|
|
14
|
+
// Get only the keys specific to T, excluding those from Service
|
|
15
|
+
type KeysWithoutService<T extends Service> = Diff<KeysWithoutIndexSignature<T>, KeysWithoutIndexSignature<Service>>;
|
|
16
|
+
|
|
17
|
+
type RetryConfig<T extends Service> = {
|
|
18
|
+
[K in KeysWithoutService<T>]?: number;
|
|
19
|
+
};
|
|
20
|
+
|
|
6
21
|
export interface Service extends Loadable {
|
|
7
22
|
serviceMetadata?: {
|
|
8
23
|
auth?: {
|
|
@@ -35,14 +50,22 @@ export interface Service extends Loadable {
|
|
|
35
50
|
*/
|
|
36
51
|
export const serviceFactory = <T extends Service>(
|
|
37
52
|
serviceInterfaceQualifiedName: string,
|
|
38
|
-
debouncer?: Debouncer
|
|
53
|
+
debouncer?: Debouncer,
|
|
54
|
+
retryConfig?: RetryConfig<T>
|
|
39
55
|
): (() => T) => {
|
|
40
56
|
return () => {
|
|
41
57
|
const service: any = {};
|
|
42
58
|
const serviceInterface = SourceRepository.get().interface(serviceInterfaceQualifiedName);
|
|
43
59
|
for (const method of serviceInterface.methods) {
|
|
44
60
|
const servicePath = `/service/${serviceInterface.qualifiedName}/${method.name}`;
|
|
45
|
-
|
|
61
|
+
|
|
62
|
+
let retryCount = 0;
|
|
63
|
+
if (retryConfig && method.name in retryConfig) {
|
|
64
|
+
const methodName = method.name as KeysWithoutService<T>;
|
|
65
|
+
retryCount = retryConfig[methodName]!;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const serviceClient = new ServiceClient(servicePath, method, debouncer, retryCount);
|
|
46
69
|
service[method.name] = serviceClient.send.bind(serviceClient);
|
|
47
70
|
}
|
|
48
71
|
|
package/src/ServiceClient.ts
CHANGED
|
@@ -9,7 +9,8 @@ export class ServiceClient {
|
|
|
9
9
|
constructor(
|
|
10
10
|
private servicePath: string,
|
|
11
11
|
private serviceMethod: Method,
|
|
12
|
-
private debouncer?: Debouncer
|
|
12
|
+
private debouncer?: Debouncer,
|
|
13
|
+
private retryCount: number = 0
|
|
13
14
|
) {}
|
|
14
15
|
|
|
15
16
|
async send(...args: any[]): Promise<any> {
|
|
@@ -31,10 +32,26 @@ export class ServiceClient {
|
|
|
31
32
|
return deserializedReturn;
|
|
32
33
|
};
|
|
33
34
|
|
|
35
|
+
const executeWithRetry = async (fn: () => Promise<any>) => {
|
|
36
|
+
const maxAttempts = 1 + this.retryCount;
|
|
37
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
38
|
+
try {
|
|
39
|
+
return await fn();
|
|
40
|
+
} catch (error) {
|
|
41
|
+
if (attempt === maxAttempts - 1) {
|
|
42
|
+
throw error;
|
|
43
|
+
}
|
|
44
|
+
await new Promise((resolve) => setTimeout(resolve, 1000)); // 1 second delay before retry
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const executeRequest = this.retryCount > 0 ? executeWithRetry : (fn: () => Promise<any>) => fn();
|
|
50
|
+
|
|
34
51
|
if (this.debouncer) {
|
|
35
|
-
this.debouncer.debounce(sendRequest);
|
|
52
|
+
return this.debouncer.debounce(() => executeRequest(sendRequest));
|
|
36
53
|
} else {
|
|
37
|
-
return sendRequest
|
|
54
|
+
return executeRequest(sendRequest);
|
|
38
55
|
}
|
|
39
56
|
}
|
|
40
57
|
|
package/src/ServiceRouter.ts
CHANGED
|
@@ -43,7 +43,7 @@ export class ServiceRouter implements Route {
|
|
|
43
43
|
if (!serviceExecutor) {
|
|
44
44
|
const error = `Unable to find service matching path: ${request.path}`;
|
|
45
45
|
this.logger.error({ message: error });
|
|
46
|
-
response.send({ error });
|
|
46
|
+
response.status(404).send({ error });
|
|
47
47
|
return;
|
|
48
48
|
}
|
|
49
49
|
|
|
@@ -56,7 +56,7 @@ export class ServiceRouter implements Route {
|
|
|
56
56
|
this.logger.error({ error });
|
|
57
57
|
errorMessage = 'Internal server error';
|
|
58
58
|
}
|
|
59
|
-
response.send({ error: errorMessage });
|
|
59
|
+
response.status(400).send({ error: errorMessage });
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
}
|