Home Understanding async await in python socket io / aiohttp server
Reply: 1

Understanding async await in python socket io / aiohttp server

Julius
1#
Julius Published in 2018-01-12 15:47:13Z

I am trying to setup an socket.io server using python-socketio. Here is a minimal working example:

import asyncio
from aiohttp import web
import socketio
import random

sio = socketio.AsyncServer(async_mode='aiohttp')
app = web.Application()
sio.attach(app)

@sio.on('connect')
def connect(sid, environ):
    print("connected: ", sid)

@sio.on('sendText')
async def message(sid, data):
    print("message ", data)
    # await asyncio.sleep(1 * random.random())
    # print('waited', data)

@sio.on('disconnect')
def disconnect(sid):
    print('disconnect ', sid)

if __name__ == '__main__':
    web.run_app(app, host='0.0.0.0', port=8080)

This runs fine, and I can execute (here in node.js) for instance

const io = require('socket.io-client');
const socket = io('ws://localhost:8080');
socket.emit('sendText', 'hey 1')
socket.emit('sendText', 'hey 2')
socket.emit('sendText', 'hey 3')

If I run the server and run the node script above I get server-side

connected: c1e687f0e2724b339fcdbefdb5aaa8f8

message hey 1

message hey 2

message hey 3

However, if I uncomment the lines with await sleep in the code, I only receive the first message:

connected: 816fb6700f5143f7875b20a252c65f33

message hey 1

waited hey 1

I don't understand why the next messages are not appearing. Can only one instance of async def message run at the same time? Or why?

I am sure that I am not understanding something very fundamental about how this works. I would be very grateful if someone could point out what I am not understanding.

Miguel
2#
Miguel Reply to 2018-01-13 00:39:01Z

I'm the author of the python-socketio package. There are two problems here, I think. I can answer your question:

Can only one instance of async def message run at the same time? Or why?

My Socket.IO server serializes the events that are received from a given client. So for example, if client A sends an event that runs for one minute, any additional events sent by A during that minute will be queued, waiting for the first event to complete first. If client B sends an event during that minute, it will be handled immediately. The reason why events from a client are artificially serialized is to prevent race conditions or other side effects from occurring as a result of two or more handlers for the same client running in parallel. This serialization of events can be turned off, with the async_handlers option:

sio = socketio.AsyncServer(async_mode='aiohttp', async_handlers=True)

Using aiohttp 2.3.7 and async_handlers=True your three events are received at more or less the same time, and then all handlers wait in parallel during their sleep periods.

Unfortunately this does not explain the 2nd and 3rd events never reaching the server. I have verified that these events are properly queued and executed in sequence with aiohttp 2.2.5, but this breaks with 2.3.0 all the way to 2.3.7. My current theory is that a change that was introduced in 2.3.0 is causing these messages that arrive while the task is sleeping to get dropped, but haven't found why that happens yet.

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.361297 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO