Service.js
5.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
/*?
// --- Scope ------------------
// T : Reflect.Service instance
*/
/**
* Constructs a new runtime Service.
* @name ProtoBuf.Builder.Service
* @param {function(string, ProtoBuf.Builder.Message, function(Error, ProtoBuf.Builder.Message=))=} rpcImpl RPC implementation receiving the method name and the message
* @class Barebone of all runtime services.
* @constructor
* @throws {Error} If the service cannot be created
*/
var Service = function(rpcImpl) {
ProtoBuf.Builder.Service.call(this);
/**
* Service implementation.
* @name ProtoBuf.Builder.Service#rpcImpl
* @type {!function(string, ProtoBuf.Builder.Message, function(Error, ProtoBuf.Builder.Message=))}
* @expose
*/
this.rpcImpl = rpcImpl || function(name, msg, callback) {
// This is what a user has to implement: A function receiving the method name, the actual message to
// send (type checked) and the callback that's either provided with the error as its first
// argument or null and the actual response message.
setTimeout(callback.bind(this, Error("Not implemented, see: https://github.com/dcodeIO/ProtoBuf.js/wiki/Services")), 0); // Must be async!
};
};
/**
* @alias ProtoBuf.Builder.Service.prototype
* @inner
*/
var ServicePrototype = Service.prototype = Object.create(ProtoBuf.Builder.Service.prototype);
/**
* Asynchronously performs an RPC call using the given RPC implementation.
* @name ProtoBuf.Builder.Service.[Method]
* @function
* @param {!function(string, ProtoBuf.Builder.Message, function(Error, ProtoBuf.Builder.Message=))} rpcImpl RPC implementation
* @param {ProtoBuf.Builder.Message} req Request
* @param {function(Error, (ProtoBuf.Builder.Message|ByteBuffer|Buffer|string)=)} callback Callback receiving
* the error if any and the response either as a pre-parsed message or as its raw bytes
* @abstract
*/
/**
* Asynchronously performs an RPC call using the instance's RPC implementation.
* @name ProtoBuf.Builder.Service#[Method]
* @function
* @param {ProtoBuf.Builder.Message} req Request
* @param {function(Error, (ProtoBuf.Builder.Message|ByteBuffer|Buffer|string)=)} callback Callback receiving
* the error if any and the response either as a pre-parsed message or as its raw bytes
* @abstract
*/
var rpc = T.getChildren(ProtoBuf.Reflect.Service.RPCMethod);
for (var i=0; i<rpc.length; i++) {
(function(method) {
// service#Method(message, callback)
ServicePrototype[method.name] = function(req, callback) {
try {
try {
// If given as a buffer, decode the request. Will throw a TypeError if not a valid buffer.
req = method.resolvedRequestType.clazz.decode(ByteBuffer.wrap(req));
} catch (err) {
if (!(err instanceof TypeError))
throw err;
}
if (req === null || typeof req !== 'object')
throw Error("Illegal arguments");
if (!(req instanceof method.resolvedRequestType.clazz))
req = new method.resolvedRequestType.clazz(req);
this.rpcImpl(method.fqn(), req, function(err, res) { // Assumes that this is properly async
if (err) {
callback(err);
return;
}
// Coalesce to empty string when service response has empty content
if (res === null)
res = ''
try { res = method.resolvedResponseType.clazz.decode(res); } catch (notABuffer) {}
if (!res || !(res instanceof method.resolvedResponseType.clazz)) {
callback(Error("Illegal response type received in service method "+ T.name+"#"+method.name));
return;
}
callback(null, res);
});
} catch (err) {
setTimeout(callback.bind(this, err), 0);
}
};
// Service.Method(rpcImpl, message, callback)
Service[method.name] = function(rpcImpl, req, callback) {
new Service(rpcImpl)[method.name](req, callback);
};
if (Object.defineProperty)
Object.defineProperty(Service[method.name], "$options", { "value": method.buildOpt() }),
Object.defineProperty(ServicePrototype[method.name], "$options", { "value": Service[method.name]["$options"] });
})(rpc[i]);
}
// Properties
/**
* Service options.
* @name ProtoBuf.Builder.Service.$options
* @type {Object.<string,*>}
* @expose
*/
var $optionsS; // cc needs this
/**
* Service options.
* @name ProtoBuf.Builder.Service#$options
* @type {Object.<string,*>}
* @expose
*/
var $options;
/**
* Reflection type.
* @name ProtoBuf.Builder.Service.$type
* @type {!ProtoBuf.Reflect.Service}
* @expose
*/
var $typeS;
/**
* Reflection type.
* @name ProtoBuf.Builder.Service#$type
* @type {!ProtoBuf.Reflect.Service}
* @expose
*/
var $type;
if (Object.defineProperty)
Object.defineProperty(Service, "$options", { "value": T.buildOpt() }),
Object.defineProperty(ServicePrototype, "$options", { "value": Service["$options"] }),
Object.defineProperty(Service, "$type", { "value": T }),
Object.defineProperty(ServicePrototype, "$type", { "value": T });