TheSchwartzを利用していて、priority周りがどのように機能しているのかよく分からなかったので、軽くコードを読んでみた。
TheSchwartzでジョブを一つ実行する一番単純な手段はTheSchwartz->work_onceを一度実行する部分である。またジョブを実行するための他のいろいろな関数でも結局このwork_onceを利用している。そこでまずはwork_onceから読んでみる。
work_once
https://metacpan.org/source/JFEARN/TheSchwartz-1.12/lib/TheSchwartz.pm#L646
work_onceを見ると、すぐにjobを探していると思われるメソッドが見つかる。work_onceを引数なしで呼ぶことにより、find_job_for_workersが呼ばれ、jobが一つ返ってくるようだ。そこで続いてこのfind_job_for_workersを読んでみる。
find_job_for_workers
https://metacpan.org/source/JFEARN/TheSchwartz-1.12/lib/TheSchwartz.pm#L328
find_job_for_workersで重要そうな部分は
- https://metacpan.org/source/JFEARN/TheSchwartz-1.12/lib/TheSchwartz.pm#L327
- https://metacpan.org/source/JFEARN/TheSchwartz-1.12/lib/TheSchwartz.pm#L329
- https://metacpan.org/source/JFEARN/TheSchwartz-1.12/lib/TheSchwartz.pm#L380
辺り。
https://metacpan.org/source/JFEARN/TheSchwartz-1.12/lib/TheSchwartz.pm#L327 にかかれているように、一度に取得してくるジョブ数は$client->batch_size分であり、これはデフォルトでは50に設定されている。
またhttps://metacpan.org/source/JFEARN/TheSchwartz-1.12/lib/TheSchwartz.pm#L329 にあるように、prioritizeというオプションが有効であれば、priority -> jobidの順でsortしてDBから取得してくるという事がわかる。prioritizeが有効でなければjobidの順でDBから取得してくる。なので、https://metacpan.org/pod/TheSchwartz に書かれているprioritizeというオプションが有効でないと、いくらjobにpriorityを指定しても意味が無いという事がわかる。
最後にhttps://metacpan.org/source/JFEARN/TheSchwartz-1.12/lib/TheSchwartz.pm#L380 から、$client->_grab_a_jobで、取得してきたjobから実行するjobを選んでいることが分かる。なので次は_grab_a_jobを読んでみる。
_grab_a_job
https://metacpan.org/source/JFEARN/TheSchwartz-1.12/lib/TheSchwartz.pm#L397
_grab_a_jobを見ると、まず最初に渡された引数をshuffleしている。つまり先ほど取ってきた50個ほどのジョブをshuffleしている。その後、順にjobを見ていって他のclientに取られていないjobを返すようにしている。基本的にはそれぞれのclientで別々にshuffleされているため、大体は一番最初のjobが実行されるように見える。
結論
- prioritizeが有効であれば、priorityが高いものを優先してDBから取得してきてくれる
- ただし、DBから取得してきたあとに、実行するjobを決めるときにはshuffleするため、priorityが高いものが常に先に実行されるわけではない
- 極論を言うと、priorityが低いjobが1000個くらい入っていて、priorityが高いjobが3個という状況の時、1つジョブを選ぶ時にpriorityが高いものは3/50の確率でしか選ばれない
- またDBから取得する際のデフォルトのlimitは50なので、ある程度ジョブがはけていて50個以下しかない場合は、priorityは意味が無い
などといったことが分かった。