2013-10-01 75 views
1

我在django中長時間計算時遇到了麻煩。由於我公司的白癡,我無法安裝芹菜,所以我必須「重新發明輪子」。
我想在TaskQueue類中進行所有計算,它將所有計算結果存儲在字典「結果」中。另外,我正在嘗試製作「Please Wait」頁面,如果提供的密鑰任務已準備就緒,該頁面將詢問此TaskQueue。
而問題是,結果不知何故消失。
我有一些觀點與長計算。
在字典中存儲HttpResponse

def some_view(request): 
    ... 
    uuid = task_queue.add_task(method_name, params) #method_name(params) returns HttpResponse 
    return redirect('/please_wait/?uuid={0}'.format(uuid)) 

而且PLEASE_WAIT觀點:

def please_wait(request): 
    uuid = request.GET.get('uuid','0') 
    ready = task_queue.task_ready(uuid) 
    if ready: 
     return task_queue.task_result(uuid) 
    elif ready == None: 
     return render_to_response('admin/please_wait.html',{'not_found':True}) 
    else: 
     return render_to_response('admin/please_wait.html',{'not_found':False}) 

而在去年的代碼,我的任務隊列:

class TaskQueue: 
    def __init__(self): 
     self.pool = ThreadPool() 
     self.results = {} 
     self.lock = Lock() 

    def add_task(self, method, params): 
     self.lock.acquire() 
     new_uuid = self.generate_new_uuid() 
     while self.results.has_key(new_uuid): 
      new_uuid = self.generate_new_uuid() 
     self.results[new_uuid] = self.pool.apply_async(func=method, args=params) 
     self.lock.release() 
     return new_uuid 

    def generate_new_uuid(self): 
     return uuid.uuid1().hex[0:8] 

    def task_ready(self, task_id): 
     if self.results.has_key(task_id): 
      return self.results[task_id].ready() 
     else: 
      return None 

    def task_result(self, task_id): 
     if self.task_ready(task_id): 
      return self.results[task_id].get() 
     else: 
      return None 
global task_queue = TaskQueue() 

任務添加後我可以登錄導致提供這幾秒鐘的UUID,和那麼它說這個任務沒有準備好。這是我的日誌:(我輸出task_queue.results)

[INFO] 2013-10-01 16:04:52,782 logger: {'ade5d154': <multiprocessing.pool.ApplyResult object at 0x1989906c>} 
[INFO] 2013-10-01 16:05:05,740 logger: {} 

請幫助我!爲什麼地獄的結果會消失?

UPD:@freakish幫我找到了一些新的信息。這個結果不會永遠消失,如果我會重複嘗試記錄它,它有時會消失。

[INFO] 2013-10-01 16:52:41,743 logger: {} 
[INFO] 2013-10-01 16:52:45,775 logger: {} 
[INFO] 2013-10-01 16:52:48,855 logger: {'ade5d154': <multiprocessing.pool.ApplyResult object at 0x1989906c>} 
+0

你是在開發服務器上還是在生產環境中運行這個? –

+0

@ daniel-roseman我在開發服務器上運行它。 – Geslot

+1

@Geslot我試過你的代碼,它按預期工作。所以會發生以下情況:1)你實際上在某處刪除了鍵2)你正在運行多個Django進程('task_queue'不會在它們之間共享)3)你正在重寫'task_queue':這個'global'標誌是耐人尋味,你在一個函數內部運行這個嗎?也許你多次撥打它? – freakish

回答

3

好的,所以我們確定您正在運行Django的4個進程。在這種情況下,您的隊列將不會在它們之間共享。實際上有兩種可能的解決方案AFAIK:

  1. 使用共享排隊服務器。你可以自己寫(例如參見this entry),但使用適當的(比如Celery)會容易很多(如果你不能說服你的僱主安裝它,那麼就退出這個工作了))。

  2. 使用數據庫在其中存儲結果並讓每個服務器執行計算(通過進程或線程)。它不一定是一個合適的數據庫服務器。例如,您可以使用sqlite3。這是更安全可靠的方式,但效率較低。我認爲這比隊列機制更容易。您只需創建列表:id, state, result。當您創建作業時,用state=processing更新條目,當您完成作業時,用state=doneresult=result(例如JSON字符串)更新條目。這很簡單和可靠(你實際上根本就不需要排隊,除非我缺少一些東西,否則就業順序並不重要)。

你當然不能,除非你泡菜結果使用此功能.ready()用它(你應該儲存這些存儲器內的結果),但是這是一個不必要的開銷。

+0

謝謝,我會試試看。 – Geslot