From a777637089b5c6bca89f576ca9d3cbb4aa3e6ef1 Mon Sep 17 00:00:00 2001 From: Andrew Newdigate Date: Thu, 17 Dec 2015 18:20:55 +0000 Subject: [PATCH 1/9] Use Halley for realtime communications instead of Faye --- .gitignore | 1 + lib/faye.js | 43 ++++++++++++++++++++++++++++++++++--------- package.json | 9 +++++---- 3 files changed, 40 insertions(+), 13 deletions(-) diff --git a/.gitignore b/.gitignore index ff4601c..194c116 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ *.swo node_modules npm-debug.log +.env diff --git a/lib/faye.js b/lib/faye.js index 82df014..314611d 100644 --- a/lib/faye.js +++ b/lib/faye.js @@ -1,7 +1,9 @@ /* jshint node:true, unused:true */ +'use strict'; -var Faye = require('gitter-faye'); +var Halley = require('halley'); var EventEmitter = require('eventemitter3'); +var Promise = require('bluebird'); // Authentication extension for Faye var ClientAuthExt = function(opts) { @@ -41,7 +43,7 @@ var FayeClient = function(token, opts) { this.subscriptions = {}; - this.client = new Faye.Client(host, {timeout: 60, retry: 5, interval: 1}); + this.client = new Halley.Client(host); this.client.addExtension(new ClientAuthExt({token: token, clientType: opts.clientType})); this.client.addExtension(new SnapshotExt({subscriptions: this.subscriptions})); }; @@ -50,14 +52,14 @@ FayeClient.prototype.subscribeTo = function(resource, eventName) { if (this.subscriptions[resource]) return this.subscriptions[resource].emitter; var emitter = new EventEmitter(); - var subscription = this.client.subscribe(resource, function(msg) { + var subscribe = this.client.subscribe(resource, function(msg) { emitter.emit(eventName, msg); - }); + }); // TODO: catch this.subscriptions[resource] = { eventName: eventName, emitter: emitter, - subscription: subscription + subscribe: subscribe }; return emitter; @@ -66,10 +68,33 @@ FayeClient.prototype.subscribeTo = function(resource, eventName) { FayeClient.prototype.disconnect = function() { var self = this; - Object.keys(this.subscriptions).forEach(function(sub) { - self.subscriptions[sub].subscription.cancel(); - self.subscriptions[sub].emitter.removeAllListeners(); - }); + var promises = Object.keys(this.subscriptions) + .map(function(sub) { + var subscriptionsInfo = self.subscriptions[sub]; + subscriptionsInfo.emitter.removeAllListeners(); + + var promise = subscriptionsInfo.subscribe; + + if (promise.isCancellable()) { + promise.cancel(); + return null; + } else { + return promise.then(function(subscription) { + return subscription.unsubscribe(); // TODO: catch + }); + } + }); + + return Promise.all(promises) + .bind(this) + .catch(function() { + // Ignore unsubscribe errors, we plan to disconnect anyway + }) + .then(function() { + return this.client.disconnect(); + }); + + }; module.exports = FayeClient; diff --git a/package.json b/package.json index 75bb352..d51a1a6 100644 --- a/package.json +++ b/package.json @@ -20,15 +20,16 @@ }, "homepage": "https://github.com/gitterHQ/node-gitter", "dependencies": { - "debug": "^0.8.1", + "bluebird": "^3.1.1", + "debug": "^2.2.0", "eventemitter3": "^0.1.6", - "faye": "~1.0.1", "gitter-faye": "^1.1.0-e", + "halley": "^0.3.2", "q": "~1.0.1", "qs": "~1.2.1" }, "devDependencies": { - "mocha": "~1.18.2", - "retire": "latest" + "mocha": "^2.3.4", + "retire": "^1.1.2" } } From d0092a51f496e12934025cfa2c63ee6d003e2240 Mon Sep 17 00:00:00 2001 From: Andrew Newdigate Date: Fri, 18 Dec 2015 11:59:41 +0000 Subject: [PATCH 2/9] Switching from `Q` to `bluebird` since Halley uses Bluebird already --- lib/client.js | 83 +++++++++++++++++++++++----------------------- lib/faye.js | 11 +----- lib/gitter.js | 1 + lib/rooms.js | 39 ++++++++++++---------- package.json | 2 +- test/rooms-test.js | 10 +++--- test/users-test.js | 2 +- 7 files changed, 71 insertions(+), 77 deletions(-) diff --git a/lib/client.js b/lib/client.js index 8ef90e3..ba46ca0 100644 --- a/lib/client.js +++ b/lib/client.js @@ -1,11 +1,11 @@ /* jshint node:true, unused:true */ -var https = require('https'); -var http = require('http'); -var qs = require('qs'); -var Q = require('q'); -var url = require('url'); -var debug = require('debug')('node-gitter'); +var https = require('https'); +var http = require('http'); +var qs = require('qs'); +var Promise = require('bluebird'); +var url = require('url'); +var debug = require('debug')('node-gitter'); var Client = function(token, opts) { opts = opts || {}; @@ -44,7 +44,6 @@ var Client = function(token, opts) { Client.prototype.request = function(method, path, opts) { opts = opts || {}; var self = this; - var defer = Q.defer(); var headers = { 'Authorization': 'Bearer ' + this.token, @@ -67,47 +66,47 @@ Client.prototype.request = function(method, path, opts) { debug('%s %s', req_opts.method, req_opts.path); - var req = scheme.request(req_opts, function(res) { - // Accommodate webpack/browserify - if(res.setEncoding) { - res.setEncoding('utf-8'); - } - - self.rateLimit = res.headers['x-ratelimit-limit']; - self.remaining = res.headers['x-ratelimit-remaining']; - - var data = ''; - res.on('data' , function(chunk) { - data += chunk; - }); - - res.on('end', function() { - var body; - try { - body = JSON.parse(data); - } catch(err) { - defer.reject(new Error(res.statusCode + ' ' + data)); + return new Promise(function(resolve, reject) { + var req = scheme.request(req_opts, function(res) { + // Accommodate webpack/browserify + if(res.setEncoding) { + res.setEncoding('utf-8'); } - if (res.statusCode !== 200) { - defer.reject(new Error(res.statusCode + ' ' + data)); - } else { - defer.resolve(body); - } + self.rateLimit = res.headers['x-ratelimit-limit']; + self.remaining = res.headers['x-ratelimit-remaining']; + + var data = ''; + res.on('data' , function(chunk) { + data += chunk; + }); + + res.on('end', function() { + var body; + try { + body = JSON.parse(data); + } catch(err) { + reject(new Error(res.statusCode + ' ' + data)); + } + + if (res.statusCode !== 200) { + reject(new Error(res.statusCode + ' ' + data)); + } else { + resolve(body); + } + }); }); - }); - req.on('error', function(err) { - defer.reject(err); - }); - - if (opts.body) { - req.write(JSON.stringify(opts.body)); - } + req.on('error', function(err) { + reject(err); + }); - req.end(); + if (opts.body) { + req.write(JSON.stringify(opts.body)); + } - return defer.promise; + req.end(); + }); }; Client.prototype.stream = function(path, cb) { diff --git a/lib/faye.js b/lib/faye.js index 314611d..e915dc8 100644 --- a/lib/faye.js +++ b/lib/faye.js @@ -73,16 +73,7 @@ FayeClient.prototype.disconnect = function() { var subscriptionsInfo = self.subscriptions[sub]; subscriptionsInfo.emitter.removeAllListeners(); - var promise = subscriptionsInfo.subscribe; - - if (promise.isCancellable()) { - promise.cancel(); - return null; - } else { - return promise.then(function(subscription) { - return subscription.unsubscribe(); // TODO: catch - }); - } + return subscriptionsInfo.subscribe.unsubscribe(); }); return Promise.all(promises) diff --git a/lib/gitter.js b/lib/gitter.js index 3e562e5..fa7230b 100644 --- a/lib/gitter.js +++ b/lib/gitter.js @@ -1,4 +1,5 @@ /* jshint node:true, unused:true */ +'use strict'; var Client = require('./client.js'); var Users = require('./users.js'); diff --git a/lib/rooms.js b/lib/rooms.js index 3b8aea6..5d80482 100644 --- a/lib/rooms.js +++ b/lib/rooms.js @@ -1,8 +1,9 @@ /* jshint node:true, unused:true */ +'use strict'; var util = require('util'); var EventEmitter = require('eventemitter3'); -var Q = require('q'); +var Promise = require('bluebird'); var Room = function(attrs, client, faye) { EventEmitter.call(this); @@ -18,8 +19,8 @@ var Room = function(attrs, client, faye) { if (typeof this.users !== 'function') { var users = this.users; this.users = function() { - return Q.resolve(users); - } + return Promise.resolve(users); + }; } this.client = client; @@ -77,23 +78,25 @@ Room.prototype.listen = function() { }); Room.prototype.subscribe = function() { - ['chatMessages', 'events', 'users'].forEach(function(resource) { + this.subscriptions = ['chatMessages', 'events', 'users'].map(function(resource) { var resourcePath = '/api/v1/rooms/' + this.id + '/' + resource; - var events = this.faye.subscribeTo(resourcePath, resourcePath) - events.on(resourcePath, function(msg) { - this.emit(resource, msg); - }.bind(this)); - }.bind(this)); -}; + return this.faye.client.subscribe(resourcePath, function(message) { + this.emit(resource, message); + }, this); + }, this); -Room.prototype.unsubscribe = function() { - ['chatMessages', 'events', 'users'].forEach(function(resource) { - var resourcePath = '/api/v1/rooms/' + this.id + '/' + resource; - var meta = this.faye.subscriptions[resourcePath]; - if (meta) meta.subscription.cancel(); - }.bind(this)); + return Promise.all(this.subscriptions); }; +Room.prototype.unsubscribe = Promise.method(function() { + if (!this.subscriptions) return; + + return Promise.all(this.subscriptions.map(function(subscription) { + return subscription.unsubscribe(); + })); + +}); + // DEPRECATED Rooms is now an event emitter and all you need is to // subscribe() to start receiving events Room.prototype.streaming = function() { @@ -105,7 +108,7 @@ Room.prototype.streaming = function() { events: fn, users: fn, disconnect: function() { this.faye.disconnect(); }.bind(this) - } -} + }; +}; module.exports = Room; diff --git a/package.json b/package.json index d51a1a6..40043a1 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "debug": "^2.2.0", "eventemitter3": "^0.1.6", "gitter-faye": "^1.1.0-e", - "halley": "^0.3.2", + "halley": "^0.4.1", "q": "~1.0.1", "qs": "~1.2.1" }, diff --git a/test/rooms-test.js b/test/rooms-test.js index bf33aab..3ed93f6 100644 --- a/test/rooms-test.js +++ b/test/rooms-test.js @@ -69,7 +69,7 @@ describe('Gitter Rooms', function() { }).then(function(rooms) { var check = rooms.some(function(room) { return room.name === 'node-gitter/yacht'; }); assert.equal(false, check); - }).fin(function() { + }).finally(function() { // Join the room again for the rest of the tests gitter.rooms.join('node-gitter/yacht'); }).nodeify(done); @@ -77,10 +77,10 @@ describe('Gitter Rooms', function() { it('should not be able to join an invalid room', function(done) { gitter.rooms.join('some-invalid-room').then(function() { - }).fail(function(err) { + }).catch(function(err) { assert(err); done(); - }).fail(done); + }).catch(done); }); it('should be able to send a message', function(done) { @@ -136,7 +136,7 @@ describe('Gitter Rooms', function() { }); setTimeout(function() { room.send(msg); }, 500); - }).fail(done); + }).catch(done); }); it('should be able to subscribe to a room', function(done) { @@ -164,7 +164,7 @@ describe('Gitter Rooms', function() { }); setTimeout(function() { room.send(msg); }, 750); - }).fail(done); + }).catch(done); }); diff --git a/test/users-test.js b/test/users-test.js index 9b62182..a4d89d7 100644 --- a/test/users-test.js +++ b/test/users-test.js @@ -72,7 +72,7 @@ describe('Gitter Users', function() { it('should fail when fidning an invalid user', function(done) { gitter.users.find('invalid').then(function() { assert(false); - }).fail(function() { + }).catch(function() { done(); }); }); From 6d2e4ee7974044e4b3f640037dc209940384fb3a Mon Sep 17 00:00:00 2001 From: Andrew Newdigate Date: Fri, 18 Dec 2015 13:09:29 +0000 Subject: [PATCH 3/9] Switched `.subscribe` back to old event --- lib/faye.js | 23 ++++++++--------------- lib/rooms.js | 38 +++++++++++++++++++++----------------- 2 files changed, 29 insertions(+), 32 deletions(-) diff --git a/lib/faye.js b/lib/faye.js index e915dc8..becb78c 100644 --- a/lib/faye.js +++ b/lib/faye.js @@ -52,14 +52,16 @@ FayeClient.prototype.subscribeTo = function(resource, eventName) { if (this.subscriptions[resource]) return this.subscriptions[resource].emitter; var emitter = new EventEmitter(); - var subscribe = this.client.subscribe(resource, function(msg) { + var subscription = this.client.subscribe(resource, function(msg) { emitter.emit(eventName, msg); - }); // TODO: catch + }).catch(function(err) { + emitter.emit('error', err); + }); this.subscriptions[resource] = { eventName: eventName, emitter: emitter, - subscribe: subscribe + subscription: subscription }; return emitter; @@ -68,22 +70,13 @@ FayeClient.prototype.subscribeTo = function(resource, eventName) { FayeClient.prototype.disconnect = function() { var self = this; - var promises = Object.keys(this.subscriptions) - .map(function(sub) { + Object.keys(this.subscriptions) + .forEach(function(sub) { var subscriptionsInfo = self.subscriptions[sub]; subscriptionsInfo.emitter.removeAllListeners(); - - return subscriptionsInfo.subscribe.unsubscribe(); }); - return Promise.all(promises) - .bind(this) - .catch(function() { - // Ignore unsubscribe errors, we plan to disconnect anyway - }) - .then(function() { - return this.client.disconnect(); - }); + return this.client.disconnect(); }; diff --git a/lib/rooms.js b/lib/rooms.js index 5d80482..c5ac382 100644 --- a/lib/rooms.js +++ b/lib/rooms.js @@ -78,24 +78,28 @@ Room.prototype.listen = function() { }); Room.prototype.subscribe = function() { - this.subscriptions = ['chatMessages', 'events', 'users'].map(function(resource) { + ['chatMessages', 'events', 'users'].forEach(function(resource) { var resourcePath = '/api/v1/rooms/' + this.id + '/' + resource; - return this.faye.client.subscribe(resourcePath, function(message) { - this.emit(resource, message); - }, this); - }, this); - - return Promise.all(this.subscriptions); + var events = this.faye.subscribeTo(resourcePath, resourcePath) + events.on(resourcePath, function(msg) { + this.emit(resource, msg); + }.bind(this)); + }.bind(this)); }; -Room.prototype.unsubscribe = Promise.method(function() { - if (!this.subscriptions) return; - - return Promise.all(this.subscriptions.map(function(subscription) { - return subscription.unsubscribe(); - })); - -}); +Room.prototype.unsubscribe = function() { + var promises = Promise.all(['chatMessages', 'events', 'users'].forEach(function(resource) { + var resourcePath = '/api/v1/rooms/' + this.id + '/' + resource; + var meta = this.faye.subscriptions[resourcePath]; + if (meta) { + meta.subscription.then(function(subscription) { + return subscription.unsubscribe(); + }); + } + }.bind(this))); + + return Promise.all(promises) +}; // DEPRECATED Rooms is now an event emitter and all you need is to // subscribe() to start receiving events @@ -108,7 +112,7 @@ Room.prototype.streaming = function() { events: fn, users: fn, disconnect: function() { this.faye.disconnect(); }.bind(this) - }; -}; + } +} module.exports = Room; From 4d974f7543e05bd9e3c204a900da9ce2110d0762 Mon Sep 17 00:00:00 2001 From: Andrew Newdigate Date: Fri, 18 Dec 2015 13:09:44 +0000 Subject: [PATCH 4/9] 2.0.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 40043a1..8047814 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-gitter", - "version": "1.2.8", + "version": "2.0.0", "description": "Gitter client", "main": "lib/gitter.js", "scripts": { From c81439e0ee4dfa237ecdf12b63b12ec352b3f800 Mon Sep 17 00:00:00 2001 From: Andrew Newdigate Date: Fri, 18 Dec 2015 13:11:57 +0000 Subject: [PATCH 5/9] Later version of Halley --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8047814..3983e96 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ "debug": "^2.2.0", "eventemitter3": "^0.1.6", "gitter-faye": "^1.1.0-e", - "halley": "^0.4.1", + "halley": "^0.4.2", "q": "~1.0.1", "qs": "~1.2.1" }, From 40d3355752c887ef9590a3f04c779ee63a1ebd27 Mon Sep 17 00:00:00 2001 From: Andrew Newdigate Date: Fri, 18 Dec 2015 13:14:11 +0000 Subject: [PATCH 6/9] 2.0.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3983e96..9b3c090 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-gitter", - "version": "2.0.0", + "version": "2.0.1", "description": "Gitter client", "main": "lib/gitter.js", "scripts": { From 175ed7ce9eafc3e750f82395b830e83f4578dab7 Mon Sep 17 00:00:00 2001 From: Andrew Newdigate Date: Fri, 18 Dec 2015 14:50:21 +0000 Subject: [PATCH 7/9] Fix for incorrect url for unread items --- lib/users.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/users.js b/lib/users.js index 960e9fb..b311fc8 100644 --- a/lib/users.js +++ b/lib/users.js @@ -1,7 +1,7 @@ /* jshint node:true, unused:true */ var User = function(attrs, client, faye) { - // API path to Users + // API path to Users this.path = '/user'; if (attrs) @@ -32,7 +32,7 @@ User.prototype.findById = function(id, cb) { .then(function(userData) { return new User(userData, this.client, this.faye); }.bind(this)); - + return cb ? user.nodeify(cb) : user; }; @@ -42,7 +42,7 @@ User.prototype.findByUsername = function(username, cb) { var userData = results.results[0]; return new User(userData, this.client, this.faye); }.bind(this)); - + return cb ? user.nodeify(cb) : user; }; @@ -55,7 +55,7 @@ User.prototype.findByUsername = function(username, cb) { }); User.prototype.markAsRead = function(roomId, chatIds, cb) { - var resourcePath = this.path + '/' + this.id + '/troupes/' + roomId + '/unreadItems'; + var resourcePath = this.path + '/' + this.id + '/rooms/' + roomId + '/unreadItems'; var resource = this.client.post(resourcePath, {body: {chat: chatIds}}); return cb ? resource.nodeify(cb) : resource; }; From 284912e40614e7cdffbafcf1c671e48330ee88bf Mon Sep 17 00:00:00 2001 From: Andrew Newdigate Date: Fri, 18 Dec 2015 14:50:27 +0000 Subject: [PATCH 8/9] 2.0.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9b3c090..4b3e872 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-gitter", - "version": "2.0.1", + "version": "2.0.2", "description": "Gitter client", "main": "lib/gitter.js", "scripts": { From af3420ec6960ca26b9f4deb3e8eaee3b1b2f3b18 Mon Sep 17 00:00:00 2001 From: Andrew Newdigate Date: Fri, 18 Dec 2015 14:53:00 +0000 Subject: [PATCH 9/9] 2.0.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4b3e872..dcef0f3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-gitter", - "version": "2.0.2", + "version": "2.0.3", "description": "Gitter client", "main": "lib/gitter.js", "scripts": {