简体   繁体   中英

quart is not able to process multi request from a background task

We are using quart from last 6 months and it was a awesome journey with it. Now we have a new requirement where we need to build a request engine using which we can make request to any url. Now we have tried different url and it work perfectly whereas it fails on the same server request. As it was already running for 3-4 months we can not make a full refactor. is there a better way to handle this scenario?


from quart import Quart, request
import time
import asyncio

import requests

app = Quart(__name__)
 
 
@app.route("/", methods=["POST", "GET"])
async def main_route():
  print("Hello from main route")
  await asyncio.sleep(1)

  loop = asyncio.get_event_loop()

  
  async def handle_future(timeout):
    print("future is here")

    res = requests.get('http://0.0.0.0:5000/test')
    print("Response from test route",res.text)

    await asyncio.sleep(timeout)
    print("I am completed")

  def call_soon():
    asyncio.ensure_future(handle_future(10))

  loop.call_soon_threadsafe(call_soon)

  return "Hello from root"


@app.route("/test", methods=["POST", "GET"])
async def test_route():
  print("Hello from test route")
  await asyncio.sleep(0.5)
  return "Hello from test" + str(time.time())


if __name__ == '__main__':
  from hypercorn.config import Config
  from hypercorn.asyncio import serve

  Config.bind = ["0.0.0.0:5000"]
  asyncio.run(serve(app, Config()))

Output

 * Serving Quart app 'index'
 * Environment: production
 * Please use an ASGI server (e.g. Hypercorn) directly in production
 * Debug mode: False
 * Running on http://0.0.0.0:5000 (CTRL + C to quit)
[2022-03-22 10:54:09,047] Running on http://0.0.0.0:5000 (CTRL + C to quit)
Hello from main route
[2022-03-22 10:54:13,775] 127.0.0.1:49650 GET / 1.1 200 15 1009876
future is here

It was hanged infinitely until the request is timed out. And moreover, it is not accepting any more request during this period

I'd recommend you use a background task to run a coroutine function in the background (via add_background_task). I'd also recommend you switch from requests to httpx as httpx makes requests without blocking the event loop (you can also use requests by using the app.ensure_async function). This is what I suggest,

import asyncio
import time

import httpx
from quart import Quart, request

app = Quart(__name__)

async def _background_task(timeout):
    async with httpx.AsyncClient() as client:
        response = await client.get('http://0.0.0.0:5000/test')
        print("Response from test route", response.text)
    await asyncio.sleep(timeout)
    print("I am completed")
 
@app.route("/", methods=["POST", "GET"])
async def main_route():
    print("Hello from main route")
    await asyncio.sleep(1)
    app.add_background_task(_background_task, 10)
    return "Hello from root"

@app.route("/test", methods=["POST", "GET"])
async def test_route():
    print("Hello from test route")
    await asyncio.sleep(0.5)
    return "Hello from test" + str(time.time())

if __name__ == '__main__':
    from hypercorn.config import Config
    from hypercorn.asyncio import serve

    Config.bind = ["0.0.0.0:5000"]
    asyncio.run(serve(app, Config()))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM