Как в FastAPI правильно обрабатывать асинхронные внешние API, которые никогда не выполняют обратный вызов?Python

Программы на Python
Ответить
Anonymous
 Как в FastAPI правильно обрабатывать асинхронные внешние API, которые никогда не выполняют обратный вызов?

Сообщение Anonymous »

Я использую FastAPI для создания службы API. Моей службе необходимо вызвать внешний API через сеть, назовем его ex_api. В документации ex_api указано, что он принимает задачи, отправленные пользователями, и выполняет их асинхронно. Конкретный процесс вызова выглядит следующим образом:
  • Моя служба отправляет запрос в конечную точку создания задачи ex_api, а параметры запроса содержат callback_url
  • Конечная точка создания задачи ex_api сразу возвращает ответ после получения запроса, который содержит идентификатор созданной задачи
    ex_api автоматически обрабатывает задачу.
  • После обработки ex_api отправляет запрос на callback_url, и полезная нагрузка является результатом обработки моей задачи.
    Мой сервис возвращает ответ после получения запроса, и процесс завершается
Проблема в том, что ex_api не очень стабилен. Иногда он застревает на третьем шаге выше. Но у меня нет возможности узнать об этом, и я всегда жду, пока ex_api перезвонит. У меня есть идея исправить это: просто дождаться обратного вызова от ex_api в течение ограниченного времени, и если время истекло, а обратный вызов все еще не получен, моя служба будет искать другой способ. Но я не знаю, как это сделать. Обратите внимание, что я не имею права изменять какое-либо содержимое или метод работы ex_api.
Мои вопросы следующие:
  • Есть ли какие-либо передовые методы или опыт, которыми вы можете поделиться со мной?
  • Можно ли реализовать мое исправление? Если да, то как это сделать?
Вот пример кода моей проблемы. Допустим, моя служба пытается прибавить 1 к целому числу, а затем умножьте его на 2, и этап сложения должен опираться на внешний API по сети:
from typing import Any

import fastapi
import httpx
from pydantic import BaseModel

THIS_SERVER_URL = "https://fake.this.server.public.url"
CALLBACK_API = "/callback/plus_one"
CALLBACK_URL = f"{THIS_SERVER_URL}{CALLBACK_API}"
API_PLUS_ONE = "https://fake.api.url/api/plus_one"

app = fastapi.FastAPI()

class MyQuery(BaseModel):
x: int

class MyResponse(BaseModel):
message: str
result: int

@app.post("/api/plus_one_mul_two", response_model=MyResponse)
async def post_plus_one_mul_two(params: MyQuery):
async with httpx.AsyncClient() as c:
response = await c.post(
API_PLUS_ONE,
json={
"callback_url": CALLBACK_URL,
"number": params.x,
},
)
response.raise_for_status()
result: dict[str, Any] = response.json()
return {"message": result["message"]}

class CbQuery(BaseModel):
message: str
number: int

class CbResponse(BaseModel):
message: str

async def fake_upload_to_oss(number: int):
pass

# FIXME: May never receive callback!
@app.post(CALLBACK_API, response_model=CbResponse)
async def callback_plus_one_mul_two(params: CbQuery):
if params.message == "ok":
await fake_upload_to_oss(params.number * 2)
else:
raise Exception("failed")
return {"message": "ok"}


Подробнее здесь: https://stackoverflow.com/questions/791 ... y-never-ca
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»