プログラムを遅延実行させたり、定期実行させるのに便利な Gem です。
遅延実行
遅延実行させたい場合 #after
を使います。以下のように、引数に interval
(seconds) と実行したい内容をブロックで渡します。
timers = Timers::Group.new
puts Time.now.strftime("%M:%S") #=> 23:42
timers.after(5) { puts Time.now.strftime("%M:%S") }
timers.wait #=> 23:47
#wait
はスケジュールされたタイミングまで待って、実行するメソッドです。after
に渡した「5 秒」待って、ブロックが実行されているのがわかります。
また、#now_and_after
メソッドも用意されていて、名前の通り、スケジュールしたタイミングと interval 後に実行されます。
timers = Timers::Group.new
puts Time.now.strftime("%M:%S") #=> 28:40
timers.now_and_after(5) { puts Time.now.strftime("%M:%S") } #=> 28:40
timers.wait #=> 28:45
定期実行
次に、定期実行させたい場合です。
定期実行させる場合は、#every
を使います。
timers = Timers::Group.new
timers.every(2) { puts Time.now.strftime("%M:%S") }
5.times { timers.wait }
#=> 37:21
# 37:23
# 37:25
# 37:27
# 37:29
同じように #now_and_every
が用意されています。
使用例
これだけだと、sleep(interval)
使えばいいじゃん。。。という感じですが、複数だったり、複雑なスケジューリングする場合に便利です。
例えば、(ありえないですが、、、)
「あなたは、ユーザーアクティビティをモニタリングをしていて、 2 秒ごとにアクティビティのデータを Slack にポストして、5 秒ごとにまとめをメールする必要があります。
しかも、Slack とメールに送信したメッセージは、ログとしてサーバーにダウンロードしておく必要があるのですが、メッセージ送信後 1 秒はインターバルを置かないとうまく取得できないことがわかっています」
と言った場合、以下のように書けます。
timers = Timers::Group.new
timers.every(2) {
puts "#{Time.now.strftime('%M:%S')} : post to slack"
timers.after(1) { puts "#{Time.now.strftime('%M:%S')} : download slack" }
}
timers.every(5) {
puts "#{Time.now.strftime('%M:%S')} : send to mail"
timers.after(1) { puts "#{Time.now.strftime('%M:%S')} : download mail" }
}
loop { timers.wait }
# =>
# 32:00 : post to slack
# 32:01 : download slack
# 32:02 : post to slack
# 32:03 : download slack
# 32:03 : send to mail
# 32:04 : post to slack
# 32:04 : download mail
# 32:05 : download slack
# 32:06 : post to slack
# 32:07 : download slack
# 32:08 : post to slack
# 32:08 : send to mail
# 32:09 : download slack
# 32:09 : download mail
# ...
みたいな。
いろいろ組み合わせたいときは便利!