2014-06-24 33 views
5

Làm cách nào để kéo kết quả của tác vụ nếu tôi không biết trước đó tác vụ nào đã được thực hiện? Dưới đây là các thiết lập: Với nguồn sau ('tasks.py'):Lấy kết quả từ 'task_id' trong Celery từ tác vụ không xác định

from celery import Celery 

app = Celery('tasks', backend="db+mysql://u:[email protected]/db", broker = 'amqp://guest:[email protected]:5672//') 

@app.task 
def add(x,y): 
    return x + y 


@app.task 
def mul(x,y): 
    return x * y 

với RabbitMQ 3.3.2 chạy cục bộ:

marcs-mbp:sbin marcstreeter$ ./rabbitmq-server 

       RabbitMQ 3.3.2. Copyright (C) 2007-2014 GoPivotal, Inc. 
    ## ##  Licensed under the MPL. See http://www.rabbitmq.com/ 
    ## ## 
    ########## Logs: /usr/local/var/log/rabbitmq/[email protected] 
    ###### ##  /usr/local/var/log/rabbitmq/[email protected] 
    ########## 
       Starting broker... completed with 10 plugins. 

với cần tây 3.1.12 chạy cục bộ:

-------------- [email protected] v3.1.12 (Cipater) 
---- **** ----- 
--- * *** * -- Darwin-13.2.0-x86_64-i386-64bit 
-- * - **** --- 
- ** ---------- [config] 
- ** ---------- .> app:   tasks:0x105dea3d0 
- ** ---------- .> transport: amqp://guest:**@localhost:5672// 
- ** ---------- .> results:  disabled 
- *** --- * --- .> concurrency: 8 (prefork) 
-- ******* ---- 
--- ***** ----- [queues] 
-------------- .> celery   exchange=celery(direct) key=celery 

Sau đó tôi có thể nhập phương thức và truy xuất kết quả bằng 'task_id':

from tasks import add, mul 
from celery.result import AsyncResult 

result = add.delay(2,2) 
task_id = result.task_id 
result.get() # 4 

result = AsyncResult(id=task_id) 
result.get() # 4 

result = add.AsyncResult(id=task_id) 
result.get() # 4 

# and the same for the 'mul' task. Just imagine I put it here 

Trong ví dụ tiếp theo, tôi chia các bước này giữa các quy trình. Trong một quá trình tôi lấy 'task_id' như vậy:

from tasks import add 

result = add.delay(5,5) 
task_id = result.task_id 

Và trong quá trình khác nếu tôi sử dụng cùng một 'task_id' (sao chép và dán khác REPL, hoặc trong một yêu cầu HTTP khác nhau) như vậy:

from celery.result import AsyncResult 

result = AsyncResult(id="copied_task_id", backend="db+mysql://u:[email protected]/db") 
result.get() # AttributeError: 'str' object has no attribute 'get_task_meta' 
result.state # AttributeError: 'str' object has no attribute 'get_task_meta' 
result.status # AttributeError: 'str' object has no attribute 'get_task_meta' 

Và trong quá trình khác nếu tôi làm:

from task import add # in this instance I know that an add task was performed 

result = add.AsyncResult(id="copied_task_id") 
result.status # "SUCCESSFUL" 
result.state # "SUCCESSFUL" 
result.get() # 10 

tôi muốn để có thể nhận được kết quả mà không cần biết trước khi tay những gì nhiệm vụ được tạo ra kết quả. Trong môi trường thực của tôi, tôi dự định trả lại task_id này cho máy khách và cho phép họ truy vấn trạng thái công việc của họ thông qua một yêu cầu HTTP.

Trả lời

11

Ok - vì vậy tôi đã tìm kiếm một giải pháp cho một thời gian dài, và bây giờ mà tôi đã cuối cùng đã chính thức đăng tải này và nhìn qua documentation tôi thấy this gem:

lớp celery.result .AsyncResult (id, backend = None, task_name = None, app = None, parent = None)

Trạng thái nhiệm vụ truy vấn.

thông số:

id - xem id.

chương trình phụ trợ - xem backend.

ngoại lệTimeoutError

Lỗi lớn lên cho timeout.

AsyncResult.ứng dụng = Không

Vì vậy, thay vì cung cấp các tham số backend tôi cung cấp các "ứng dụng" lập luận thay vì như vậy:

from celery.result import AsyncResult 
from task import app 

# Assuming add.delay(10,10) was called in another process 
# and that I'm using a 'task_id' I retrieved from that process 

result = AsyncResult(id='copied_task_id', app=app) 
result.state # 'SUCCESSFUL' 
result.get() # 20 

Đây có lẽ là hiển nhiên đối với nhiều người. Nó không phải với tôi. Bây giờ tất cả những gì tôi có thể nói là giải pháp này "chỉ hoạt động", nhưng tôi cảm thấy thoải mái hơn nếu tôi biết đó là cách bị xử phạt để làm điều đó. Nếu bạn biết một phần trong tài liệu làm rõ điều này, hãy đăng nó trong phần bình luận hoặc làm câu trả lời và tôi sẽ chọn nó làm câu trả lời nếu có thể.

+0

Chính xác những gì tôi đang tìm kiếm; Tôi chia sẻ quan điểm của bạn rằng điều này là rất không rõ ràng từ các tài liệu để bài viết của bạn đã giúp tôi rất nhiều. – markjan

+0

Bạn có thể muốn thiết lập một thời gian chờ nhỏ trên cuộc gọi này, bởi vì một số cuộc gọi 'có thể' của Celery có thể không trả lại trong một thời gian rất dài trong trường hợp ID nhiệm vụ không hợp lệ hoặc một tác vụ không còn được người môi giới biết đến. Xem http://stackoverflow.com/a/10074280/992887 – RichVel

+0

Cảm ơn bạn đã sửa lỗi này. Nó khiến tôi kéo tóc trong 2 tuần. – Pant

Các vấn đề liên quan