Browse Source

async_handlers option for asyncio servers

pull/117/merge
Miguel Grinberg 8 years ago
parent
commit
93f70dc9e1
No known key found for this signature in database GPG Key ID: 36848B262DF5F06C
  1. 5
      socketio/asyncio_manager.py
  2. 15
      socketio/asyncio_server.py
  3. 19
      tests/test_asyncio_server.py

5
socketio/asyncio_manager.py

@ -23,8 +23,9 @@ class AsyncManager(BaseManager):
id = None
tasks.append(self.server._emit_internal(sid, event, data,
namespace, id))
if tasks != []:
await asyncio.wait(tasks)
if tasks == []: # pragma: no cover
return
await asyncio.wait(tasks)
async def close_room(self, room, namespace):
"""Remove all participants from a room.

15
socketio/asyncio_server.py

@ -24,6 +24,9 @@ class AsyncServer(server.Server):
packets. Custom json modules must have ``dumps`` and ``loads``
functions that are compatible with the standard library
versions.
:param async_handlers: If set to ``True``, event handlers are executed in
separate threads. To run handlers synchronously,
set to ``False``. The default is ``False``.
:param kwargs: Connection parameters for the underlying Engine.IO server.
The Engine.IO configuration supports the following settings:
@ -55,11 +58,13 @@ class AsyncServer(server.Server):
a logger object to use. To disable logging set to
``False``.
"""
def __init__(self, client_manager=None, logger=False, json=None, **kwargs):
def __init__(self, client_manager=None, logger=False, json=None,
async_handlers=False, **kwargs):
if client_manager is None:
client_manager = asyncio_manager.AsyncManager()
super().__init__(client_manager=client_manager, logger=logger,
binary=False, json=json, **kwargs)
binary=False, json=json,
async_handlers=async_handlers, **kwargs)
def is_asyncio_based(self):
return True
@ -280,7 +285,11 @@ class AsyncServer(server.Server):
namespace = namespace or '/'
self.logger.info('received event "%s" from %s [%s]', data[0], sid,
namespace)
await self._handle_event_internal(self, sid, data, namespace, id)
if self.async_handlers:
self.start_background_task(self._handle_event_internal, self, sid,
data, namespace, id)
else:
await self._handle_event_internal(self, sid, data, namespace, id)
async def _handle_event_internal(self, server, sid, data, namespace, id):
r = await server._trigger_event(data[0], namespace, sid, *data[1:])

19
tests/test_asyncio_server.py

@ -56,14 +56,15 @@ class TestAsyncServer(unittest.TestCase):
def test_create(self, eio):
eio.return_value.handle_request = AsyncMock()
mgr = self._get_mock_manager()
s = asyncio_server.AsyncServer(client_manager=mgr, foo='bar')
s = asyncio_server.AsyncServer(client_manager=mgr,
async_handlers=True, foo='bar')
_run(s.handle_request({}))
_run(s.handle_request({}))
eio.assert_called_once_with(**{'foo': 'bar', 'async_handlers': False})
self.assertEqual(s.manager, mgr)
self.assertEqual(s.eio.on.call_count, 3)
self.assertEqual(s.binary, False)
self.assertEqual(s.async_handlers, False)
self.assertEqual(s.async_handlers, True)
def test_attach(self, eio):
s = asyncio_server.AsyncServer()
@ -581,12 +582,18 @@ class TestAsyncServer(unittest.TestCase):
# restore the default JSON module
packet.Packet.json = json
def test_async_handlers(self, eio):
s = asyncio_server.AsyncServer(async_handlers=True)
_run(s._handle_eio_message('123', '2["my message","a","b","c"]'))
s.eio.start_background_task.assert_called_once_with(
s._handle_event_internal, s, '123', ['my message', 'a', 'b', 'c'],
'/', None)
def test_start_background_task(self, eio):
eio.return_value.start_background_task = AsyncMock()
s = asyncio_server.AsyncServer()
_run(s.start_background_task('foo', 'bar', baz='baz'))
s.eio.start_background_task.mock.assert_called_once_with('foo', 'bar',
baz='baz')
s.start_background_task('foo', 'bar', baz='baz')
s.eio.start_background_task.assert_called_once_with('foo', 'bar',
baz='baz')
def test_sleep(self, eio):
eio.return_value.sleep = AsyncMock()

Loading…
Cancel
Save