[英]Task progress is not updated latest status on Celery+RabbitMQ
我在Celery + RabbitMQ結果后端上使用自定義狀態實現了長期任務的進度反饋。
但是呼叫者無法按我期望的那樣獲取最新的進度狀態。 在以下代碼中, result.info['step']
始終返回0
,然后任務將以“ result = 42”結束。
# tasks.py -- celery worker
from celery import Celery
app = Celery('tasks', backend='amqp', broker='amqp://guest@localhost//')
@app.task
def long_task():
for i in range(0, 10):
timer.sleep(10) # some work
self.update_state(state='PROGRESS', meta={'step': i})
return 42
# caller.py
from tasks import long_task
result = long_task.delay()
while not (result.successful() or result.failed()):
try:
result.get(timeout=1)
except celery.exceptions.TimeoutError:
if result.state == 'PROGRESS':
print("progress={}".format(result.info['step']))
print("result={}".format(result.get()))
Python 3.4.1 /芹菜3.1.17 / RabbitMQ 3.4.4
我相信這是一個細微的計時問題,再加上RabbitMQ結果后端將任務結果作為消息發送,並且只能被檢索一次的事實。
預先簡短的答案:避免在真正需要最終結果之前調用result.get()
:
while not result.ready():
if result.state == "PROGRESS":
print("progress={}".format(result.info['step']))
time.sleep(1)
print("result={}".format(result.get()))
# +additional cleanup: see comments below
更長的答案是,這里實際上有兩種與AMQP后端對話的方法(和屬性):
調用AMQPBackend.wait_for()
,它將消耗任務隊列中的所有結果,直到出現狀態為celery.states.READY_STATES
的結果為止。
AsyncResult.successful()
, AsyncResult.failed()
, AsyncResult.info
調用AMQPBackend.get_task_meta()
,它將使用任務隊列中的所有結果,然后進行緩存並返回最新的結果。 如果未檢索到任何消息,則后端將返回緩存的結果或PENDING
結果。 注意:最新消息由后端重新排隊 ,如果是最終結果 ,它將由AsyncResult
實例1緩存。
調用result.get()
將消耗所有狀態更新,而result.info
沒有機會提供最新進度報告; 取而代之的是,它很可能是一個過時的緩存,它在某個時候成功捕獲了對AsyncResult.get_task_meta()
的調用之一。
因此,根據時間安排,在次最差情況下, step
可能會停留在0,最差的情況是PROGRESS
狀態永遠不會到達調用者。
1因為通過調用get_task_meta()
來獲取最終結果時,它既要重新排隊get_task_meta()
緩存,所以您需要按照以下注釋中的說明手動排空隊列。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.