Jig
Jig lets you use jsonnet to implement gRPC methods, e.g.
// Greeter.Hello
function(input) {
response: {
greeting: '💃 : Hello ' + input.request.firstName,
},
}
The jsonnet method definitions can be updated in real time without restarting
jig.
Jig uses protobuf FileDescriptorSets
, generated by protoc
into .pb
files,
as a description of valid gRPC method names, request and response types. Jig
does not need any further pre-generated or pre-compiled code.
Usage
Generate a FileDescriptorSet for the services to stub with:
protoc --descriptor_set_out service.pb --include_imports service.proto
Put jsonnet method definitions together in a directory, each file named
<pkg>.<service>.<method>.jsonnet
. The jsonnet file is (re-)evaluated when the
gRPC server receives a call to that method.
Request protobuf messages are marshaled to JSON and passed to the jsonnet method
definition function as the input
parameter. If the method is a unary,
server-streaming or bidirectional streaming method, the request message is
placed in the request
field of input
:
{
request: { ...json-encoded gRPC request protobuf... }
}
If the method is a client-streaming method, the stream of request messages is
placed in the stream
field of input
as an array:
{
stream: [ {request1}, {request2}, ...]
}
For bidirectional streaming methods, the jsonnet method definition is evaluated
once for each message on the request stream (with a single message in the
request
field). Once EOF
has been received on the request stream, the
jsonnet method definition is evaluated one more time with the request
field
set to null
.
Response protobuf messages are unmarshaled from the jsonnet evaluation of the
method definition. The result must evaluate as an object with fields describing
the response to send back to the gRPC client.
If the method is a unary or client-streaming method, the result must have a
response
field that contains the response message encoded as JSON:
function(input) {
response: { ...json-encoded gRPC response protobuf... }
}
If the method is a server- or bidirectional streaming method, the result must
have a stream
field that contains an array of response messages encoded as
JSON:
function(input) {
stream: [ {response1}, {response2}, ... ]
}
The response can reference fields of the input using regular jsonnet references.
See the testdata samples.
The request
and response
fields are encoded from/to protobuf messages
according to the protojson encoding rules.
To serve these jsonnet methods, run:
jig serve --proto-set=service.pb --method-dir=dir
Playing
Build and start jig on the test data:
. ./bin/activate-hermit
make install pb
jig serve --proto-set testdata/all.pb --method-dir testdata
in a second terminal call it with
client world
To see streaming, call it with
client --stream=server world
client --stream=client you me world
client --stream=bidi you me world
Experiment with the jsonnet method files in the testdata
directory.
Alternatively there is a traditional generated gRPC server that the same client
can interact with. Start with:
server
Development
. ./bin/activate-hermit
make ci
Run make help
for help on other make targets.