2013-06-29 31 views
1

我將我的站點移植到python/django,其中一個主要練習涉及一組數據,用戶可以在其當地時間安排一個事件,並且它每天都在發生。Django:每天在指定用戶當地時間運行一個進程

目前我有一個cron工作(在另一臺服務器上),每隔5分鐘就打一個方法,看看是否需要安排下一個(比如說)10分鐘。

我保存時間值,併爲每個作業

什麼是做到這一點的最佳方式在用戶的本地時區?

現在我工作的一個函數:

  • 服務器時間轉換到用戶本地時間。
  • 創建本地日期時間對象本地化的「今天」和用戶指定的時間
  • 檢查它是否在用戶警報關閉的10分鐘內。
  • 如果它在23:50-23:59:59之間,並且用戶的設置時間是00:00-00:10 本地化的「今天」是用「明天」的日期創建的。 (例如,如果 爲2分鐘至午夜,用戶希望在 12:01有一個事件,我計算與明天的日期的事件)
  • 我定當它被安排了 last_scheduled場和last_fired場到 確保我不發送倍數。

如果距離現在還不到10分鐘,我會安排一個即將開火的任務(線程,無論什麼)。

這裏的最佳做法並不確定。我應該:
繼續檢查,看看我是否有將來的任務,並安排短期任務?
提前生成我所有的時間(可能一個月一次嗎?)
完成其他操作嗎?
我也在想我總是可以安排「下一個」事件,但我擔心的是,如果說我的服務器脫機了,而我錯過了「下一個」事件,那麼第二天永遠都不會安排。

澄清:

  • 我儲存的時間和每個作業時區(如中午在美國/東部)。
  • 我正在爲DST進行更正,因此在計算UTC時間時,我將utc的當天日期轉換爲當地時間,然後使用它計算增量值。我使用pytz和normalize()來確保我沒有遇到任何不可靠的DST問題。
  • 我確實有最後一次預定時間和最後一次運行時間,以確保我不會執行兩次。

看着下面的解決方案,我想我唯一的其他看法是,如果出於某種原因,我錯過了預定的時間,我的「下一個」永遠不會發生,因爲它是那麼過去。我想我可以做第二個功能來修復任何錯過的警報。

編輯: 所著的Grokking下面的答案後,我想出了以下不太糟糕的情況下:

我有以下字段

  • 上次事件執行時間
  • 最後時間事件安排
  • 下一個事件執行時間
  • 時間和時區

我每當我計算並設置next_run_time:更新事件或觸發事件。 此執行以下操作:

  • 如果它有一個最後的運行時,next_run_time計算,至少2,今後小時(避免DST問題通過添加一些填充)。
  • 如果事件從未運行,在未來的時間表至少15分鐘(避免多個同時時間表)

我的計劃作業執行以下操作:

  1. 檢查有所有事件next_run_time在接下來的15分鐘內,並且目前沒有安排。任何匹配都是預定的。

調度作業:

  • 計劃任務,並將任務如期 「現在」

執行任務時(成功):

  • last_run_time更新爲「現在」
  • next_run_time重新計算

如果任務失敗: - 作業將在未來重新計劃30秒。如果失敗超過閾值(在我的情況下過期3分鐘),任務將中止,next_run_time將在第二天重新計算。這得到記錄,並希望不會發生太大

這似乎大多是工作,因爲我的活動總是(每日),這樣我就可以買得起扔在了時代的一些空隙,以防止有些發毛的問題

回答

2

我因爲那不是我的專業領域,所以我會繼續關注Python/Django的細節。但在一般情況下,你所描述如下(恕我直言)應採取行動的類型的任務調度:

  • 單獨從
  • 時間表定義應該在用戶定義的本地時間執行時間調度定義,幷包含時區標識。
  • 執行時間應以UTC爲單位。
  • 當任務執行時,它應該從計劃中計算下一個執行時間。

讓我們來看一個例子。

  • 用戶說:「每晚在美國東部時間午夜運行」。
  • 我們存儲「每日,00:00,America/New_York」的時間表。
  • 我們計算第一個執行時間爲2013-06-30T04:00:00Z
  • 使用您喜歡的任何機制,在執行時運行作業。如果您定期輪詢需要運行的作業,只需查看時間是否已過(ExecTime < = utcnow)。如果你可以依靠事件系統,定時任務等,那可能會更好。
  • 作業運行時,使用計劃計算下一個執行時間。

爲什麼在當地時間安排?那麼,在東部時間的情況下,由於夏令時間的原因,它將從UTC到-5小時和-4小時之間轉換。如果日程安排嚴格按照UTC進行,那麼在DST過渡之後,您會發現作業運行在用戶認爲是錯誤的時間。

另外,您應該考慮處理故障,重試等。並且您不希望該作業每次執行預定運行超過一次,因此如果您需要某種方法將其標記爲「正在處理中」有多個程序檢查任務。有時您可能需要更復雜的鎖定策略來確保多個工作進程不會執行相同的任務。這有點超出我可以在這裏寫的範圍。

您還應該考慮您希望如何處理由夏令時轉換引起的本地時間歧義。考慮到「後退式」轉換,如果用戶說在「每天晚上1:30」運行,但每年有一個晚上1:30發生兩次,你想要做什麼?如果你什麼都不做,它會在第一次發生時運行 - 這通常是夏令時。用戶可能需要標準時間,所以你可能需要檢查這個。即使你只是在午夜運行,你也不能免除這個決定。有幾個時區在午夜時分(巴西)進行轉換。

如果所有這些聽起來像是太多工作,那麼您可能只想尋找一個已經寫好的作業調度程序。例如,Java上的Quartz或.Net堆棧上的Quartz.Net。我並不直接熟悉它,但Python的搜索結果爲APScheduler,看起來非常相似。

+0

欣賞任何信息在這裏。爲了說明我在當地時間存儲以避免DST問題,並且確實有例如每日00:00紐約。我有一個to_next_utc_time()函數,它給了我下一個運行時間,在now() – Yablargo

+0

之後,我實際上已經在.net端實現了Quartz解決方案。我只是不能證明跳過一些偉大的/便宜的Linux託管。 FWIW,但是我在日常工作中在生產中運行單聲道應用程序,在heroku上單聲道很誘人。感謝Apscheduler鏈接,我想我會在這裏至少將解決方案納入解決方案的一半。 – Yablargo

3

(我會把這個作爲一個評論,但因此不會允許他們對新用戶) 看看還在芹菜,也許這將有助於http://docs.celeryproject.org/en/latest/userguide/tasks.html

+0

謝謝,我會去看看。 – Yablargo

+0

哇,我認爲這正是我正在尋找的。 HTTP://計算器。COM /問題/ 7848512 /芹菜時間表週期性任務啓動-AT-一個特定的時間 – Yablargo

+1

看起來像芹菜會做[有個時區的週期性任務(http://docs.celeryproject.org/en/最新/ userguide/periodic-tasks.html#時區),並與[pytz](http://pytz.sourceforge.net/)集成,所以它也有我的投票。很好找! –

相關問題