Solid Queue 是一個基於資料庫的 Active Job 佇列後端,在設計時考慮到了簡單性和效能。
除了常規作業排隊和處理之外,Solid Queue 還支援延遲作業、並發控制、重複作業、暫停佇列、每個作業的數字優先權、按佇列順序排列的優先權以及批次排隊(活動作業的perform_all_later
的enqueue_all
)。
Solid Queue 可與 MySQL、PostgreSQL 或 SQLite 等 SQL 資料庫一起使用,並且它利用FOR UPDATE SKIP LOCKED
子句(如果可用)來避免在輪詢作業時阻塞和等待鎖定。它依賴 Active Job 進行重試、丟棄、錯誤處理、序列化或延遲,並且與 Ruby on Rails 的多執行緒相容。
Solid Queue 在新的 Rails 8 應用程式中預設為配置。但如果您使用的是早期版本,則可以按照以下步驟手動新增:
bundle add solid_queue
bin/rails solid_queue:install
這會將 Solid Queue 配置為生產活動作業後端,建立設定檔config/queue.yml
和config/recurring.yml
,並建立db/queue_schema.rb
。它還將創建一個bin/jobs
可執行包裝器,您可以使用它來啟動 Solid Queue。
完成此操作後,您必須在config/database.yml
中新增佇列資料庫的設定。如果您使用 SQLite,它將如下所示:
production :
primary :
<< : *default
database : storage/production.sqlite3
queue :
<< : *default
database : storage/production_queue.sqlite3
migrations_paths : db/queue_migrate
……或如果您使用 MySQL/PostgreSQL/Trilogy:
production :
primary : &primary_production
<< : *default
database : app_production
username : app
password : <%= ENV["APP_DATABASE_PASSWORD"] %>
queue :
<< : *primary_production
database : app_production_queue
migrations_paths : db/queue_migrate
注意:呼叫bin/rails solid_queue:install
會自動新增config.solid_queue.connects_to = { database: { writing: :queue } }
到config/environments/production.rb
,因此不需要額外的設定(儘管你必須確保您使用database.yml
中的queue
名稱來符合!但是,如果您想在不同的環境(例如登台甚至開發)中使用 Solid Queue,則必須手動將該config.solid_queue.connects_to
行新增至對應的環境檔案中。而且,與往常一樣,請確保您在config/database.yml
中使用的資料庫名稱與您在config.solid_queue.connects_to
中使用的名稱相符。
然後在生產中運行db:prepare
以確保創建資料庫並載入架構。
現在您已準備好透過在正在執行工作的伺服器上執行bin/jobs
來開始處理作業。這將開始使用預設配置處理所有佇列中的作業。請參閱下文以了解有關配置 Solid Queue 的更多資訊。
對於小型項目,您可以在與網頁伺服器相同的電腦上執行 Solid Queue。當您準備好擴充時,Solid Queue 支援開箱即用的水平擴充。您可以在與 Web 伺服器不同的伺服器上執行 Solid Queue,甚至可以同時在多台電腦上執行bin/jobs
。根據配置,您可以指定某些機器僅執行排程器或僅執行工作人員。有關詳細信息,請參閱配置部分。
注意:未來對架構的變更將以定期遷移的形式出現。
建議在單獨的資料庫中執行 Solid Queue,但也可以為應用程式和佇列使用一個資料庫。只需按照以下步驟操作:
db/queue_schema.rb
的內容複製到普通遷移中,並刪除db/queue_schema.rb
production.rb
中刪除config.solid_queue.connects_to
bin/jobs
您不會有多個資料庫,因此database.yml
不需要有主資料庫和佇列資料庫。
如果您打算透過一次切換一項作業來逐步採用 Solid Queue,則可以將config.active_job.queue_adapter
設定保留為舊後端,然後直接在要移動的作業中設定queue_adapter
:
# app/jobs/my_job.rb
class MyJob < ApplicationJob
self . queue_adapter = :solid_queue
# ...
end
Solid Queue 旨在與 MySQL 8+ 或 PostgreSQL 9.5+ 一起使用時實現最高吞吐量,因為它們支援FOR UPDATE SKIP LOCKED
。您可以將其與舊版本一起使用,但在這種情況下,如果為同一佇列運行多個工作線程,則可能會遇到鎖定等待。您也可以在較小的應用程式上將其與 SQLite 一起使用。
Solid Queue 中有幾種類型的參與者:
solid_queue_ready_executions
表。solid_queue_scheduled_executions
表移動到solid_queue_ready_executions
表,以便工作人員可以拾取它們。最重要的是,他們做一些與並發控制相關的維護工作。Solid Queue 的主管將為每個受監督的工作人員/調度程序/調度程序分叉一個單獨的進程。
預設情況下,Solid Queue 會嘗試在config/queue.yml
下尋找您的配置,但您可以使用環境變數SOLID_QUEUE_CONFIG
或使用bin/jobs
的-c/--config_file
選項設定不同的路徑,如下所示:
bin/jobs -c config/calendar.yml
此配置如下所示:
production :
dispatchers :
- polling_interval : 1
batch_size : 500
concurrency_maintenance_interval : 300
workers :
- queues : " * "
threads : 3
polling_interval : 2
- queues : [ real_time, background ]
threads : 5
polling_interval : 0.1
processes : 3
一切都是可選的。如果未提供任何配置,Solid Queue 將使用預設設定來執行一名排程器和一名工作人員。如果您只想執行排程器或工作人員,則只需在組態中單獨包含該部分即可。例如,使用以下配置:
production :
dispatchers :
- polling_interval : 1
batch_size : 500
concurrency_maintenance_interval : 300
主管將運行 1 名調度員,沒有工人。
以下是不同選項的概述:
polling_interval
:工作人員和排程器在檢查更多作業之前等待的時間間隔(以秒為單位)。對於調度員,該時間預設為1
秒;對於工作人員,該時間預設為0.1
秒。
batch_size
:排程器將依此大小批次排程作業。預設值為 500。
concurrency_maintenance_interval
:調度程式在檢查可以解除阻塞的阻塞作業之前等待的時間間隔(以秒為單位)。閱讀有關並發控制的更多資訊以了解有關此設定的更多資訊。預設為600
秒。
queues
:工作人員將從中選擇作業的佇列清單。您可以使用*
來指示所有隊列(這也是預設值,如果您省略它,您將得到的行為)。您可以提供單一佇列或作為陣列的佇列清單。作業將從這些佇列中按順序輪詢,因此,例如,使用[ real_time, background ]
,不會從background
取得任何作業,除非real_time
中沒有更多作業在等待。您也可以提供帶有通配符的前綴來匹配以前綴開頭的佇列。例如:
staging :
workers :
- queues : staging*
threads : 3
polling_interval : 5
這將建立一個工作人員,從staging
開始的所有佇列中取得作業。通配符*
只能單獨使用或出現在佇列名稱的末端;您不能指定佇列名稱,例如*_some_queue
。這些將被忽略。
最後,您可以將前綴與確切的名稱組合起來,例如[ staging*, background ]
,並且與順序有關的行為將與僅使用確切名稱時相同。
請查看以下部分,以了解佇列順序如何與優先權結合使用,以及為每個工作執行緒指定佇列的方式可能會如何影響效能。
執行threads
:這是每個工作執行緒必須執行作業的執行緒池的最大大小。每個工作人員最多將從其佇列中取得此數量的作業,並將它們發佈到執行緒池中執行。預設情況下,這是3
。只有工人有此設定。
processes
:這是主管根據給定的設定分叉的工作進程的數量。預設情況下,這是1
,只是一個進程。如果您想要將多個 CPU 核心專用於一個或多個具有相同配置的佇列,則此設定非常有用。只有工人有此設定。
concurrency_maintenance
:調度程式是否執行並發維護工作。預設情況下這是true
,如果您不使用任何並發控制並想要停用它,或者如果您運行多個調度程序並希望其中一些調度程序只調度作業而不執行任何其他操作,那麼它會很有用。
如上所述,如果您為工作人員指定佇列列表,這些佇列將按照給定的順序進行輪詢,例如對於列表real_time,background
,不會從background
取得任何作業,除非沒有更多作業在等待real_time
。
Active Job 在排隊作業時也支援正整數優先權。在Solid Queue中,值越小,優先權越高。預設值為0
。
當您在同一佇列中執行具有不同重要性或緊急程度的作業時,這非常有用。在同一個佇列中,作業將按優先權順序選取,但在佇列清單中,佇列順序優先,因此在前面的real_time,background
範例中, real_time
佇列中的作業會先於background
作業選取佇列,即使在背景background
列中的那些設定了更高的優先權(較小的值)。
我們建議不要將佇列順序與優先權混合,而是選擇其中之一,因為這將使作業執行順序對您來說更加簡單。
為了保持輪詢效能並確保始終使用覆蓋索引,Solid Queue 僅執行兩種類型的輪詢查詢:
-- No filtering by queue
SELECT job_id
FROM solid_queue_ready_executions
ORDER BY priority ASC , job_id ASC
LIMIT ?
FOR UPDATE SKIP LOCKED;
-- Filtering by a single queue
SELECT job_id
FROM solid_queue_ready_executions
WHERE queue_name = ?
ORDER BY priority ASC , job_id ASC
LIMIT ?
FOR UPDATE SKIP LOCKED;
當您指定時,請使用第一個(不按隊列過濾)
queues : *
並且沒有任何隊列暫停,因為我們要定位所有隊列。
在其他情況下,我們需要有一個隊列列表來按順序進行過濾,因為我們一次只能按一個隊列進行過濾,以確保我們使用索引進行排序。這意味著如果您將隊列指定為:
queues : beta*
我們需要先取得與該前綴相符的所有現有隊列的列表,查詢如下所示:
SELECT DISTINCT (queue_name)
FROM solid_queue_ready_executions
WHERE queue_name LIKE ' beta% ' ;
由於一種稱為「鬆散索引掃描」的技術,這種針對索引中最左側列的DISTINCT
查詢可以在 MySQL 中非常快速地執行。然而,PostgreSQL 和 SQLite 沒有實現這種技術,這意味著如果您的solid_queue_ready_executions
表非常大,因為您的佇列變得非常深,則該查詢將會變慢。通常,您的solid_queue_ready_executions
表會很小,但這種情況也有可能發生。
與使用前綴類似,如果您暫停了佇列,也會發生相同的情況,因為我們需要使用以下查詢來取得所有佇列的列表
SELECT DISTINCT (queue_name)
FROM solid_queue_ready_executions
然後刪除暫停的。一般來說,暫停應該是罕見的,在特殊情況下使用,而且時間很短。如果您不想再處理佇列中的作業,最好的方法是將其從佇列清單中刪除。
總而言之,如果您想確保輪詢的最佳效能,最好的方法是始終為它們指定確切的名稱,並且不要暫停任何佇列。
這樣做:
queues : background, backend
而不是這個:
queues : back*
Solid Queue 中的工作執行緒使用執行緒池在多個執行緒中執行工作,可透過上面的執行threads
參數進行設定。除此之外,並行性可以透過一台機器上的多個進程(可透過不同的工作進程或上面的processes
參數進行配置)或透過水平擴展來實現。
主管負責管理這些流程,並回應以下訊號:
TERM
、 INT
:開始優雅終止。主管將向其受監督進程發送TERM
訊號,並且它將等待SolidQueue.shutdown_timeout
時間,直到它們完成。如果那時任何受監督的進程仍然存在,它將向它們發送QUIT
訊號以指示它們必須退出。QUIT
:開始立即終止。監督者將向其監督的進程發送QUIT
訊號,使它們立即退出。當收到QUIT
訊號時,如果工作人員仍有正在進行的作業,則在取消註冊程序時,這些作業將會回到佇列。
如果進程在退出之前沒有機會進行清理(例如,如果有人在某處拉動電纜),則執行中的作業可能仍由執行它們的進程佔用。進程發送心跳,主管檢查並修剪心跳過期的進程,這會將任何已聲明的作業釋放回其佇列。您可以配置心跳頻率和閾值以將進程視為死亡。請參閱下面的部分以了解這一點。
您可以透過config/application.rb
或config/environments/production.rb
設定檔中的config.solid_queue.connects_to
選項來設定 Solid Queue 所使用的資料庫。預設情況下,使用稱為queue
單一資料庫進行寫入和讀取,以符合您在安裝過程中設定的資料庫配置。
此處可以使用適用於多個資料庫的 Active Record 的所有選項。
在 Solid 隊列中,您可以連接到主管生活中的兩個不同點:
start
:在supervisor完成啟動之後,在fork工人和調度程序之前。stop
:收到訊號( TERM
、 INT
或QUIT
)後,在開始正常或立即關閉前。並分為工人生活中的兩個不同點:
worker_start
:在工作進程完成啟動之後和開始輪詢循環之前。worker_stop
:在收到訊號( TERM
、 INT
或QUIT
)之後,在開始正常或立即關閉(即exit!
)之前。您可以使用以下帶有區塊的方法來執行此操作:
SolidQueue . on_start
SolidQueue . on_stop
SolidQueue . on_worker_start
SolidQueue . on_worker_stop
例如:
SolidQueue . on_start { start_metrics_server }
SolidQueue . on_stop { stop_metrics_server }
可以多次呼叫這些函數來新增多個鉤子,但需要在 Solid Queue 啟動之前進行。初始化程序將是執行此操作的好地方。
注意:本節中的設定應在config/application.rb
或環境配置中設置,如下所示: config.solid_queue.silence_polling = true
您也可以設定幾個控制 Solid Queue 運作方式的設定:
logger
:您希望 Solid Queue 使用的記錄器。預設為應用程式記錄器。
app_executor
:用於包裝非同步操作的Rails執行器,預設為app執行器
on_thread_error
:當 Solid Queue 執行緒中出現錯誤(將引發的例外作為參數)時要呼叫的自訂 lambda/Proc。預設為
-> ( exception ) { Rails . error . report ( exception , handled : false ) }
這不用於作業執行上引發的錯誤。作業中發生的錯誤由 Active Job 的retry_on
或discard_on
處理,最終將導致作業失敗。這是針對 Solid Queue 本身所發生的錯誤。
use_skip_locked
:執行鎖定讀取時是否使用FOR UPDATE SKIP LOCKED
。將來會自動檢測到這一點,目前,如果您的資料庫不支援它,您只需將其設為false
即可。對於 MySQL,版本 < 8,對於 PostgreSQL,版本 < 9.5。如果您使用 SQLite,這不會產生任何影響,因為寫入是連續的。
process_heartbeat_interval
:所有行程將遵循的心跳間隔 - 預設為 60 秒。
process_alive_threshold
:進程在最後一次心跳後被視為死亡的等待時間 - 預設為 5 分鐘。
shutdown_timeout
:管理程式在向受監督TERM
發送QUIT
版本請求立即終止之前將等待的時間,預設為 5 秒。
silence_polling
:是否靜默輪詢工作人員和調度程式時發出的 Active Record 日誌 - 預設為true
。
supervisor_pidfile
:主管在啟動時將建立的 pid 檔案的路徑,以防止在同一主機上執行多個主管,或萬一您想將其用於執行狀況檢查。預設情況下它nil
。
preserve_finished_jobs
:是否將已完成的作業保留在solid_queue_jobs
表中 - 預設為true
。
clear_finished_jobs_after
:保留已完成作業的時間段(如果preserve_finished_jobs
為true),預設為1天。注意:目前,無法自動清理已完成的作業。您需要透過定期呼叫SolidQueue::Job.clear_finished_in_batches
來完成此操作,但這將在不久的將來自動發生。
default_concurrency_control_period
:用作並發控制中duration
參數預設值的值。預設為 3 分鐘。
對於將作業排隊時發生的任何 Active Record 錯誤,Solid Queue 都會引發SolidQueue::Job::EnqueueError
。不引發ActiveJob::EnqueueError
的原因是,此錯誤由 Active Job 處理,導致perform_later
回傳false
並設定job.enqueue_error
,將作業產生一個需要傳遞給perform_later
區塊。這對於您自己的作業非常有效,但對於 Rails 或其他 gem 排隊的作業(例如Turbo::Streams::BroadcastJob
或ActiveStorage::AnalyzeJob
來說,失敗很難處理,因為您無法控制對perform_later
呼叫在那種情況下。
在重複任務的情況下,如果在排隊與該任務相對應的作業時引發此類錯誤,它將被處理和記錄,但不會冒泡。
Solid Queue 透過並發控制擴展了 Active Job,讓您可以限制可以同時執行的特定類型或具有特定參數的作業數量。以這種方式限制時,作業將被阻止運行,並且它們將保持阻塞狀態,直到另一個作業完成並取消阻止它們,或在設定的到期時間(並發限制的持續時間)過去之後。工作永遠不會被丟棄或遺失,只會被阻止。
class MyJob < ApplicationJob
limits_concurrency to : max_concurrent_executions , key : -> ( arg1 , arg2 , ** ) { ... } , duration : max_interval_to_guarantee_concurrency_limit , group : concurrency_group
# ...
key
是唯一必需的參數,它可以是符號、字串或流程,用於接收作業參數作為參數,並用於識別需要限制在一起的作業。如果程序傳回 Active Record 記錄,則將根據其類別名稱和id
建立鍵。to
預設為1
。duration
預設為SolidQueue.default_concurrency_control_period
,本身預設為3 minutes
,但您也可以配置。group
用來控制不同作業類別的並發性。它預設為作業類別名稱。當作業包含這些控制時,我們將確保最多會同時執行產生相同key
的作業數量(表示to
),並且這種保證將持續每個排隊作業的duration
。請注意,不能保證執行順序,只能保證同時執行的作業(重疊)。
並發限制在排隊時使用信號量的概念,工作原理如下:當作業排隊時,我們檢查它是否指定了並發控制。如果是,我們檢查信號量中計算出的並發鍵。如果信號量打開,我們聲明它並將作業設定為準備就緒。就緒意味著工作人員可以拿起它來執行。當作業完成執行時(無論成功或不成功,導致執行失敗),我們都會向信號量發出訊號,並嘗試使用相同的金鑰(如果有)解鎖下一個作業。解除下一個作業的阻斷並不意味著立即執行該作業,而是將其從阻塞狀態轉移到就緒狀態。由於可能發生某些情況,阻止第一個作業釋放信號量並解鎖下一個作業(例如,有人拔掉工作執行緒運行的機器的插頭),因此我們將duration
作為故障保護。被阻止超過持續時間的作業是要被釋放的候選作業,但只有並發規則允許的數量,因為每個作業都需要經過信號量舞蹈檢查。這意味著duration
實際上與排隊或正在執行的作業無關,而是與阻塞等待的作業有關。
例如:
class DeliverAnnouncementToContactJob < ApplicationJob
limits_concurrency to : 2 , key : -> ( contact ) { contact . account } , duration : 5 . minutes
def perform ( contact )
# ...
其中contact
account
是ActiveRecord
記錄。在這種情況下,我們將確保同一帳戶最多同時執行兩個DeliverAnnouncementToContact
類型的作業。如果出於任何原因,其中一個作業花費的時間超過5 分鐘,或者在獲取並發鎖後5 分鐘內未釋放其並發鎖(向信號量發出信號),則具有相同密鑰的新作業可能會獲得該鎖。
讓我們來看另一個使用group
例子:
class Box :: MovePostingsByContactToDesignatedBoxJob < ApplicationJob
limits_concurrency key : -> ( contact ) { contact } , duration : 15 . minutes , group : "ContactActions"
def perform ( contact )
# ...
class Bundle :: RebundlePostingsJob < ApplicationJob
limits_concurrency key : -> ( bundle ) { bundle . contact } , duration : 15 . minutes , group : "ContactActions"
def perform ( bundle )
# ...
在這種情況下,如果我們有一個Box::MovePostingsByContactToDesignatedBoxJob
作業為 id 為123
聯絡人記錄排隊,並且另一個Bundle::RebundlePostingsJob
作業同時為引用聯絡人123
捆綁記錄排隊,則只允許其中一個繼續進行。另一個將保持阻塞狀態,直到第一個完成(或 15 分鐘過去,無論先發生什麼)。
請注意, duration
設定間接取決於您為排程器設定的concurrency_maintenance_interval
值,因為這將是檢查和解除封鎖的阻塞作業的頻率。一般來說,您應該以一種方式設定duration
,以便所有作業都能在該持續時間內順利完成,並將並發維護任務視為萬一出現問題的故障保護。
作業依優先權順序解除阻塞,但解除阻塞作業時不考慮佇列順序。這意味著,如果您有一組共享並發群組但位於不同佇列中的作業,或者您在不同佇列中排隊的相同類別作業,則在解除阻塞時不會考慮您為工作執行緒設定的佇列順序那些。原因是,執行的作業會解鎖下一個作業,而且作業本身不知道特定工作執行緒的佇列順序(甚至可以有具有不同佇列順序的不同工作執行緒),它只能知道優先權。一旦被封鎖的作業被解除封鎖並可供輪詢,它們將被工作人員按照其佇列順序擷取。
最後,自動或手動重試的失敗作業的工作方式與排隊的新作業相同:它們進入佇列以獲取開啟的信號量,並且每當它們獲取信號量時,它們就會運行。他們過去是否已經獲得了開放的信號量並不重要。
Solid Queue 不包含任何自動重試機制,它依賴 Active Job 來實現此目的。失敗的作業將保留在系統中,並為其建立失敗的執行( solid_queue_failed_executions
表中的一筆記錄)。作業將保留在那裡,直到手動丟棄或重新排隊。您可以在控制台中執行此操作,如下所示:
failed_execution = SolidQueue :: FailedExecution . find ( ... ) # Find the failed execution related to your job
failed_execution . error # inspect the error
failed_execution . retry # This will re-enqueue the job as if it was enqueued for the first time
failed_execution . discard # This will delete the job from the system
但是,我們建議您查看mission_control-jobs,這是一個儀表板,您可以在其中檢查並重試/放棄失敗的作業。
一些與 Rails 整合的錯誤追蹤服務(例如 Sentry 或 Rollbar)會掛鉤到 Active Job 並自動報告作業執行期間發生的未處理錯誤。但是,如果您的錯誤追蹤系統沒有,或者您需要一些自訂報告,您可以自己連接到 Active Job。一種可能的方法是:
# application_job.rb
class ApplicationJob < ActiveJob :: Base
rescue_from ( Exception ) do | exception |
Rails . error . report ( exception )
raise exception
end
end
請注意,您也必須在ActionMailer::MailDeliveryJob
上複製上述邏輯。這是因為ActionMailer
不繼承自ApplicationJob
,而是使用繼承自ActiveJob::Base
ActionMailer::MailDeliveryJob
。
# application_mailer.rb
class ApplicationMailer < ActionMailer :: Base
ActionMailer :: MailDeliveryJob . rescue_from ( Exception ) do | exception |
Rails . error . report ( exception )
raise exception
end
end
如果您想將 Solid Queue 的管理程式與 Puma 一起運行並讓 Puma 進行監控和管理,我們提供了一個 Puma 外掛程式。你只需要添加
plugin :solid_queue
到你的puma.rb
配置。
因為這可能非常棘手,而且很多人不需要擔心它,所以預設情況下,Solid Queue 配置在與主應用程式不同的資料庫中,由於 Active Job 的內建功能,作業排隊會被推遲,直到提交任何正在進行的事務為止。這意味著即使您在與應用程式相同的資料庫中執行 Solid Queue,您也無法利用這種事務完整性。
如果您想要變更此設置,可以將config.active_job.enqueue_after_transaction_commit
設定為never
。您也可以根據每個作業進行設定。
如果您將其設為never
但仍想確保不會無意中影響事務完整性,則可以確保:
依賴特定資料的作業始終在after_commit
回呼上排隊,或從您確定作業將使用的任何資料在作業排隊之前已提交到資料庫的位置排隊。
或者,您為 Solid Queue 配置不同的資料庫,即使它與您的應用程式相同,也確保處理請求或為您的應用程式執行作業的執行緒上的不同連接將用於對作業進行排隊。例如:
class ApplicationRecord < ActiveRecord :: Base
self . abstract_class = true
connects_to database : { writing : :primary , reading : :replica }
config . solid_queue . connects_to = { database : { writing : :primary , reading : :replica } }
Solid Queue 支援定義在未來特定時間執行的重複任務,就像 cron 作業一樣定期執行。它們由調度程序進程管理,並在它們自己的配置檔案中定義。預設情況下,該檔案位於config/recurring.yml
中,但您可以使用環境變數SOLID_QUEUE_RECURRING_SCHEDULE
或使用bin/jobs
的--recurring_schedule_file
選項來設定不同的路徑,如下所示:
bin/jobs --recurring_schedule_file=config/schedule.yml
配置本身如下所示:
production :
a_periodic_job :
class : MyJob
args : [ 42, { status: "custom_status" } ]
schedule : every second
a_cleanup_task :
command : " DeletedStuff.clear_all "
schedule : every day at 9am
任務被指定為雜湊/字典,其中鍵將是任務內部的鍵。每個任務需要有一個class
,它將是要排隊的作業類,或者一個command
,它將在作業 ( SolidQueue::RecurringJob
) 的上下文中進行評估,該作業將根據其調度進行排隊,在solid_queue_recurring
隊列。
每個任務還需要有一個時間表,該時間表使用 Fugit 進行解析,因此它接受 Fugit 作為 cron 接受的任何內容。您可以選擇為每個任務提供以下內容:
args
:要傳遞給作業的參數,作為單一參數、雜湊或參數數組,也可以包含 kwargs 作為數組中的最後一個元素。上面範例配置中的作業每秒都會排隊如下:
MyJob . perform_later ( 42 , status : "custom_status" )
queue
:將作業排隊時使用的不同佇列。如果沒有,則為作業類別設定佇列。
priority
:將作業排隊時使用的數字優先權值。
任務由調度程序在相應的時間排隊,每個任務都會調度下一個任務。這很大程度上受到 GoodJob 所做工作的啟發。
可以使用相同的recurring_tasks
配置運行多個調度程序,例如,如果您有多個伺服器用於冗餘,並且您在其中多個伺服器中運行scheduler
。為了避免同時將重複任務排隊,會在作業排隊時在相同交易中建立新的solid_queue_recurring_executions
表中的項目。該表在task_key
和run_at
上有唯一索引,確保每次每個任務僅建立一個條目。只有當您將preserve_finished_jobs
設為true
(預設值)時,這才有效,並且只要您保留作業,保證就適用。
注意:支援單一循環計劃,因此您可以讓多個計劃程序使用相同的計劃,但不能讓多個計劃程序使用不同的配置。
最後,可以設定 Solid Queue 不處理的作業。也就是說,您可以在您的應用程式中進行這樣的工作:
class MyResqueJob < ApplicationJob
self . queue_adapter = :resque
def perform ( arg )
# ..
end
end
您仍然可以在 Solid Queue 中進行設定:
my_periodic_resque_job :
class : MyResqueJob
args : 22
schedule : " */5 * * * * "
並且該作業將透過perform_later
入隊,因此它將在 Resque 中運行。但是,在這種情況下,我們不會追蹤它的任何solid_queue_recurring_execution
記錄,並且不能保證該作業每次僅入隊一次。
Solid Queue 的靈感來自於 resque 和 GoodJob。我們建議您查看這些項目,因為它們是很好的例子,我們從中學到了很多東西。
該 gem 根據 MIT 授權條款作為開源提供。