Permalink
Comparing changes
Open a pull request
- 1 commit
- 8 files changed
- 0 commit comments
- 1 contributor
Unified
Split
Showing
with
64 additions
and 17 deletions.
- +1 −1 h/static/scripts/annotation-viewer-controller.coffee
- +1 −1 h/static/scripts/stream-controller.coffee
- +32 −3 h/static/scripts/streamer.js
- +1 −1 h/static/scripts/test/annotation-viewer-controller-test.coffee
- +1 −1 h/static/scripts/test/stream-controller-test.coffee
- +21 −8 h/static/scripts/test/streamer-test.js
- +6 −1 h/static/scripts/websocket.js
- +1 −1 h/static/scripts/widget-controller.coffee
| @@ -33,4 +33,4 @@ module.exports = class AnnotationViewerController | ||
| .addClause('/references', 'first_of', id, true) | ||
| .addClause('/id', 'equals', id, true) | ||
| streamer.send({filter: streamFilter.getFilter()}) | ||
| streamer.setConfig('filter', {filter: streamFilter.getFilter()}) | ||
| @@ -45,7 +45,7 @@ module.exports = class StreamController | ||
| # Apply query clauses | ||
| terms = searchFilter.generateFacetedFilter $routeParams.q | ||
| queryParser.populateFilter streamFilter, terms | ||
| streamer.send({filter: streamFilter.getFilter()}) | ||
| streamer.setConfig('filter', {filter: streamFilter.getFilter()}) | ||
| # Perform the initial search | ||
| fetch(20) | ||
| @@ -32,12 +32,14 @@ function connect($rootScope, annotationMapper, groups, session, settings) { | ||
| socket.close(); | ||
| } | ||
| var configMessages = {}; | ||
| // Open the socket | ||
| socket = new Socket(url); | ||
| socket.send({ | ||
| setConfig('client-id', { | ||
| messageType: 'client_id', | ||
| value: clientId | ||
| }) | ||
| }); | ||
| function handleAnnotationNotification(message) { | ||
| action = message.options.action | ||
| @@ -70,6 +72,18 @@ function connect($rootScope, annotationMapper, groups, session, settings) { | ||
| session.update(message.model); | ||
| } | ||
| function sendClientConfig () { | ||
| Object.keys(configMessages).forEach(function (key) { | ||
| if (configMessages[key]) { | ||
| socket.send(configMessages[key]); | ||
| } | ||
| }); | ||
| } | ||
| socket.on('open', function () { | ||
| sendClientConfig(); | ||
| }); | ||
| socket.on('error', function (error) { | ||
| console.warn('Error connecting to H push notification service:', error); | ||
| }); | ||
| @@ -94,7 +108,22 @@ function connect($rootScope, annotationMapper, groups, session, settings) { | ||
| }); | ||
| }); | ||
| return socket | ||
| /** | ||
| * Send a configuration message to the push notification service. | ||
| * Each message is associated with a key, which is used to re-send | ||
| * configuration data to the server in the event of a reconnection. | ||
| */ | ||
| function setConfig(key, configMessage) { | ||
| configMessages[key] = configMessage; | ||
| if (socket.isConnected()) { | ||
| socket.send(configMessage); | ||
| } | ||
| } | ||
| return { | ||
| setConfig: setConfig, | ||
| _socket: socket, | ||
| }; | ||
| } | ||
| module.exports = { | ||
| @@ -26,7 +26,7 @@ describe "AnnotationViewerController", -> | ||
| $location: $location or {} | ||
| $routeParams: $routeParams or {id: "test_annotation_id"} | ||
| $scope: $scope or {search: {}} | ||
| streamer: streamer or {send: ->} | ||
| streamer: streamer or {setConfig: ->} | ||
| store: store or { | ||
| AnnotationResource: {get: sinon.spy()}, | ||
| SearchResource: {get: ->}} | ||
| @@ -54,7 +54,7 @@ describe 'StreamController', -> | ||
| fakeStreamer = { | ||
| open: sandbox.spy() | ||
| close: sandbox.spy() | ||
| send: sandbox.spy() | ||
| setConfig: sandbox.spy() | ||
| } | ||
| fakeStreamFilter = { | ||
| @@ -9,6 +9,8 @@ function FakeSocket(url) { | ||
| this.messages = []; | ||
| this.didClose = false; | ||
| this.isConnected = sinon.stub().returns(true); | ||
| this.send = function (message) { | ||
| this.messages.push(message); | ||
| }; | ||
| @@ -71,9 +73,10 @@ describe('streamer', function () { | ||
| }); | ||
| it('should send a client ID', function () { | ||
| assert.equal(socket.messages.length, 1); | ||
| assert.equal(socket.messages[0].messageType, 'client_id'); | ||
| assert.equal(socket.messages[0].value, streamer.clientId); | ||
| var fakeWebSocket = socket._socket; | ||
| assert.equal(fakeWebSocket.messages.length, 1); | ||
| assert.equal(fakeWebSocket.messages[0].messageType, 'client_id'); | ||
| assert.equal(fakeWebSocket.messages[0].value, streamer.clientId); | ||
| }); | ||
| it('should close any existing socket', function () { | ||
| @@ -85,13 +88,13 @@ describe('streamer', function () { | ||
| fakeSession, | ||
| fakeSettings | ||
| ); | ||
| assert.ok(oldSocket.didClose); | ||
| assert.ok(!newSocket.didClose); | ||
| assert.ok(oldSocket._socket.didClose); | ||
| assert.ok(!newSocket._socket.didClose); | ||
| }); | ||
| describe('annotation notifications', function () { | ||
| it('should load new annotations', function () { | ||
| socket.notify({ | ||
| socket._socket.notify({ | ||
| type: 'annotation-notification', | ||
| options: { | ||
| action: 'create', | ||
| @@ -104,7 +107,7 @@ describe('streamer', function () { | ||
| }); | ||
| it('should unload deleted annotations', function () { | ||
| socket.notify({ | ||
| socket._socket.notify({ | ||
| type: 'annotation-notification', | ||
| options: { | ||
| action: 'delete', | ||
| @@ -124,11 +127,21 @@ describe('streamer', function () { | ||
| id: 'new-group' | ||
| }] | ||
| }; | ||
| socket.notify({ | ||
| socket._socket.notify({ | ||
| type: 'session-change', | ||
| model: model, | ||
| }); | ||
| assert.ok(fakeSession.update.calledWith(model)); | ||
| }); | ||
| }); | ||
| describe('reconnections', function () { | ||
| it('resends configuration messages when a reconnection occurs', function () { | ||
| var fakeWebSocket = socket._socket; | ||
| fakeWebSocket.messages = []; | ||
| fakeWebSocket.emit('open'); | ||
| assert.equal(fakeWebSocket.messages.length, 1); | ||
| assert.equal(fakeWebSocket.messages[0].messageType, 'client_id'); | ||
| }); | ||
| }); | ||
| }); | ||
| @@ -59,6 +59,7 @@ function Socket(url) { | ||
| } | ||
| } | ||
| socket = null; | ||
| self.emit('close', event); | ||
| }; | ||
| socket.onerror = function (event) { | ||
| @@ -85,11 +86,15 @@ function Socket(url) { | ||
| */ | ||
| this.send = function (message) { | ||
| messageQueue.push(message); | ||
| if (socket && socket.readyState === WebSocket.OPEN) { | ||
| if (socket && this.isConnected()) { | ||
| sendMessages(); | ||
| } | ||
| }; | ||
| this.isConnected = function () { | ||
| return socket.readyState === WebSocket.OPEN; | ||
| }; | ||
| // establish the initial connection | ||
| reconnect(); | ||
| } | ||
| @@ -50,7 +50,7 @@ module.exports = class WidgetController | ||
| if loaded.length > 0 | ||
| streamFilter.resetFilter().addClause('/uri', 'one_of', loaded) | ||
| streamer.send({filter: streamFilter.getFilter()}) | ||
| streamer.setConfig('filter', {filter: streamFilter.getFilter()}) | ||
| $scope.$on events.GROUP_FOCUSED, -> | ||
| _resetAnnotations(annotationMapper, drafts, threading) | ||