Archtecture/Design pattern for communication between asyncio and non-asyncio context

  Kiến thức lập trình

I am writing a TCP-based client which do both req/rep pattern communication and push/pull pattern communication. I tried to employ asyncio and its transport/protocol structure to handle the low-level transport actions. But the APIs for others to use is not run in asyncio context. So I create the following archetecture to run asyncio in a thread and use asyncio.run_coroutine_threadsafe to submit request and wait the response using a future.

import asyncio as aio
from threading import Thread

class MyProtocol(aio.Protocol):
    ...

async def aio_main(drv, ip, port):
    loop = aio.get_running_loop()
    on_connection_lost = loop.create_future()
    transport, protocol = loop.create_connection(
        lambda: MyProtocol(drv, on_connection_lost ), ip, port
    )
    drv._transport = transport
    drv._protocol = protocol
    drv._loop = loop
    try:
        await on_connect_lost
    finally:
        transport.close()

class Driver:
    def __init__(self):
        self._thread = Thread(target=lambda: aio.run(aio_main(self, '192.168.0.1', 8888))
        self._thread.start()

    async def _request(self, data):
        loop = aio.get_running_loop()
        fut = loop.create_future()
        self._transport.write(data)
        return await fut # which is set in MyProtocol

    def request(self, data):
        coro = self._request(b'HELLO')
        fut = aio.run_coroutine_threadsafe(coro, self._loop)
        return fut.result(1.0) # 1s timeout

Does this archetecture a good practice or bad? Is there better pattern do handle this?

Theme wordpress giá rẻ Theme wordpress giá rẻ Thiết kế website

LEAVE A COMMENT