json-rpc icon indicating copy to clipboard operation
json-rpc copied to clipboard

Add an async manager

Open liujordan opened this issue 11 months ago • 1 comments

Description of the Change

This is a full copy of the JSONRPCResponseManager but with an async handle method for async dispatchers

full sample usage of this with a Tornado server that has a die action that kills the process after a short delay

async def delay(coro, seconds):
    await asyncio.sleep(seconds)
    await coro

class MainHandler(tornado.web.RequestHandler):
    dispatcher = None

    def initialize(self, dispatcher):
        self.dispatcher = dispatcher

    async def post(self):
        response = await JSONRPCResponseManagerAsync.handle(self.request.body, self.dispatcher)
        self.write(response.result)


class Server:
    def __init__(self, dispatcher: Dispatcher = None):
        if dispatcher is None:
            dispatcher = Dispatcher()
        self.dispatcher = dispatcher
        self.dispatcher.add_method(self.die)

    async def die(self, **kwargs):
        async def coro():
            sys.exit(0)
        asyncio.create_task(delay(coro(), 10))
        return {"response": "success"}

    def make_app(self):
        return tornado.web.Application([
            (r"/jsonrpc", MainHandler, dict(dispatcher=self.dispatcher)),
        ])

    async def start_server_task(self, **kwargs):
        app = self.make_app()
        app.listen(8888)
        await asyncio.Event().wait()

async def async_main():
    thing_server = Server()
    threads = [
        asyncio.create_task(thing_server.start_server_task()),
    ]
    await asyncio.gather(*threads)


def main(*args, **kwargs):
    try:
        loop = asyncio.get_running_loop()
    except RuntimeError:
        loop = asyncio.new_event_loop()

    try:
        loop.run_until_complete(async_main())
    except KeyboardInterrupt:
        pass

    loop.close()


if __name__ == "__main__":
    main()

Alternate Designs

Benefits

ability to dispatch with async handlers

Possible Drawbacks

This is a copy & paste of the existing manager.py and test_manager.py, any change needs to the manger will need to be made in both places. Some refactoring is recommended in the next PR

#116 mentions theres an ajson-rpc fork and this is meant to support older versions but i do not see the reason why this package can't just bump the major version and cut support for older python versions

Applicable Issues

#116

liujordan avatar Feb 15 '25 23:02 liujordan

Hi @liujordan thank you for the PR! Would https://github.com/pavlov99/ajsonrpc work for your case?

pavlov99 avatar Feb 16 '25 09:02 pavlov99