【Rails7】sidekiq-schedulerで定期的にジョブを実行する
Rails7で個人開発しているスケジュール通知アプリ(下記/もしよかったら使ってみてください!)で、sidekiq-schedulerというgemを導入してバックグラウンドで定期的にジョブを実行する環境を作りました。そのやり方の備忘録です。
環境
アプリは以下の環境で作成しています。
- macOS 11.6.2
- Ruby 3.1.2
- Rails 7.0.3
- PostgreSQL 14.4
下準備
RailsアプリにSidekiqを導入し、Redisと接続します。下記の記事で、開発環境での環境構築手順をまとめました。
本番環境にはHerokuのFreeプランを選び、下記の記事を参考にしてデプロイしました。
今回作成するジョブについて
HerokuのFreeプランで運用しているアプリは、30分以上アクセスがないとスリープ状態になってしまいます。
アプリがスリープ状態になると、次にユーザーがアクセスした際の読み込みが非常に遅くなり、ユーザー体験を損ねてしまいます。
そこで、アプリへのアクセスを発生させるジョブを作成し、そのジョブを30分以内の間隔で定期的に実行するようにします。
まあ、HerokuのFreeプランは2022年11月に廃止されてしまうので、このジョブが活きるのもそこまでの話ではあるのですが……。
sidekiq-schedulerを導入する
sidekiq-schedulerはSidekiqの拡張gemで、cronのようにジョブを定期的に実行してくれます。GitHubはこちら。
このsidekiq-schedulerをRailsアプリに導入します。
gem 'sidekiq-scheduler'
$ bundle install
ジョブを作成する
下記のコマンドでジョブを作成します。
$ bundle exec rails g job access_route_page
生成されたファイルのperform
メソッド内に、ジョブで実行したい処理を記述します。
class AccessRoutePageJob < ApplicationJob
queue_as :default
def perform
# 下記2行を追加
uri = URI('あなたのアプリのURL')
response = Net::HTTP.get_response(uri)
end
end
作成したジョブは、[ジョブ名].perfom_now
ですぐに実行できます。Redis、Sidekiqを立ち上げて、Railsのコンソール画面でジョブを実行してみましょう。
$ redis-server
# 略
$ bundle exec sidekiq
# 略
$ bundle exec rails c
Loading development environment (Rails 7.0.3)
[1] pry(main)> AccessRoutePageJob.perform_now
Performing AccessRoutePageJob (Job ID: d5af5ea0-36fd-4598-a185-70c409400d43) from Sidekiq(default) enqueued at
Performed AccessRoutePageJob (Job ID: d5af5ea0-36fd-4598-a185-70c409400d43) from Sidekiq(default) in 815.91ms
=> #<Net::HTTPOK 200 OK readbody=true>
無事HTTPリクエストが発生しました。
ジョブの実行スケジュールを追加する
最後に、作成したジョブを定期的に実行させましょう。
スケジュールを指定してジョブを実行させたい場合は、そのスケジュールをconfig/sidekiq.yml
に記述します。
例えば、下記の記述で、20分おきにAccessRoutePageJobが実行されます。
:schedule:
access_route_page:
cron: '0 0/20 * * * *'
class: AccessRoutePageJob
スケジュールの指定方法は、sidekiq-schedulerのREADMEで豊富に紹介されていますので、参考にしてみてください。
管理画面を追加する
上記までの内容を本番環境にデプロイすれば、やりたいことは終わりなのですが、Sidekiqでは便利な管理画面が用意されているので、ついでに追加しておきます。
管理画面を見られるユーザーは限定したいので、下記の記事を参考にBASIC認証を取り入れます。
# 下記2行を追加
require 'sidekiq/web'
require 'sidekiq-scheduler/web'
Rails.application.routes.draw do
# 下記4行を追加
Sidekiq::Web.use(Rack::Auth::Basic) do |user_id, password|
[user_id, password] == [ENV['USER_ID'], ENV['USER_PASSWORD']]
end
mount Sidekiq::Web, at: '/sidekiq'
end
ご自身でUSER_ID
、USER_PASSWORD
を指定し、環境変数に設定しましょう。
開発環境の場合、http://localhost:3000/sidekiq
へアクセスすれば、Sidekiqの管理画面が見られます。
パスワードとIDの入力が求められるので、先ほど指定した、USER_ID
、USER_PASSWORD
を入力しましょう。
「定期ジョブ」のタブで、ジョブの実行状況が確認できます。
きちんと20分おきにジョブがスケジューリングされました!
感想
Herokuでcronライクなジョブ管理を実現する方法としては、今回紹介した方法のほかに、Heroku Schedulerというツールを利用する方法もあるそうです。
ここまで完全無料で遊ばせてもらっていたHerokuですが、Sidekiqとあわせて使っているRedisも11月から有料になったりするので、今後の身の振り方を考えねば・・・というところです。
Discussion