[英]run celery task only once on button click
我創建了一個celery任務來組織數據庫表的django應用。 芹菜任務大約需要8秒鍾來完成這項工作(相當多的表移動和超過100萬行的查找)
此芹菜通過注冊用戶單擊按鈕開始。
我在views.py中創建了一個任務視圖,並在urls.py中創建了一個單獨的task-url。 導航到此任務URL時,任務開始。
我的問題:
如何防止每次刷新時啟動任務,並防止導航到另一個頁面。 理想情況下,用戶只能運行此特定類型的一項任務。
可以在JQuery / Ajax中實現嗎? 因為我不是專家,也沒有使用JQuery / Ajax的經驗,所以有些英雄可以向我指出正確的方向。
謝謝
“如何防止每次刷新時啟動任務”
首先,請確保使用“ POST / redirect / GET”模式:您的視圖應僅在“ POST”請求上觸發任務(GET請求必須沒有副作用),然后返回HttpResponseRedirect
。
這不會阻止用戶在第一個任務仍在運行時觸發第二個任務,但確實可以防止每次刷新(“ GET”)頁面時重新提交表單...
理想情況下,用戶只能運行此特定類型的一項任務。
觸發任務時,將其ID存儲在會話中,並在觸發任務之前檢查會話中的任務ID。 如果有,請使用它檢查任務的狀態。 如果完成(無論結果如何),請刪除任務ID並繼續執行新任務,否則僅顯示一條消息,告訴您用戶他已經在運行任務。
只要確保您在會話中正確處理了“幽靈” task_id的情況即可(這可能是一個長期完成的任務,芹菜已經放棄了該結果,或者是一個因工人或經紀人崩潰而迷失的任務-是的,噓! t發生-等等)。 一個(timestamp, task_id)
解決方案是實際存儲(timestamp, task_id)
對,並且如果celery沒有task_id的狀態-實際上“無狀態”被命名為celery.states.PENDING
,這實際上意味着“我沒有一個有關此任務的狀態ATM的線索”-檢查時間戳記。 如果它比它應有的年代久遠,那么您可能會認為它已經死了而且在6英尺以下。
並防止導航到另一個頁面。
實際上,您為什么要阻止您的用戶執行其他操作? 從UI / UX的角度來看,一旦任務被觸發,您的用戶應被重定向到“請稍候”頁面,並(盡可能)帶有一些進度條或類似的反饋。 這里的簡單(如果有點繁瑣)的解決方案是使用ajax進行一些輪詢:您設置一個接受task_id的視圖,檢查結果/進度,並將其返回為json,然后“請等待”頁面調用此視圖(使用ajax )每隔X秒更新一次(可能會在完成任務后將用戶重定向到下一頁)。
現在,如果有一些操作(除了重新啟動同一任務),而用戶在任務運行時無法執行,則可以對這些操作使用相同的“檢查當前任務的會話”機制(將其作為視圖裝飾器確實有幫助)。
我相信使用鎖可以在服務器端更輕松地完成此操作,請參見此問題。 用芹菜運行“獨特”任務
如果需要在客戶端完成,可能的方法是像這樣設置cookie
if (typeof $.cookie("running") === "undefined"){
var date = new Date();
var minutes = 20;
date.setTime(date.getTime() + (minutes * 60 * 1000));
$.cookie("running", "true", { expires: date });
}
並在任務完成時刪除
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.