Permalink
Browse files

Initial take on runtime services, see #507

  • Loading branch information...
dcodeIO committed Nov 30, 2016
1 parent 6a06e95 commit d3ae961765e193ec11227d96d699463de346423f

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.

Large diffs are not rendered by default.

Oops, something went wrong.

Large diffs are not rendered by default.

Oops, something went wrong.
BIN +130 Bytes (100%) dist/protobuf.min.js.gz
Binary file not shown.

Large diffs are not rendered by default.

Oops, something went wrong.
@@ -138,3 +138,52 @@ ServicePrototype.remove = function remove(object) {
}
return NamespacePrototype.remove.call(this, object);
};
/**
* RPC implementation passed to {@link Service#create} performing a service request on network level, i.e. by utilizing http requests or websockets.
* @typedef RPCImpl
* @function
* @param {Method} method Reflected method being called
* @param {Uint8Array} requestData Request data
* @param {function(?Error, Uint8Array=)} callback Node-style callback called with the error, if any, and the response data
* @returns {undefined}
*/
/**
* Creates a runtime service using the specified rpc implementation.
* @param {RPCImpl} rpc RPC implementation
* @param {boolean} [requestDelimited=false] Whether request data is length delimited
* @param {boolean} [responseDelimited=false] Whether response data is length delimited
* @returns {Object} Runtime service
*/
ServicePrototype.create = function create(rpc, requestDelimited, responseDelimited) {
var rpcService = {};
this.getMethodsArray().forEach(function(method) {
rpcService[method.resolve().name] = function(request, callback) {
var requestData;
try {
requestData = (requestDelimited && method.resolvedRequestType.encodeDelimited(request) || method.resolvedRequestType.encode(request)).finish();
} catch (err) {
(typeof setImmediate === 'function' && setImmediate || setTimeout)(function() { callback(err); });
return;
}
// Calls the custom RPC implementation with the reflected method and binary request data
// and expects the rpc implementation to call its callback with the binary response data.
rpc(method, requestData, function(err, responseData) {
if (err) {
callback(err);
return;
}
var response;
try {
response = responseDelimited && method.resolvedResponseType.decodeDelimited(responseData) || method.resolvedResponseType.decode(responseData);
} catch (err2) {
callback(err2);
return;
}
callback(null, response);
});
};
});
return rpcService;
};
@@ -0,0 +1,13 @@
syntax = "proto3";
service MyService {
rpc MyMethod (MyRequest) returns (MyResponse);
}
message MyRequest {
string path = 1;
}
message MyResponse {
int32 status = 2;
}
@@ -0,0 +1,57 @@
var tape = require("tape");
var protobuf = require("..");
tape.test("RPC", function(test) {
protobuf.load("tests/data/rpc.proto", function(err, root) {
if (err)
return test.fail(err.message);
var MyService = root.lookup("MyService"),
MyMethod = MyService.get("MyMethod").resolve(),
MyRequest = MyMethod.resolvedRequestType,
MyResponse = MyMethod.resolvedResponseType;
function rpc(method, requestData, callback) {
test.test("should call the rpc impl with", function(test) {
test.equal(method, MyMethod, "the reflected method");
test.ok(requestData.length, "a buffer");
test.ok(typeof callback === 'function', "a callback function");
test.end();
});
test.test("should call with a buffer that contains", function(test) {
test.equal(requestData[0], 3, "ldelim 3");
test.equal(requestData[1], 10, "id 1, wireType 2");
test.equal(requestData[2], 1, "length 1");
test.equal(requestData[3], 0x2f, "the original string");
test.end();
});
setTimeout(function() {
callback(null, MyResponse.encode({
status: 200
}).finish());
});
}
var MyService = root.lookup("MyService");
var service = MyService.create(rpc, true, false);
test.deepEqual(Object.keys(service), [ "MyMethod" ], "should create a service with exactly one method");
service.MyMethod(MyRequest.create({
path: "/"
}), function(err, response) {
if (err)
return test.fail(err.message);
test.ok(response instanceof MyResponse.ctor, "should return an instance of MyResponse");
test.deepEqual(response, {
status: 200
}, "should return status 200");
test.end();
});
});
});
@@ -3,7 +3,7 @@
/*
* protobuf.js v6.0.1 TypeScript definitions
* Generated Wed, 30 Nov 2016 13:45:03 UTC
* Generated Wed, 30 Nov 2016 22:05:17 UTC
*/
declare module protobuf {
@@ -1259,8 +1259,28 @@ declare module protobuf {
*/
static fromJSON(name: string, json: Object): Service;
/**
* Creates a runtime service using the specified rpc implementation.
* @param {RPCImpl} rpc RPC implementation
* @param {boolean} [requestDelimited=false] Whether request data is length delimited
* @param {boolean} [responseDelimited=false] Whether response data is length delimited
* @returns {Object} Runtime service
*/
create(rpc: RPCImpl, requestDelimited?: boolean, responseDelimited?: boolean): Object;
}
/**
* RPC implementation passed to {@link Service#create} performing a service request on network level, i.e. by utilizing http requests or websockets.
* @typedef RPCImpl
* @function
* @param {Method} method Reflected method being called
* @param {Uint8Array} requestData Request data
* @param {function(?Error, Uint8Array=)} callback Node-style callback called with the error, if any, and the response data
* @returns {undefined}
*/
function RPCImpl(method: Method, requestData: Uint8Array, callback: (() => any)): undefined;
/**
* Handle object returned from {@link tokenize}.
* @typedef {Object} TokenizerHandle

0 comments on commit d3ae961

Please sign in to comment.