Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
0191289
Initial skeleton for changes to enable distributed gevent-socketio:
dragozov Feb 13, 2014
89f5c71
- Session lock won't block for multiple calls from the same socket, i…
dragozov Feb 14, 2014
4c608ab
Handling of namespaces for distributed sockets.
dragozov Feb 15, 2014
7509aa6
Configuring and creating the socket manager
dragozov Feb 15, 2014
6a75566
Minor refactoring
dragozov Feb 15, 2014
48d5904
Bugfixing and refactoring.
dragozov Feb 16, 2014
1ca794f
Minor fix in the default implementation for SocketManager
dragozov Feb 16, 2014
e5f3f40
Bugfixes for the Redis based socket-manager.
dragozov Feb 17, 2014
5d3337e
- Added 'emit_to_endpoint' method at SocketManager
dragozov Feb 18, 2014
2029fb5
Cooperative emit filtering for namespace mixins.
dragozov Feb 18, 2014
f4c7d39
- Cleanup socket data from Redis when disconnected.
dragozov Feb 21, 2014
f6ee0f7
Added support for listening to 'socket' and 'endpoint' events to Sock…
dragozov Feb 25, 2014
413133b
Fixes for cleaning up after disconnected sockets.
dragozov Feb 26, 2014
f659fed
Better cleanup after detach.
dragozov Feb 26, 2014
be88aad
All existing tests pass.
dragozov Feb 26, 2014
183860f
Fixed the django_chat project to work with new code.
dragozov Feb 26, 2014
373adc3
Sample gunicorn config file
dragozov Feb 28, 2014
807d65e
Localhost for Redis config
dragozov Feb 28, 2014
92513ff
Split socket data hashes (for Redis manager) in smaller buckets.
dragozov Mar 4, 2014
6a5fd2c
Don't wait between runs of the _orphan_cleaner until orphans are stil…
dragozov Mar 4, 2014
bb796c7
Notify listeners for orphan cleanup after the Redis commands where run
dragozov Mar 5, 2014
1a140ea
Don't crash when removing listeners that were not listening.
dragozov Mar 5, 2014
58bd693
Better Redis cleanup
dragozov Mar 9, 2014
b38f31b
Switched to sorted sets for keeping track of dead sockets.
dragozov Mar 10, 2014
939f028
Convert score to string when querying Redis.
dragozov Mar 10, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
Caution!!!
============

This is an experimental fork of ``gevent-socketio`` that adds support for
pluggable backends to create and manage the lifecycle of sockets across multiple
workers and implements a Redis-based version of such a backend.

There are significant changes to the original code and it won't be
backward-compatible with existing projects. However it should be relatively
trivial to switch, if you know what you are doing.

Presentation
============

Expand Down
26 changes: 26 additions & 0 deletions examples/django-gunicorn-redis/gunicorn.conf.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import multiprocessing
import os
os.environ["GEVENT_RESOLVER"] = "ares" #Resolves some nasty bugs with native socket creation in imports (for example a mobile detection lib reading cache from Redis)

bind = "0.0.0.0:8080"
workers = multiprocessing.cpu_count() * 2 + 1
max_requests = 10000
worker_class = "socketio.sgunicorn.GeventSocketIOWorker"
preload_app = True

raw_env=[
"SOCKET_MANAGER_CLASS=socketio.contrib.redis.socket_manager.RedisSocketManager",
"SOCKET_MANAGER_REDIS_HOST=127.0.0.1",
"SOCKET_MANAGER_REDIS_PORT=6379",
"SOCKET_MANAGER_REDIS_DB=0"
]


loglevel = "debug"


# this ensures forked processes are patched with psycogreen
def post_fork(server, worker):
os.environ["GEVENT_RESOLVER"] = "ares"
from psycogreen.gevent import patch_psycopg
patch_psycopg()
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,15 @@ def handle(self, addrport="", *args, **options):
print "SocketIOServer running on %s:%s" % bind
print
handler = self.get_handler(*args, **options)
server = SocketIOServer(bind, handler, resource="socket.io", policy_server=True)
manager_conf = getattr(settings, "SOCKET_MANAGER", None)
kw = {
"resource":"socket.io",
"policy_server":True
}
if manager_conf:
kw["socket_manager_config"] = manager_conf
print "SocketManager settings %s" % manager_conf
server = SocketIOServer(bind, handler, **kw)
server.serve_forever()
except KeyboardInterrupt:
if RELOAD:
Expand Down
28 changes: 18 additions & 10 deletions examples/django_chat/chat/sockets.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,34 +12,42 @@ def initialize(self):
self.logger = logging.getLogger("socketio.chat")
self.log("Socketio session started")


def log(self, message):
self.logger.info("[{0}] {1}".format(self.socket.sessid, message))

def on_join(self, room):
self.room = room
self.join(room)
return True

def on_nickname(self, nickname):
self.log('Nickname: {0}'.format(nickname))
self.nicknames.append(nickname)
self.socket.session['nickname'] = nickname
self.session['nickname'] = nickname
nicknames = self.session.get('nicknames', None)#WTH is 'nicknames'?!!
if nicknames is None:
nicknames = set()
nicknames.add(nickname)
self.session['nicknames'] = nicknames

self.broadcast_event('announcement', '%s has connected' % nickname)
self.broadcast_event('nicknames', self.nicknames)
self.broadcast_event('nicknames', list(nicknames))
return True, nickname

def recv_disconnect(self):
# Remove nickname from the list.
self.log('Disconnected')
nickname = self.socket.session['nickname']
self.nicknames.remove(nickname)
nickname = self.session.get('nickname')
if nickname:
nicknames = self.session.get('nicknames', None)
if nicknames:
nicknames.remove(nickname)
self.session['nicknames'] = nicknames
self.broadcast_event('announcement', '%s has disconnected' % nickname)
self.broadcast_event('nicknames', self.nicknames)
self.broadcast_event('nicknames', list(self.nicknames))
self.disconnect(silent=True)
return True

def on_user_message(self, msg):
def on_user_message(self, room, msg):
self.log('User message: {0}'.format(msg))
self.emit_to_room(self.room, 'msg_to_room',
self.socket.session['nickname'], msg)
self.emit_to_room(room, 'msg_to_room', self.session['nickname'], msg)
return True
2 changes: 1 addition & 1 deletion examples/django_chat/chat/static/js/chat.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ $(function () {

$('#send-message').submit(function () {
message('me', $('#message').val());
socket.emit('user message', $('#message').val());
socket.emit('user message', window.room, $('#message').val());
clear();
$('#lines').get(0).scrollTop = 10000000;
return false;
Expand Down
3 changes: 3 additions & 0 deletions examples/django_chat/chatproject/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,6 @@
},
}

SOCKET_MANAGER = {
"class": "socketio.socket_manager.SocketManager"
}
2 changes: 1 addition & 1 deletion examples/simple_pyramid_chat/chatter2/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def emit_to_room(self, event, args, room):
args=args,
endpoint=self.ns_name)
room_name = self._get_room_name(room)
for sessid, socket in self.socket.server.sockets.iteritems():
for sessid, socket in self.socket.manager.sockets.iteritems():
if not hasattr(socket, 'rooms'):
continue
if room_name in socket.rooms:
Expand Down
Empty file added socketio/contrib/__init__.py
Empty file.
Empty file.
Loading