- 更新日: 2014年8月31日
- Rails
wheneverでActiveRecord管理の古いセッション情報レコードを自動で削除
先日のエントリー、Rails4でsession storeをActiveRecordに変更 | EasyRamble の続き。ActiveRecord で管理しているセッション情報(Sessionモデル、DBはsessionsテーブル)のうち、古くなったものをサーバー側で自動的に破棄するようにします。レコードの削除を cron で定期的に自動実行するために、crontab を Ruby で管理できる gem である whenever を利用する。
Gemfile に whenever を追加してインストール
Gemfile
1 |
gem 'whenever', :require => false |
1 2 3 |
$ bundle install |
続いて、wheneverize コマンドを実行。
1 2 3 4 5 |
$ bundle exec wheneverize . [add] writing `./config/schedule.rb' [done] wheneverized! |
config/schedule.rb が作成されます。
古いセッションデータのレコードを削除するクラスメソッドを作成
sessions テーブルの古いセッションデータを持つレコードを削除するロジックは、Rails Guides を参考にしました。
Ruby on Rails Security Guide — Ruby on Rails Guides
app/models/session.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 |
class Session < ActiveRecord::Base def self.sweep(time = 1.hour, old = 2.days) if time.is_a?(String) time = time.split.inject { |count, unit| count.to_i.send(unit) } end if old.is_a?(String) old = old.split.inject { |count, unit| count.to_i.send(unit) } end delete_all "updated_at < '#{time.ago.to_s(:db)}' OR created_at < '#{old.ago.to_s(:db)}'" end end |
created_at で指定する期間も、引数で渡せるように変更した。
config/schedule.rb で cron ジョブの設定
whenever では、config/schedule.rb にスケジューリング実行するジョブを追加します。以下のジョブをスケジュール設定できます。
command: bashコマンド
runner: 任意のメソッド
rake: Rakeタスク
script: script
とりあえず実験用で動作確認のため、以下のように設定しました。
config/schedule.rb
1 2 3 4 5 6 |
set :output, 'log/crontab.log' set :environment, :development every 2.minutes do runner "Session.sweep(5.minutes, 15.minutes)" end |
2分おきに cron で Session.sweep を実行。セッションレコードのうち updated_at が5分前より古いもの、または created_at が15分前より古いものを削除します。テストでは、無事に動作確認できました。
以下は production 環境での例。
1 2 3 4 5 6 |
set :output, 'log/crontab.log' set :environment, :production every 1.day, :at => '4:30 am' do runner "Session.sweep(7.days, 30.days)" end |
production 環境で、1日1回午前4時30分に Session.sweep を実行するジョブです。updated_at が7日前より古いもの、または created_at が30日前より古いものを削除する。この Session.sweep メソッドが実行されると、Devise 等によるログイン認証の維持も破棄される(ログアウトされる)のでそこは注意。Session.sweep の引数で指定する期間は適宜調整します。
whenever で設定したジョブを crontab に反映させる
ここまでの作業だけでは、まだ whenever で設定したジョブが crontab 自体に登録されることはありません。
whenever のヘルプは以下。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
$ bundle exec whenever --help Usage: whenever [options] -i [identifier], Default: full path to schedule.rb file --update-crontab -w, --write-crontab [identifier] Default: full path to schedule.rb file -c, --clear-crontab [identifier] -s, --set [variables] Example: --set 'environment=staging&path=/my/sweet/path' -f, --load-file [schedule file] Default: config/schedule.rb -u, --user [user] Default: current user -k, --cut [lines] Cut lines from the top of the cronfile -r, --roles [role1,role2] Comma-separated list of server roles to generate cron jobs for |
whenever でスケジューリングしたジョブを確認。
1 2 3 4 5 6 7 |
$ bundle exec whenever 0 0,2,4,6,8,10,12,14,16,18,20,22 * * * /bin/bash -l -c 'cd /path/to/railsapp && bin/rails runner -e production '\''Session.sweep(8.hours, 7.days)'\''' ## [message] Above is your schedule file converted to cron syntax; your crontab file was not updated. ## [message] Run `whenever --help' for more options. |
crontab に反映させる。
1 2 3 |
$ bundle exec whenever --update-crontab |
crontab 確認。
1 2 3 4 5 6 7 |
$ crontab -e # Begin Whenever generated tasks for: /path/to/railsapp/config/schedule.rb 0 0,2,4,6,8,10,12,14,16,18,20,22 * * * /bin/bash -l -c 'cd /path/to/railsapp && bin/rails runner -e production '\''Session.sweep(8.hours, 7.days)'\''' # End Whenever generated tasks for: /path/to/railsapp/config/schedule.rb |
とりあえずテスト確認用で設定した、2時間毎に実行する cron ジョブが登録されています。
crontab から削除。
1 2 3 |
$ bundle exec whenever --clear-crontab |
再び crontab 確認。
1 2 3 |
$ crontab -e |
削除されていることを確認する。
whenever と Capistrano の連携
Capistrano3 でデプロイ実行時に、自動で crontab をアップデートする設定を行います。
Capfile で、whenever/capistrano の require を追記。
Capfile
1 |
require "whenever/capistrano" |
続いて、config/deploy.rb で whenever 実行の環境、cronjob 識別子の設定、および SSHKit.config で whenever コマンドが bundle exec 付きで実行されるように指定。以下の内容を追記します。
config/deploy.rb
1 2 3 4 |
set :whenever_environment, "#{fetch(:stage)}" set :whenever_identifier, ->{ "#{fetch(:application)}_#{fetch(:stage)}" } SSHKit.config.command_map[:whenever] = "bundle exec whenever" |
デプロイ実行。
1 2 3 |
$ bundle exec cap production deploy |
whenever でスケジューリング設定したジョブが、crontab に反映されていることを確認できたら完了です。config/schedule.rb を編集した場合、デプロイするたびに自動で crontab が更新されます。
- – 参考リンク –
- Wheneverは導入が超簡単なcrontab管理ライブラリGemです![Rails4.1] – 酒と泪とRubyとRailsと
- Capistrano 3系でRails4.1のデプロイ[rbenv][rvm][ruby2.1] – 酒と泪とRubyとRailsと
- capistrano3 + wheneverでハマったメモ – リア充爆発日記
- Rails – Mysqlバックアップrakeタスクを作ってwheneverで回すまで – Qiita
- Rails の関連記事
- RailsでMySQLパーティショニングのマイグレーション
- Rails ActiveRecordでdatetime型カラムのGROUP BY集計にタイムゾーンを考慮する
- RailsプラグインGemの作成方法、RSpecテストまで含めたrails pluginの作り方
- RailsでAMPに対応するgemをリリースしました
- Railsでrequest.urlとrequest.original_urlの違い
- Railsでwheneverによるcronバッチ処理
- Google AnalyticsのRails Turbolinks対応
- Railsアプリにソーシャル・シェアボタンを簡単設置
- Rails監視ツール用にErrbitをHerokuで運用
- Facebook APIバージョンのアップグレード手順(Rails OmniAuth)
Leave Your Message!