我试图使用芹菜发送从1到大约25个连续请求到第三方API的任何地方。衡量成功的标准是我是否在响应有效负载中获得一个URL:response_json["data"]["url"]
。不管是不是芹菜,有时候我能得到我想要的数据,有时候却得不到。
我决定尝试用芹菜来重试API调用,同时利用内置的指数回退,这听起来非常适合我的需要,但我正在努力实现。
当我期望的数据在响应有效负载中不可用时,我得到一个TypeError: 'type' object is not iterable
(即,响应中没有这样的项)。但我也得到了一个Internal Server Error
,我想知道我是否需要处理,或者我是否可以用来触发重试。
下面是我尝试过的几个类似方法中的一个:
@shared_task(autoretry_for=(Exception), retry_backoff=True, retry_backoff_max=120)
def third_party_api_request(payload, api_url, headers):
response = requests.request("POST", api_url, headers=headers, data=payload)
response_json = response.json()
return response_json["data"]["url"]
# output:
Internal Server Error:
-- snip --
autoretry_for = tuple(
TypeError: 'type' object is not iterable
我试过的另一种方法:
@shared_task(bind=True)
def third_party_api_request(self, payload, api_url, headers):
try:
response = requests.request("POST", api_url, headers=headers, data=payload)
response_json = response.json()
return response_json["data"]["url"]
except TypeError as exc:
logger.error("Error sending request to API: %s", exc)
raise self.retry(exc=exc)
# output:
ERROR 2022-04-22 17:31:40,131 tasks 72780 123145528369152 Error sending request to API: 'NoneType' object is not subscriptable
Internal Server Error:
-- snip --
TypeError: 'NoneType' object is not subscriptable
-- snip --
raise ret
celery.exceptions.Retry: Retry in 180s: TypeError("'NoneType' object is not subscriptable")
ERROR 2022-04-22 17:31:40,409 log 72780 123145528369152 Internal Server Error:
-- snip --
TypeError: 'NoneType' object is not subscriptable
-- snip --
raise ret
celery.exceptions.Retry: Retry in 180s: TypeError("'NoneType' object is not subscriptable")
还有另一种方法,结果相似:
@shared_task(autoretry_for=(TypeError), retry_backoff=True, retry_backoff_max=120)
def send_http_request_to_proctoru_task(payload, api_url, headers):
response = requests.request("POST", api_url, headers=headers, data=payload)
response_json = response.json()
try:
return response_json["data"]["url"]
except TypeError:
logger.error("API response: %s", response_json)
raise
问题是我放错了返回语句。我还有很多微调要做,但是下面的代码解决了我今天早些时候提出的问题中的问题。几天来,我一直在阅读帖子、文档和文章,我希望我能感谢每个人,但这篇博客文章最终帮助我意识到自己的错误:https://testdriven.io/blog/retrying-failed-celery-tasks/.
@shared_task(name="send_http_request_to_proctoru_task", bind=True, max_retries=6)
def send_http_request_to_proctoru_task(self, api_url, headers, payload):
try:
response = requests.request("POST", api_url, headers=headers, data=payload)
response_json = response.json()
if response_json["response_code"] == 2:
raise Exception()
return response_json["data"]["url"]
except Exception as exc:
logger.warning("Exception raised. Executing retry %s" % self.request.retries)
raise self.retry(exc=exc, countdown=2 ** self.request.retries)