add rpc call batching

This commit is contained in:
freewil 2012-10-18 08:23:00 -04:00
parent 2127609f4c
commit c989985b2c
3 changed files with 93 additions and 27 deletions

View File

@ -64,3 +64,19 @@ client.cmd('getbalance', '*', 6, function(err, balance){
console.log('Balance:', balance);
});
```
### Batch multiple RPC calls into single HTTP request
```js
var batch = [];
for (var i = 0; i < 10; ++i) {
batch.push({
method: 'getnewaddress',
params: ['myaccount']
});
}
client.cmd(batch, function(err, address) {
if (err) return console.log(err);
console.log('Address:', address);
});
```

View File

@ -14,13 +14,31 @@ var Client = function(port, host, user, password) {
this.password = password;
this.call = function(method, params, callback, errback, path) {
var time = Date.now();
var requestJSON;
if (Array.isArray(method)) {
// multiple rpc batch call
requestJSON = [];
method.forEach(function(batchCall, i) {
requestJSON.push({
id: time + '-' + i,
method: batchCall.method,
params: batchCall.params
});
});
} else {
// single rpc call
requestJSON = {
id: time,
method: method,
params: params
};
}
// First we encode the request into JSON
var requestJSON = JSON.stringify({
'id': '' + (new Date()).getTime(),
'method': method,
'params': params
});
var requestJSON = JSON.stringify(requestJSON);
// prepare request options
var requestOptions = {
@ -71,32 +89,39 @@ var Client = function(port, host, user, password) {
return;
}
if (decoded.hasOwnProperty('error') && decoded.error != null) {
if (errback) {
err = new Error(decoded.error.message || '');
if (decoded.error.code) {
err.code = decoded.error.code;
}
errback(err);
}
} else if (decoded.hasOwnProperty('result')) {
if (callback) {
callback(decoded.result);
}
} else {
if (errback) {
err = new Error(decoded.error.message || '');
if (decoded.error.code) {
err.code = decoded.error.code;
}
errback(err);
}
if (!Array.isArray(decoded)) {
decoded = [decoded];
}
// iterate over each response, normally there will be just one
// unless a batch rpc call response is being processed
decoded.forEach(function(decodedResponse, i) {
if (decodedResponse.hasOwnProperty('error') && decodedResponse.error != null) {
if (errback) {
err = new Error(decodedResponse.error.message || '');
if (decodedResponse.error.code) {
err.code = decodedResponse.error.code;
}
errback(err);
}
} else if (decodedResponse.hasOwnProperty('result')) {
if (callback) {
callback(decodedResponse.result);
}
} else {
if (errback) {
err = new Error(decodedResponse.error.message || '');
if (decodedResponse.error.code) {
err.code = decodedResponse.error.code;
}
errback(err);
}
}
});
});
});
request.write(requestJSON);
request.end();
request.end(requestJSON);
};
}

View File

@ -25,6 +25,8 @@ function notEmpty(data) {
assert.ok(data);
}
var batchCallbackCount = 0;
vows.describe('api').addBatch({
'': {
topic: makeClient,
@ -134,6 +136,29 @@ vows.describe('api').addBatch({
assert.equal(expectedValue, undefined);
},
},
'running batch of rpc calls': {
topic: function(client) {
// create batch of calls to get 10 new addresses
var batch = [];
for (var i = 0; i < 10; ++i) {
batch.push({
method: 'getnewaddress',
params: [test.account]
});
}
var self = this;
client.cmd(batch, function(err, address) {
assert.isTrue(++batchCallbackCount <= 10);
if (batchCallbackCount === 10) {
self.callback(err, address);
}
});
},
'should receive new address': function(err, address){
assert.equal(err, null);
assert.ok(address);
}
}
},
'invalid credentials': {
topic: function() {