Commit 2358bd20 authored by Randall Leeds's avatar Randall Leeds

Switch to ws4py

Since pyramid_sockjs seems pretty unmaintained, having fallen behind
gevent-websocket quite a bit, and there don't seem to be any actively
maintained pyramid websocket integration libraries, switch to using
ws4py directly.

This change drops support for non-native websockets. As a result, we
have to do our own JSON decoding of the messages.

We also switch to a `gevent.pywsgi` based worker of our own. This
worker combines the gevent_pywsgi worker from Gunicorn with the
gevent helpers from ws4py that cleanly shutdown sockets on server
termination.
parent 11466a79
...@@ -57,7 +57,7 @@ configure = [ ...@@ -57,7 +57,7 @@ configure = [
basePattern = baseURI.replace /\/[^\/]*$/, '/**.html' basePattern = baseURI.replace /\/[^\/]*$/, '/**.html'
$sceDelegateProvider.resourceUrlWhitelist ['self', basePattern] $sceDelegateProvider.resourceUrlWhitelist ['self', basePattern]
streamerProvider.url = baseURI + '__streamer__' streamerProvider.url = baseURI.replace('http', 'ws') + 'ws'
] ]
......
...@@ -57,23 +57,22 @@ class AppController ...@@ -57,23 +57,22 @@ class AppController
annotator.deleteAnnotation(annotation) annotator.deleteAnnotation(annotation)
streamer.onmessage = (msg) -> streamer.onmessage = (msg) ->
unless msg.data.type? and msg.data.type is 'annotation-notification' data = JSON.parse(msg.data)
unless data.type? and data.type is 'annotation-notification'
return return
data = msg.data.payload payload = data.payload
action = msg.data.options.action action = data.options.action
unless data instanceof Array then data = [data] unless payload instanceof Array then payload = [payload]
p = $scope.persona p = $scope.persona
user = if p? then "acct:" + p.username + "@" + p.provider else '' user = if p? then "acct:" + p.username + "@" + p.provider else ''
unless data instanceof Array then data = [data] unless payload instanceof Array then payload = [payload]
if $scope.socialView.name is 'single-player' if $scope.socialView.name is 'single-player'
owndata = data.filter (d) -> d.user is user payload = payload.filter (d) -> d.user is user
applyUpdates action, owndata
else
applyUpdates action, data
applyUpdates action, payload
$scope.$digest() $scope.$digest()
initStore = -> initStore = ->
......
...@@ -12,12 +12,13 @@ ST_OPEN = 3 ...@@ -12,12 +12,13 @@ ST_OPEN = 3
# Provides access to the streamer websocket. # Provides access to the streamer websocket.
### ###
class Streamer class Streamer
constructor: (url) -> constructor: (transport, url) ->
this.onmessage = -> this.onmessage = ->
this._failCount = 0 this._failCount = 0
this._queue = [] this._queue = []
this._state = ST_CLOSED this._state = ST_CLOSED
this._transport = transport
this._url = url this._url = url
###* ###*
...@@ -33,7 +34,7 @@ class Streamer ...@@ -33,7 +34,7 @@ class Streamer
return return
self = this self = this
this._sock = new SockJS(this._url) this._sock = new this._transport(this._url)
this._state = ST_CONNECTING this._state = ST_CONNECTING
this._sock.onopen = -> this._sock.onopen = ->
...@@ -112,7 +113,9 @@ setAjaxClientId = (clientId) -> ...@@ -112,7 +113,9 @@ setAjaxClientId = (clientId) ->
streamerProvider = -> streamerProvider = ->
provider = {} provider = {}
provider.url = null provider.url = null
provider.$get = -> new Streamer(provider.url) provider.$get = ['$window', ($window) ->
new Streamer($window.WebSocket, provider.url)
]
return provider return provider
......
This diff is collapsed.
...@@ -31,7 +31,6 @@ module.exports = function(config) { ...@@ -31,7 +31,6 @@ module.exports = function(config) {
'h/static/scripts/vendor/moment-timezone.js', 'h/static/scripts/vendor/moment-timezone.js',
'h/static/scripts/vendor/moment-timezone-data.js', 'h/static/scripts/vendor/moment-timezone-data.js',
'h/static/scripts/vendor/Markdown.Converter.js', 'h/static/scripts/vendor/Markdown.Converter.js',
'h/static/scripts/vendor/sockjs-0.3.4.js',
'h/static/scripts/vendor/unorm.js', 'h/static/scripts/vendor/unorm.js',
'h/static/scripts/vendor/uuid.js', 'h/static/scripts/vendor/uuid.js',
'h/static/scripts/vendor/gettext.js', 'h/static/scripts/vendor/gettext.js',
......
...@@ -3,38 +3,39 @@ sinon.assert.expose assert, prefix: null ...@@ -3,38 +3,39 @@ sinon.assert.expose assert, prefix: null
sandbox = sinon.sandbox.create() sandbox = sinon.sandbox.create()
describe 'streamer', -> describe 'streamer', ->
WebSocket = null
fakeSock = null fakeSock = null
streamer = null streamer = null
beforeEach module('h.streamer') beforeEach module('h.streamer')
beforeEach module (streamerProvider) -> beforeEach module ($provide, streamerProvider) ->
fakeSock = {
send: sandbox.spy()
close: sandbox.spy()
}
WebSocket = sandbox.stub().returns(fakeSock)
$provide.decorator '$window', ($delegate) ->
angular.extend $delegate, {WebSocket}
streamerProvider.url = 'http://magicstreemz/giraffe' streamerProvider.url = 'http://magicstreemz/giraffe'
return return
beforeEach inject (_streamer_) -> beforeEach inject (_streamer_) ->
streamer = _streamer_ streamer = _streamer_
beforeEach ->
fakeSock = {
send: sandbox.spy()
close: sandbox.spy()
}
sandbox.stub(window, 'SockJS').returns(fakeSock)
afterEach -> afterEach ->
sandbox.restore() sandbox.restore()
it 'creates a socket with the correct base URL', -> it 'creates a socket with the correct base URL', ->
streamer.open() streamer.open()
assert.calledWith(SockJS, 'http://magicstreemz/giraffe') assert.calledWith(WebSocket, 'http://magicstreemz/giraffe')
it 'does not open another socket while a socket is connecting', -> it 'does not open another socket while a socket is connecting', ->
streamer.open() streamer.open()
streamer.open() streamer.open()
assert.calledOnce(SockJS) assert.calledOnce(WebSocket)
it 'queues messages until the socket is open', -> it 'queues messages until the socket is open', ->
streamer.open() streamer.open()
...@@ -82,7 +83,7 @@ describe 'streamer', -> ...@@ -82,7 +83,7 @@ describe 'streamer', ->
clock.tick(500) clock.tick(500)
assert.calledTwice(SockJS) assert.calledTwice(WebSocket)
it 'closes the socket when close is called', -> it 'closes the socket when close is called', ->
streamer.open() streamer.open()
...@@ -104,4 +105,4 @@ describe 'streamer', -> ...@@ -104,4 +105,4 @@ describe 'streamer', ->
fakeSock.onclose() fakeSock.onclose()
clock.tick(500) clock.tick(500)
assert.calledOnce(SockJS) assert.calledOnce(WebSocket)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment