grpc-helper
Advanced tools
Comparing version 0.2.3 to 0.3.0
@@ -72,2 +72,12 @@ "use strict"; | ||
} | ||
var _a = this.opts, timeoutInMS = _a.timeoutInMS, metrics = _a.metrics; | ||
this.grpcOpts.interceptors = this.grpcOpts.interceptors || []; | ||
if (metrics) { | ||
log('enable metrics'); | ||
this.grpcOpts.interceptors.push(metrics_1.getMetricsInterceptor()); | ||
} | ||
if (timeoutInMS) { | ||
log('enable global timeout: %d ms', timeoutInMS); | ||
this.grpcOpts.interceptors.push(interceptor_1.getDeadlineInterceptor(timeoutInMS)); | ||
} | ||
}; | ||
@@ -96,12 +106,3 @@ HelperClientCreator.prototype.getBrake = function (pkg, svc, host) { | ||
log('Setup client for %s', host); | ||
var _a = this.opts, pkg = _a.packageName, svc = _a.serviceName, timeoutInMS = _a.timeoutInMS, metrics = _a.metrics, resolveFullResponse = _a.resolveFullResponse; | ||
this.grpcOpts.interceptors = this.grpcOpts.interceptors || []; | ||
if (metrics) { | ||
log('enable metrics for %s', host); | ||
this.grpcOpts.interceptors.push(metrics_1.getMetricsInterceptor(host)); | ||
} | ||
if (timeoutInMS) { | ||
log('enable global timeout: %d ms', timeoutInMS); | ||
this.grpcOpts.interceptors.push(interceptor_1.getDeadlineInterceptor(timeoutInMS)); | ||
} | ||
var _a = this.opts, pkg = _a.packageName, svc = _a.serviceName, resolveFullResponse = _a.resolveFullResponse; | ||
var grpcClient = new this.Service(host, this.grpcCredentials, this.grpcOpts); | ||
@@ -130,2 +131,3 @@ var brake = this.getBrake(pkg, svc, host); | ||
function wrappedMethodCall(data) { | ||
if (data === void 0) { data = {}; } | ||
var args = []; | ||
@@ -132,0 +134,0 @@ for (var _i = 1; _i < arguments.length; _i++) { |
/// <reference types="node" /> | ||
import { Client } from 'grpc'; | ||
import { Options as NodeRetryOpts } from 'async-retry'; | ||
export declare class GRPCHelperError extends Error { | ||
@@ -117,2 +118,12 @@ name: string; | ||
} | ||
interface RetryOpts extends NodeRetryOpts { | ||
/** | ||
* Disabled by default. | ||
*/ | ||
enable: boolean; | ||
/** | ||
* Whether ignore some specified errors | ||
*/ | ||
bailError?: (e: Error, attempt: number) => boolean; | ||
} | ||
export interface GRPCHelperOpts { | ||
@@ -180,2 +191,8 @@ /** | ||
metrics?: boolean; | ||
/** | ||
* Retry options for [async-retry](https://github.com/zeit/async-retry) when error, | ||
* options is actually based on [node-retry](https://github.com/tim-kos/node-retry) | ||
*/ | ||
retryOpts?: RetryOpts; | ||
} | ||
export {}; |
@@ -42,2 +42,3 @@ "use strict"; | ||
var lodash_1 = require("lodash"); | ||
var retry = require("async-retry"); | ||
var common_1 = require("./common"); | ||
@@ -61,2 +62,5 @@ var lb_1 = require("./lb"); | ||
}, opts.healthCheck); | ||
this.opts.retryOpts = Object.assign({ | ||
enable: false, | ||
}, opts.retryOpts); | ||
var clientCreator = new client_1.HelperClientCreator(this.opts); | ||
@@ -78,3 +82,16 @@ var _a = this.parseSDUri(this.opts.sdUri), type = _a.type, addr = _a.addr; | ||
var methodNames = clientCreator.getMethodNames(); | ||
var retryOpts = this.opts.retryOpts; | ||
lodash_1.each(methodNames, function (method) { | ||
if (!retryOpts.enable) { | ||
_this[method] = function () { | ||
var args = []; | ||
for (var _i = 0; _i < arguments.length; _i++) { | ||
args[_i] = arguments[_i]; | ||
} | ||
var client = _this.lb.get(); | ||
return client[method].apply(client, args); | ||
}; | ||
return; | ||
} | ||
// Implement retry logic by async-retry | ||
_this[method] = function () { | ||
@@ -85,4 +102,26 @@ var args = []; | ||
} | ||
var client = _this.lb.get(); | ||
return client[method].apply(client, args); | ||
return retry(function (bail, attempt) { return __awaiter(_this, void 0, void 0, function () { | ||
var client, res, e_1; | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: | ||
client = this.lb.get(); | ||
_a.label = 1; | ||
case 1: | ||
_a.trys.push([1, 3, , 4]); | ||
return [4 /*yield*/, client[method].apply(client, args)]; | ||
case 2: | ||
res = _a.sent(); | ||
return [3 /*break*/, 4]; | ||
case 3: | ||
e_1 = _a.sent(); | ||
if (retryOpts.bailError && retryOpts.bailError(e_1, attempt)) { | ||
bail(e_1); | ||
return [2 /*return*/]; | ||
} | ||
throw e_1; | ||
case 4: return [2 /*return*/, res]; | ||
} | ||
}); | ||
}); }, retryOpts); | ||
}; | ||
@@ -89,0 +128,0 @@ }); |
import * as grpc from 'grpc'; | ||
export declare function getMetricsInterceptor(peer: string): (options: any, nextCall: any) => grpc.InterceptingCall; | ||
export declare function getMetricsInterceptor(): (options: any, nextCall: any) => grpc.InterceptingCall; |
@@ -10,6 +10,7 @@ "use strict"; | ||
}); | ||
function getMetricsInterceptor(peer) { | ||
function getMetricsInterceptor() { | ||
return function metricsInterceptor(options, nextCall) { | ||
var call = nextCall(options); | ||
var endTimer = histogram.startTimer({ | ||
peer: peer, | ||
peer: call.getPeer(), | ||
method: options.method_definition.path, | ||
@@ -28,3 +29,3 @@ }); | ||
}).build(); | ||
return new grpc.InterceptingCall(nextCall(options), requester); | ||
return new grpc.InterceptingCall(call, requester); | ||
}; | ||
@@ -31,0 +32,0 @@ } |
{ | ||
"name": "grpc-helper", | ||
"version": "0.2.3", | ||
"description": "grpc helper", | ||
"version": "0.3.0", | ||
"description": "gRPC helper, an improved gRPC client for grpc-node", | ||
"main": "dist/src/index.js", | ||
@@ -39,8 +39,8 @@ "scripts": { | ||
"compileEnhancements": false, | ||
"extensions": [ | ||
"ts" | ||
], | ||
"require": [ | ||
"ts-node/register" | ||
] | ||
"extensions": [ | ||
"ts" | ||
], | ||
"require": [ | ||
"ts-node/register" | ||
] | ||
}, | ||
@@ -62,2 +62,3 @@ "nyc": { | ||
"@grpc/proto-loader": "^0.3.0", | ||
"async-retry": "^1.2.3", | ||
"bluebird": "^3.5.0", | ||
@@ -71,2 +72,3 @@ "brakes": "^2.6.0", | ||
"devDependencies": { | ||
"@types/async-retry": "^1.2.1", | ||
"@types/bluebird-global": "^3.5.3", | ||
@@ -73,0 +75,0 @@ "@types/debug": "^0.0.30", |
@@ -110,2 +110,31 @@ # gRPC helper | ||
#### Retry | ||
```ts | ||
const helper = new GRPCHelper({ | ||
packageName: 'helloworld', | ||
serviceName: 'Greeter', | ||
protoPath: path.resolve(__dirname, './hello.proto'), | ||
sdUri: 'static://localhost:50051', | ||
retryOpts: { | ||
enable: true, | ||
retries: 5, | ||
bailError(err, attempt) { | ||
// Just for example !!! It will not retry when code is 2 | ||
return err.code === 2; | ||
}, | ||
}, | ||
}); | ||
await helper.waitForReady(); | ||
await helper.SayHello({ | ||
name: 'foo', | ||
}); | ||
``` | ||
#### More | ||
Please take a look at the [test](test/) folder for more examples. | ||
### TODO | ||
@@ -116,3 +145,3 @@ | ||
- [x] Test code | ||
- [ ] Retry on lb level when error | ||
- [x] Retry on lb level when error | ||
- [ ] Auto load proto when only one service available | ||
@@ -119,0 +148,0 @@ - [ ] Consul/etcd/zk service discovery |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
77779
1261
151
8
12
+ Addedasync-retry@^1.2.3
+ Addedasync-retry@1.3.3(transitive)
+ Addedretry@0.13.1(transitive)