An improved gRPC client.
This forked repository aims to provide a @grpc/grpc-js
compatable version of grpc-caller. The original repository relies on grpc
which is no longer supported.
- Promisifies request / response (Unary) calls if no callback is supplied
- Promisifies request stream / response calls if no callback is supplied
- Automatically converts plain javascript object to metadata in calls.
- Adds optional retry functionality to request / response (Unary) calls.
- Exposes expanded
Request
API for collecting metadata and status.
$ npm install @eeston/grpc-caller
Works as standard gRPC client:
const caller = require("grpc-caller");
const PROTO_PATH = path.resolve(__dirname, "./protos/helloworld.proto");
const client = caller("0.0.0.0:50051", PROTO_PATH, "Greeter");
client.sayHello({ name: "Bob" }, (err, res) => {
console.log(res);
});
For unary calls, also promisified if callback is not provided:
client.sayHello({ name: "Bob" }).then((res) => console.log(res));
Which means means you can use is with async / await
const res = await client.sayHello({ name: "Bob" });
console.log(res);
For Unary calls we expose retry
option identical to async.retry.
const res = await client.sayHello({ name: 'Bob' }, {}, { retry: 3 })
console.log(res)
Lets say we have a remote call writeStuff
that accepts a stream of messages
and returns some result based on processing of the stream input.
Works as standard gRPC client:
const call = client.writeStuff((err, res) => {
if (err) console.error(err);
console.log(res);
});
// ... write stuff to call
If no callback is provided we promisify the call such that it returns an object
with two properties call
and res
such that:
call
- the standard stream to write to as returned normally by grpcres
- a promise that's resolved / rejected when the call is finished, in place of the callback.
Using destructuring we can do something like:
const { call, res } = client.writeStuff();
res.then((res) => console.log(res)).catch((err) => console.error(err));
// ... write stuff to call
This means we can abstract the whole operation into a nicer promise returning
async function to use with async / await
async function writeStuff() {
const { call, res } = client.writeStuff();
// ... write stuff to call
return res;
}
const res = await writeStuff();
console.log(res);
All standard gRPC client calls accept Metadata
as first or second parameter (depending on the call type). However one has to
manually create the Metadata object. This module uses
grpc-create-metadata
to automatically create Metadata if plain Javascript object is passed in.
// the 2nd parameter will automatically be converted to gRPC Metadata and
// included in the request
const res = await client.sayHello(
{ name: "Bob" },
{ requestid: "my-request-id-123" }
);
console.log(res);
We can still pass an actual Metadata
object and it will be used as is:
const meta = new grpc.Metadata();
meta.add("requestid", "my-request-id-123");
const res = await client.sayHello({ name: "Bob" }, meta);
console.log(res);
In addition to simple API above, the library provides a more detailed "Request"
API that can
be used to control the call details. The API can only be used for Unary and
request streaming calls.
const req = new client.Request("sayHello", { name: "Bob" }) // call method name and argument
.withMetadata({ requestId: "bar-123" }) // call request metadata
.withResponseMetadata(true) // we want to collect response metadata
.withResponseStatus(true) // we want to collect the response status
.withRetry(5); // retry options
const res = await req.exec();
// res is an instance of our `Response`
// we can also call exec() using a callback
console.log(res.response); // the actual response data { message: 'Hello Bob!' }
console.log(res.metadata); // the response metadata
console.log(res.status); // the response status
console.log(res.call); // the internal gRPC call
In case of request streaming calls if exec()
is called with a callback the gRPC call
stream is returned.
If no callback is provided an object is returned with call
property being the call stream and res
property being a Promise fulfilled when the call is completed. There is no retry
option for
request streaming calls.
const req = new client.Request("writeStuff") // the call method name
.withMetadata({ requestId: "bar-123" }) // the call request metadata
.withResponseMetadata(true) // we want to collect response metadata
.withResponseStatus(true); // we want to collect the response status
const { call, res: resPromise } = req.exec();
// ... write data to call
const res = await resPromise; // res is our `Response`
console.log(res.response); // the actual response data
console.log(res.metadata); // the response metadata
console.log(res.status); // the response status
console.log(res.call); // the internal gRPC call
A Request class that encapsulates the request of a call.
Kind: global class
- Request
- new Request(methodName, param)
- .withGrpcOptions(opts) ⇒
Object
- .withMetadata(opts) ⇒
Object
- .withRetry(retry) ⇒
Object
- .withResponseMetadata(value) ⇒
Object
- .withResponseStatus(value) ⇒
Object
- .exec(fn) ⇒
Promise
|Object
Creates a Request instance.
Param | Type | Description |
---|---|---|
methodName | String |
the method name. |
param | * |
the call argument in case of UNARY calls. |
Create a request with call options.
Kind: instance method of Request
Returns: Object
- the request instance.
Param | Type | Description |
---|---|---|
opts | Object |
The gRPC call options. |
Create a request with call metadata.
Kind: instance method of Request
Returns: Object
- the request instance.
Param | Type | Description |
---|---|---|
opts | Object |
The gRPC call metadata. Can either be a plain object or an instance of grpc.Metadata . |
Create a request with retry options.
Kind: instance method of Request
Returns: Object
- the request instance.
Param | Type | Description |
---|---|---|
retry | Number | Object |
The retry options. Identical to async.retry . |
Create a request indicating whether we want to collect the response metadata.
Kind: instance method of Request
Returns: Object
- the request instance.
Param | Type | Description |
---|---|---|
value | Boolean |
true to collect the response metadata. Default false . |
Create a request indicating whether we want to collect the response status metadata.
Kind: instance method of Request
Returns: Object
- the request instance.
Param | Type | Description |
---|---|---|
value | Boolean |
true to collect the response status metadata. Default false . |
Execute the request.
Kind: instance method of Request
Returns: Promise
| Object
- If no callback is provided in case of UNARY
call a Promise is returned.
If no callback is provided in case of REQUEST_STREAMING
call an object is
returned with call
property being the call stream and res
property being a Promise fulfilled when the call is completed.
Param | Type | Description |
---|---|---|
fn | function |
Optional callback |
A Response class that encapsulates the response of a call using the Request
API.
Kind: global class
The response's gRPC call.
Kind: instance property of Response
The actual response data from the call.
Kind: instance property of Response
The response metadata.
Kind: instance property of Response
The response status metadata.
Kind: instance property of Response
Create client isntance.
Kind: global function
Param | Type | Description |
---|---|---|
host | String |
The host to connect to |
proto | String | Object |
Path to the protocol buffer definition file or Object specifying file to load and load options for proto loader. |
name | String |
In case of proto path the name of the service as defined in the proto definition. |
credentials | Object |
The credentials to use to connect. Defaults to grpc.credentials.createInsecure() |
options | Object |
Options to be passed to the gRPC client constructor |
options.retry | Object |
In addition to gRPC client constructor options, we accept a retry option. The retry option is identical to async.retry and is passed as is to it. This is used only for UNARY calls to add automatic retry capability. |
defaults | Object |
Metadata and Options that will be passed to every Request |
Example (Create client dynamically)
const PROTO_PATH = path.resolve(__dirname, "./protos/helloworld.proto");
const client = caller("localhost:50051", PROTO_PATH, "Greeter");
Example (With options)
const file = path.join(__dirname, "helloworld.proto");
const load = {
// ... proto-loader load options
};
const client = caller("localhost:50051", { file, load }, "Greeter");
Example (Create a static client)
const services = require("./static/helloworld_grpc_pb");
const client = caller("localhost:50051", services.GreeterClient);
Example (Pass Options, Default Metadata and Interceptor options)
const metadata = { node_id: process.env.CLUSTER_NODE_ID };
const credentials = grpc.credentials.createInsecure()
const options = {
interceptors = [ bestInterceptorEver ]
}
const client = caller('localhost:50051', PROTO_PATH, 'Greeter', credentials, options, {
metadata: { foo: 'bar' }
})
// Now every call with that client will result
// in invoking the interceptor and sending the default metadata
Utility helper function to create Metadata
object from plain Javascript object.
See grpc-create-metadata
module.
Kind: static property of caller
Utility function that can be used to wrap an already constructed client instance.
Kind: static property of caller
Apache-2.0