question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

async and thread/process executor delays emit other responses with tornado-mode

See original GitHub issue

Hi there.

I have Socket.IO client on JS and python-socketio AsyncServer under Tornado (i have tornado-app, use get_tornado_handler and async_mode set to tornado) server. Versions: python 3.6, tornado 6.0.1, socketio 4.5.1). For example, I have some handlers in server, which set in constructor:

class MySocketClass(socketio.AsyncServer):
    executor = ThreadPoolExecutor(20)
    _thread_pool = executor

    def __init__(self, _impl):
        super().__init__(async_mode='tornado')
        impl = _impl

        self.on('syncTest', self.message_sync)
        self.on('asyncTest1', self.message_a1)
        self.on('asyncTest2', self.message_a2)
        self.on('asyncTest3', self.message_a3)

    def message_sync(self):
        return None, "Synchronous message"

    # five seconds to work
    async def message_a0(self, *args):
        params = args[1]
        res = await tornado.ioloop.IOLoop.current().run_in_executor(self._thread_pool,
                                                                        functools.partial(impl.internal_message_0, params)
        return None, res

    # seven seconds to work
    async def message_a1(self, *args):
        params = args[1]
        res = await tornado.ioloop.IOLoop.current().run_in_executor(self._thread_pool,
                                                                        functools.partial(impl.internal_message_1, params)
        return None, res

    # one second to work
    async def message_a2(self, *args):
        params = args[1]
        res = await tornado.ioloop.IOLoop.current().run_in_executor(self._thread_pool,
                                                                        functools.partial(impl.internal_message_2, params)
        return None, res

self._thread_pool is concurrent.futures.ThreadPoolExecutor and implementation methods working in another threads. Socket.IO client send 3 messages simultaneously (message_a0, message_a1 and message_a2, I have logging about sending). My expectations are next:

  • SocketIO client get response for message_a3 (as fastest);
  • SocketIO client get response for message_a1 (as mid-speed);
  • SocketIO client get response for message_a2 (as slowest);

But I see that my handlers for message_a2 and message_a3 doesn’t start before ending previous (in debugger I see that these events aren’t triggering while message_a1 is working).

async_handlers flag set to True. I see that we call start_background_task(), but everything work in main thread and sequentially. But I want run some handlers concurrently (which aren’t use shared resources).

I found this issue, but it doesn’t help me.

What should I do differently in my solution (and if it’s using Tornado, how keep Tornado-server and achieve my expectations)?

Thanks in advance!

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:7 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
RSSash2006commented, Jun 11, 2020

Yes, self.sleep with await working concurrently. I tested full project again and discovered that isn’t problem of socket.io or tornado. In the end of my call stack I call some functions from pyd, and these functions lock the GIL. So, I ran another thread in async function, released GIL and locked it again inside.

Thank you in advance and for the idea about await self.sleep!

0reactions
miguelgrinbergcommented, Jun 4, 2020

Oh no, wait, sorry, I’ve made a mistake. I should have said:

res = await self.sleep(val)

Sorry, try it this way.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Tornado difference between run in executor and defining ...
run_on_executor is for interfacing with blocking non-async code. You are correct that async code is only executed in a single thread.
Read more >
Guidelines for Individual Executors & Trustees
Trustees, executors, and personal representatives are all fiduciaries. ... Other assets, such as insurance, may have to be applied for by filing a...
Read more >
Spring @Async for Asynchronous Processing
An introduction to the spring @async annotation. ... You can define multiple executor beans in case you like to have different ...
Read more >
Applied: Build an Executor - Asynchronous Programming in Rust
await it inside an async function, but that just pushes the problem one level up: who will run the futures returned from the...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found