$shibayu36->blog;

株式会社はてなでエンジニアをしています。プログラミングや読書のことなどについて書いています。

TheSchwartzが次に実行するjobをどう見つけるか

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 にかかれているように、一度に取得してくるジョブ数は$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は意味が無い

などといったことが分かった。