How to run POST requests (one after another) that calculate something without waiting for the end of calculations?
I want my FastApi work asynchronously. POST method accept two parameters: base and exponent and starts to calculate. The calculate method has a time.sleep() inside which depends on the exponent. The parameters (and the id, status and result) are collected in the database (SQLAlchemy). Status and Result should be updating during the calculation running (one can check the progress with GET request).
I want to process some POST/GET asynchronously, without waiting until the end of the calculation the request triggers.
Does anyone have an idea or hint how to make it work in Python? Thank you in advance.
@router.post("/tasks")
async def create_task(base: int, exponent: int, task_dal: TaskDAL = Depends(get_task_dal)):
async with async_session() as session:
async with session.begin():
task_dal = TaskDAL(session)
return await task_dal.create_task(base, exponent)
async def calculate(task: Task):
current_result = 1
for i in range(task.exponent):
await time.sleep(1)
current_result = task.base * current_result
task.status = ((i / task.exponent) * 100)
task.result = current_result
async def create_task(self, base: int, exponent: int):
new_task = Task(base=base, exponent=exponent)
asyncio.gather(TaskDAL.calculate(new_task))
self.db_session.add(new_task)
self.db_session.flush()
In case - all files are in my GitHub repository: https://github.com/wmaterkowska/asynchronous_task_python
UPDATE:
Hi, I rewrote my code with the tips from the comments. Unfortunately it still does not work as it should. It is asynchronous when I open the app in couple different tabs of browser (or in Postman), but that's it. I still do not know how to write it to work fully asynchronously and how to refresh the status of completion of the task.
I was able to achive this all in java but with phyton I still have a problem.
@router.post("/tasks")
async def create_task(base: int, exponent: int, task_dal: TaskDAL =
Depends(get_task_dal)):
async with async_session() as session:
async with session.begin():
task_dal = TaskDAL(session)
T = task_dal.create_task(base, exponent)
asyncio.ensure_future(task_dal.update_task(T))
loop = asyncio.get_running_loop()
res = await loop.run_in_executor(None, partial(task_dal.calculate, T, session))
return await asyncio.gather(res)
task_dal:
async def calculate(self, task: Task, db_session: AsyncSession):
current_result = 1
for i in range(task.exponent):
await asyncio.sleep(1)
current_result = task.base * current_result
task.status = ((i / task.exponent) * 100)
await db_session.flush()
task.result = current_result
task.status = 100
return await db_session.flush()
def create_task(self, base: int, exponent: int):
new_task = Task(base=base, exponent=exponent)
new_task.status = 0
new_task.result = 0
self.db_session.add(new_task)
return new_task
async def update_task(self, task: Task):
self.db_session.flush()
I will be gareful for further help and tips.