Edited at

Clockwork Cheat Sheet

More than 5 years have passed since last update.

=====================

Clockworkは定期的な処理が簡単に実装できるライブラリです。

使い方も簡単ですが、せっかくなのでチートシートを作りました。

Clockworkはcronの代替に使えます。RubyなのでDSL記法や便利な関数が使えます。

(Railsで利用するとActionPackなど更に便利なライブラリが使えます。)


Register

定期的に処理する内容をeveryに記述します。

everyは期間、処理(ジョブ)、条件を指定します。

every([period], [job name], [options]) [{job block}]


Period

ジョブを実行する期間(間隔)を指定します。

期間の単位はです。

[数字].[単位のキーワード]で設定します。

キーワードの単数形と複数形はエイリアスです。
(数字が1なら単数形、2以上なら複数形を使うとよいです。)


List

単位
単数形
複数形
Source


second
seconds
period * 1


minute
minutes
period * 60


hour
hours
period * 3600


day
days
period * 86400


week
weeks
period * 604800


Example

every(4.seconds, '4.seconds.job')  # 4秒間隔

every(2.hours, '2.hours.job') # 2時間間隔
every(1.day, '1.day.job') # 1日間隔


Options

ジョブを実行する条件を指定します。

条件にはatifがあります。


at

何時にジョブを実行するか指定します。

'[時]:[分]' で設定します。

(時間は複数の指定ができます。また、曜日を指定できます。)


List

指定
period
at
処理される時間

時分
1.day
'01:30'
1時30分

0省略
1.day
'1:30'
1時30分

毎時
1.hour
'**:30'
毎時30分

複数
1.hour
['12:00', '18:00']
12時と18時

曜日
1.week
'Saturday 12:00'
土曜日の12時


Week day list

曜日は省略を合わせると4パターンあります。

エイリアスなので好きなキーワードを使えます。

曜日
指定1
指定2
指定3
指定4


sunday
Sunday
sun
Sun


monday
Monday
mon
Mon


tuesday
Tuesday
tue
Tue


wednesday
Wednesday
wed
Wed


thursday
Thursday
thu
Thu


friday
Friday
fri
Fri


saturday
Saturday
sat
Sat


Example

every(1.day, 'job', at: '01:30')             # 1時30分

every(1.day, 'job', at: '1:30') # 1時30分
every(1.hour, 'job', at: '**:30') # 毎時30分
every(1.hour, 'job', at: ['12:00', '18:00']) # 12時と18時
every(1.week, 'job', at: 'Saturday 12:00') # 土曜日の12時


Anti-pattern

periodatの組合せに注意が必要です。

例では毎時30分の指定ですが期間が1日間隔なので、Clockworkが12時にスタートすると

初回は12時30分に実行されて、次回は翌日の12時30分に実行されます。

every(1.day, 'job', at: '**:30') # 毎時30分では実行しない!


if

ジョブを実行する条件を指定します。

lambda { |t| [式] } で設定します。

(式に時間が不要なら`|t|`を`|_|`に変更します。)


Example

月初や月末で指定できます。

every(1.day, 'job', at: '9:00', if: lambda { |t| t.day == 1 }) # 月初の9時

every(1.day, 'job', at: '21:00', if: lambda { |t| t.day == Date.new(t.year, t.month, -1).day }) # 月末の21時


Practical

処理の失敗をモニタリングしてアラートを通知することが簡単に実装できます。

(Sidekiqを利用すると非同期処理の実装が簡単です。)

every(1.minute, 'Failure::Worker', if: lambda { |_| Failure.all.count > 0 }) do 

Failure::Worker.perform_async
end


Job

実行するジョブを指定します。

(ジョブはSidekiqなどを利用が必要です。)

every(period, [job name], options) [{job block}] で設定します。

{job block}に記述する方法と[job name]を利用してhandlerに記述する方法があります。


Job block

期間、条件、ジョブをまとめて記述できます。

every(1.second, '1.second.job') do

puts "Running job"
end


handler

期間、条件とジョブを分けて記述できます。

handler do |job|

case job
when '1.second.job'
"Running job"
end
end

every(1.second, '1.second.job')


Example


Practical

Railsの例ですが、環境(開発や本番)に合わせて制御できます。


clock.rb

require_relative '../config/boot'

require_relative '../config/environment'

require 'clockwork'
include Clockwork

case Rails.env
when 'development'
every(1.second, 'seconds.job') do
puts "Running development job"
end
when 'staging'
every(1.minute, 'minutes.job') do
puts "Running staging job"
end
when 'production'
every(1.hour, 'hours.job') do
puts "Running staging job"
end
else # Unknown
every(1.day, 'days.job') do
puts "Running production job"
end
end

# Shared jobs
every(1.week, 'weeks.job') do
puts "Running common job"
end



Anti-pattern

Rubyはマルチスレッドの処理をしないとジョブが期待した時間に実行されません。

例では1秒間隔と10秒間隔のジョブを実行します。しかし、10秒間隔のジョブで

20秒の待ちが発生するので1秒間隔のジョブも20秒待たされます。

every(1.second, '1.second.job') {sleep 0}

every(10.seconds, '10.seconds.job') {sleep 20}


Tips

cronとは違いworkerの引数にオブジェクトを指定できるところがとても便利です。

(もちろんハッシュも使えます。)

every(1.minute, 'Time::Worker') do 

Time::Worker.perform_async(Time.now, {foo: :bar})
end