Skip to content

Commit 93f70dc

Browse files
async_handlers option for asyncio servers
1 parent 690be4f commit 93f70dc

File tree

3 files changed

+28
-11
lines changed

3 files changed

+28
-11
lines changed

socketio/asyncio_manager.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@ async def emit(self, event, data, namespace, room=None, skip_sid=None,
2323
id = None
2424
tasks.append(self.server._emit_internal(sid, event, data,
2525
namespace, id))
26-
if tasks != []:
27-
await asyncio.wait(tasks)
26+
if tasks == []: # pragma: no cover
27+
return
28+
await asyncio.wait(tasks)
2829

2930
async def close_room(self, room, namespace):
3031
"""Remove all participants from a room.

socketio/asyncio_server.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ class AsyncServer(server.Server):
2424
packets. Custom json modules must have ``dumps`` and ``loads``
2525
functions that are compatible with the standard library
2626
versions.
27+
:param async_handlers: If set to ``True``, event handlers are executed in
28+
separate threads. To run handlers synchronously,
29+
set to ``False``. The default is ``False``.
2730
:param kwargs: Connection parameters for the underlying Engine.IO server.
2831
2932
The Engine.IO configuration supports the following settings:
@@ -55,11 +58,13 @@ class AsyncServer(server.Server):
5558
a logger object to use. To disable logging set to
5659
``False``.
5760
"""
58-
def __init__(self, client_manager=None, logger=False, json=None, **kwargs):
61+
def __init__(self, client_manager=None, logger=False, json=None,
62+
async_handlers=False, **kwargs):
5963
if client_manager is None:
6064
client_manager = asyncio_manager.AsyncManager()
6165
super().__init__(client_manager=client_manager, logger=logger,
62-
binary=False, json=json, **kwargs)
66+
binary=False, json=json,
67+
async_handlers=async_handlers, **kwargs)
6368

6469
def is_asyncio_based(self):
6570
return True
@@ -280,7 +285,11 @@ async def _handle_event(self, sid, namespace, id, data):
280285
namespace = namespace or '/'
281286
self.logger.info('received event "%s" from %s [%s]', data[0], sid,
282287
namespace)
283-
await self._handle_event_internal(self, sid, data, namespace, id)
288+
if self.async_handlers:
289+
self.start_background_task(self._handle_event_internal, self, sid,
290+
data, namespace, id)
291+
else:
292+
await self._handle_event_internal(self, sid, data, namespace, id)
284293

285294
async def _handle_event_internal(self, server, sid, data, namespace, id):
286295
r = await server._trigger_event(data[0], namespace, sid, *data[1:])

tests/test_asyncio_server.py

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,15 @@ def _get_mock_manager(self):
5656
def test_create(self, eio):
5757
eio.return_value.handle_request = AsyncMock()
5858
mgr = self._get_mock_manager()
59-
s = asyncio_server.AsyncServer(client_manager=mgr, foo='bar')
59+
s = asyncio_server.AsyncServer(client_manager=mgr,
60+
async_handlers=True, foo='bar')
6061
_run(s.handle_request({}))
6162
_run(s.handle_request({}))
6263
eio.assert_called_once_with(**{'foo': 'bar', 'async_handlers': False})
6364
self.assertEqual(s.manager, mgr)
6465
self.assertEqual(s.eio.on.call_count, 3)
6566
self.assertEqual(s.binary, False)
66-
self.assertEqual(s.async_handlers, False)
67+
self.assertEqual(s.async_handlers, True)
6768

6869
def test_attach(self, eio):
6970
s = asyncio_server.AsyncServer()
@@ -581,12 +582,18 @@ def loads(*args, **kwargs):
581582
# restore the default JSON module
582583
packet.Packet.json = json
583584

585+
def test_async_handlers(self, eio):
586+
s = asyncio_server.AsyncServer(async_handlers=True)
587+
_run(s._handle_eio_message('123', '2["my message","a","b","c"]'))
588+
s.eio.start_background_task.assert_called_once_with(
589+
s._handle_event_internal, s, '123', ['my message', 'a', 'b', 'c'],
590+
'/', None)
591+
584592
def test_start_background_task(self, eio):
585-
eio.return_value.start_background_task = AsyncMock()
586593
s = asyncio_server.AsyncServer()
587-
_run(s.start_background_task('foo', 'bar', baz='baz'))
588-
s.eio.start_background_task.mock.assert_called_once_with('foo', 'bar',
589-
baz='baz')
594+
s.start_background_task('foo', 'bar', baz='baz')
595+
s.eio.start_background_task.assert_called_once_with('foo', 'bar',
596+
baz='baz')
590597

591598
def test_sleep(self, eio):
592599
eio.return_value.sleep = AsyncMock()

0 commit comments

Comments
 (0)