お久しぶりです、菊池です。
途中でイベント記事が数件入ったので、公開が遅くなりましたが前回の続きです。
「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 になってる!
菊池