「Sidekiq + SidekiqUniqueJobs で前回の試作コードの sync_cache! を非同期にまとめて実行するようにしてみよう」の続編

あけましておめでとうございます。
お久しぶりです、菊池です。

途中でイベント記事が数件入ったので、公開が遅くなりましたが前回の続きです。
Sidekiq + SidekiqUniqueJobs で前回の試作コードの sync_cache! を非同期にまとめて実行するようにしてみよう」で試作してみたコードを紹介したいと思います。

まずは redis-object のカウンター値をデータベースに同期する Sidekiq Worker です。

app/workers/redis_counter_cache_worker.rb

短い!試作コードなので例外処理とかやってませんので、必要に応じて入れて下さいね!

この Sidekiq Worker はクラス名とIDを受け取って、オブジェクトを find して、前に作った sync_cache! を呼び出すだけの簡単な実装になってます。

続いて「Rails4 の counter_cache のカウントを redis-objects でカウントしてみた時の試作コード」で作成した試作コードを少々修正して、カンター値が変更されたタイミングでこの Sidekiq Worker のジョブが投入されるようにします。

app/models/concerns/redis_counter_cache.rb

修正点は二箇所で
  • async_cache! メソッドの追加
  • update_counters メソッドの中に async_cache! の呼び出しを追加
です。

今回改めて動作確認したところ、sync_cache! 内に self.class.readonly_attributes.delete(dest) の追加が必要になることに気がついたので、追加してあります。この件につきましては別途記事にする予定。

 async_cache! 内で呼び出している perform_in メソッドの第一引数の 30 は、ジョブの実行を 30 秒遅らせる指定になっています。ここではとりあえず 30 にしているので、必要に応じて調整して下さい。

ということで準備ができたので動作確認してみましょう。

まずは Sidekiq を起動します。アチョー!

Rails console でデータを登録してみましょう。上手く動くでしょうか。

Sidekiq のログを見ると 3 回 Order を追加したのに、ジョブの実行は 1 回になっています。

最後の 2 行でジョブが 1 回だけ実行されたのが確認できます。

2014-12-05T03:27:22.588Z 23109 TID-ou4kx1ud0 RedisCounterCacheWorker JID-d09b98491952de2f7d526d32 INFO: start
2014-12-05T03:27:22.606Z 23109 TID-ou4kx1ud0 RedisCounterCacheWorker JID-d09b98491952de2f7d526d32 INFO: done: 0.019 sec


ということで、やりたかった

更新があったカウンター値だけ一定期間毎にデーターベースに更新をかけたい

という動作が実現出来たんじゃないでしょうか。
めでたしめでたし。

あ、ログの時間が UTC になってる!

菊池