ちょっとしたワークフローエンジンを作るときは Rake で十分だと思う
Ruby なら特に。
Ruby 以外でも、使えるケースはありそう。
Rake には次のような機能が有る。
- タスクの依存関係定義
- 並列実行
- 別のタスクの呼び出し
また、タスクを記述する Rakefile 内では Ruby の文法が使えるので、特に外部の gem を使わなくても、任意のタスクにアドオンで次のような機能を付加できる。
- リトライ
- 終了処理
- 繰り返し
- 複数のタスクを並列実行
以下にサンプルの Rakefile を示す。
※ここでは parallel を使っているが、同じことを parallel を使わずに記述することもできる。
require 'parallel' def invoke(task) Rake::Task[task].invoke end def execute(task) Rake::Task[task].execute end def parallel(*tasks) Parallel.each(tasks) do |task| invoke(task) end end task :all do invoke :prepare begin invoke :start begin invoke :main parallel :job_foo, :job_bar 3.times { |i| p i; execute :job_to_iterate } invoke :finalize end ensure invoke :clean_up end end task default: :all task :prepare do p :prepare end task :start do p :start end task :main do p :main end task :job_foo do p :job_foo end task :job_bar do p :job_bar end task :job_to_iterate do p :job_to_iterate end task :finalize do p :finalize end task :clean_up do p :clean_up end
実行すると、次のようになる。
% rake --trace ** Invoke default (first_time) ** Invoke all (first_time) ** Execute all ** Invoke prepare (first_time) ** Execute prepare :prepare ** Invoke start (first_time) ** Execute start :start ** Invoke main (first_time) ** Execute main :main ** Invoke job_foo (first_time) ** Invoke job_bar (first_time) ** Execute job_foo ** Execute job_bar :job_foo :job_bar 0 ** Execute job_to_iterate :job_to_iterate 1 ** Execute job_to_iterate :job_to_iterate 2 ** Execute job_to_iterate :job_to_iterate ** Invoke finalize (first_time) ** Execute finalize :finalize ** Invoke clean_up (first_time) ** Execute clean_up :clean_up ** Execute default
この Rakefile を見れば、タスクのワークフロー制御がどう記述されているか、プログラマならすぐ理解できるだろう。
今回の :all
のような、ユーザが実行するワークフローを記述したタスクは、外部から直接利用されるメインのタスクと言えるだろう。
メインタスクから呼び出される個々のタスクは、サブタスクということになる。
メインタスク内では、ワークフロー制御と、サブタスクの呼び出しのみを記述すべきだ。
細かな内部ロジックはサブタスク側に記述することで、 Rakefile や実装されているワークフローを見通しよく保つことができるだろうと期待される。