1

I have an application setup using FastAPI and Celery for some CPU intensive tasks (basically some synchronous functions defined). One of the REST endpoints is request_data defined as async that users can call to request data. It provides an optional parameter force that if False would simply return the data from Cassandra. But, if force is True, then the REST endpoint has to perform the CPU intensive task in sync and return the results back in the same request.

Here my problem is that, since the function is defined as async, calling the CPU intensive task would block the event loop and hamper FastAPI from handling other requests.

I tried to look for following:

  • Define two functions (one sync and one async). If FastAPI would allow me to add a middleware that can route my request to respective function but it doesn't seem possible.
  • Submit the task to celery in async fashion. But it doesn't seem I can await on the result and so waiting otherwise would simply block the event loop.
  • As a last option, I can make the REST endpoint function as sync but wanted to avoid that. Reason is that I am using Cassandra that provides async support via execute_async on which I can await. Making the REST endpoint function sync would take away async benefits on Cassandra IO.

Does any one has any suggestions on this? I understand that calling a synchronous function in an asynchronous function would eventually mean that event loop would have to perform the CPU intensive task. My only concern is how to do that without blocking the event loop—in other words, without blocking FastAPI from handling other requests?

from fastapi import FastAPI
import cassandra_wrapper  # Class wrapper providing access to Cassandra database

app = FastAPI()

@app.get("/data")
async def request_data(force=False):
    if force:
        # perform computations and return data
        return cpu_intensive_task()
    else:
        return cassandra_wrapper.get_data()


# Can call this celery task to do computations
@celery.task(bind=True, name="cpu_intensive_task")
def cpu_intensive_celery_task():
    return cpu_intensive_task


# Or can call this function directly to do computations
def cpu_intensive_task():
    import time
    time.sleep(5)
Chris
  • 18,724
  • 6
  • 46
  • 80
ATK
  • 358
  • 3
  • 17

0 Answers0