Skip to content

Commit

Permalink
Merge branch 'sequential-service-calls'
Browse files Browse the repository at this point in the history
  • Loading branch information
SomeoneWeird committed Apr 10, 2015
2 parents 1903bb5 + 38c655f commit 134e066
Show file tree
Hide file tree
Showing 8 changed files with 252 additions and 69 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
Changelog 4.0.0:

* Change Client.prototype.chain to execute sequential service calls on the remote host.

Changelog 3.3.0:

* Add Client.prototype.chain for method chaining

Changelog 3.2.0:

* Add Client.prototype.prepare

Changelog 3.1.0:

* Return method along with error if unknown-method
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ horizontally.

*Note:* If you see **HT2** anywhere, this references the new rewrite, and is applicable to any version >=2.x.x

Current Version: 3.1.0
Current Version: 4.0.0

See [Changelog here](CHANGELOG.md)

Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "hudson-taylor",
"version": "3.3.0",
"version": "4.0.0",
"description": "Library for building services.",
"main": "index.js",
"directories": {
Expand Down Expand Up @@ -44,7 +44,7 @@
"async": "^0.9.0",
"body-parser": "^1.8.2",
"express": "^4.9.0",
"ht-schema": "^0.2.0",
"ht-schema": "^1.0.4",
"request": "^2.42.0",
"uid2": "0.0.3"
},
Expand Down
61 changes: 42 additions & 19 deletions src/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ const util = require("util");
const events = require("events");
const async = require("async");

const utils = require("./utils");

let Client = function Client(services) {

this.services = {};
Expand Down Expand Up @@ -164,15 +166,15 @@ Client.prototype.prepare = function(service, method, data) {
}
}

Client.prototype.chain = function(...args) {
Client.prototype.chain = function(service, method, data) {

var client = this;
let client = this;

if(!client.isChain) {
// return new instance of the client
// so we can set values on it
client = new Client();
for(var k in this) {
for(let k in this) {
if(client.hasOwnProperty(k)) {
client[k] = this[k];
}
Expand All @@ -181,35 +183,56 @@ Client.prototype.chain = function(...args) {
client.chainedMethods = [];
}

client.chainedMethods.push(args)
client.chainedMethods.push({
service,
method,
data
});

return client;

}

Client.prototype.end = function(callback) {

async.reduce(this.chainedMethods, undefined, (lastResult, stored, done) => {
let tmp = this.chainedMethods.reduce(function(previous, method) {

let service = stored[0];
let method = stored[1];
let data = stored[2] !== undefined ? stored[2] : lastResult;
let last = previous[previous.length - 1];

this.call(service, method, data, function(err, data) {
if(!last || last.service != method.service) {
previous.push({
service: method.service,
calls: []
});
}

if(err) {
return done({
error: err,
service: service,
method: method
});
}
let call = {
method: method.method
}

return done(null, data);
if(method.data) {
call.data = method.data;
}

});
previous[previous.length-1].calls.push(call);

return previous;

}, []);

let methods = tmp.map(function(serviceCall) {

let call = {
service: serviceCall.service,
method: "$htMultiCall",
data: serviceCall.calls
}

return call;

});

}, callback);
utils.getLastResult.bind(this)(methods, callback);

}

Expand Down
11 changes: 11 additions & 0 deletions src/service.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
const async = require("async");
const s = require("ht-schema");

const utils = require("./utils");

let Service = function Service(Transports, config) {
let self = this;

Expand Down Expand Up @@ -97,6 +99,15 @@ let Service = function Service(Transports, config) {

};

this.on("$htMultiCall", s.Array({ opt: false }, [
s.Object({
method: s.String(),
data: s.Any({ opt: true })
})
]), function(data, callback) {
utils.getLastResult.bind(self)(data, callback, true);
});

Transports.forEach(function(transport) {
self.addTransport(transport);
});
Expand Down
56 changes: 55 additions & 1 deletion src/utils.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@

"use strict";

const async = require("async");

var expressProxy = function(remote, serviceName, signal) {

/* expressProxy returns an express route handler for that combines:
Expand Down Expand Up @@ -61,8 +63,60 @@ var formatError = function formatError(err) {
return { error: err };
};

var getLastResult = function getLastResult(methods, callback, isService) {

async.reduce(methods, undefined, (lastResult, stored, done) => {

let {
service,
method,
data = lastResult
} = stored;

let call = [
service,
method,
data,
function(err, result) {
if(err) {
let r = {
error: err,
method
}
if(!isService) {
r.service = service;
}
return done(r);
}

if(!isService) {

var index = methods.indexOf(stored);
var next = methods[index + 1];

if(next && next.data && !next.data[0].data) {
methods[index + 1].data[0].data = result;
}

}

return done(null, result);

}
];

if(isService) {
call.shift();
}

this.call(...call);

}, callback);
}

export {
expressProxy,
merge,
formatError
formatError,
getLastResult
};
88 changes: 43 additions & 45 deletions test-src/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -655,16 +655,19 @@ describe("Client", function() {
s1: mockTransport({
call(method, data, callback) {
switch(method) {
case "method1": {
assert.deepEqual(data, _data)
return callback(null, _data2);
}
case "method2": {
assert.deepEqual(data, _data2);
return callback(null, _data3);
}
case "method3": {
assert.deepEqual(data, _data3);
case "$htMultiCall": {
assert.deepEqual(data, [
{
method: "method1",
data: _data
},
{
method: "method2"
},
{
method: "method3"
}
]);
return callback(null, _data4);
}
}
Expand All @@ -691,13 +694,17 @@ describe("Client", function() {
s1: mockTransport({
call(method, data, callback) {
switch(method) {
case "method1": {
assert.deepEqual(data, _data)
return callback(null, _data2);
}
case "method2": {
// method2 should have overriden data
assert.deepEqual(data, _data4);
case "$htMultiCall": {
assert.deepEqual(data, [
{
method: "method1",
data: _data
},
{
method: "method2",
data: _data4
}
]);
return callback(null, _data3);
}
}
Expand All @@ -717,43 +724,34 @@ describe("Client", function() {

});

it("should be stop chain if call returns error", function(done) {
it("should successfully be able to call methods on multiple services", function(done) {

let str = "hello world";
let strRev = "dlrow olleh";

let services = {
s1: mockTransport({
call(method, data, callback) {
switch(method) {
case "method1": {
assert.deepEqual(data, _data)
return callback(null, _data2);
}
case "method2": {
assert.deepEqual(data, _data2);
return callback(_err);
}
case "method3": {
assert.deepEqual(data, _data3);
return callback(null, _data4);
}
}
assert.equal(data[0].data, str);
return callback(null, data[0].data);
}
})(),
s2: mockTransport({
call(method, data, callback) {
// reverse
assert.equal(data[0].data, str);
return callback(null, data[0].data.split("").reverse().join(""));
}
})()
};

let client = new Client(services);

client.chain("s1", "method1", _data)
.chain("s1", "method2")
.chain("s1", "method3")
.end(function(err, result) {
assert.deepEqual(err, {
service: "s1",
method: "method2",
error: _err
});
assert.equal(result, undefined);
done();
});
client.chain("s1", "echo", str).chain("s2", "reverse").end(function(err, response) {
assert.ifError(err);
assert.deepEqual(response, strRev);
done();
});

});

Expand All @@ -765,7 +763,7 @@ describe("Client", function() {
.end(function(err, result) {
assert.deepEqual(err, {
service: "s1",
method: "method",
method: "$htMultiCall",
error: {
error: "unknown-service"
}
Expand Down
Loading

0 comments on commit 134e066

Please sign in to comment.