LoginSignup
4
2

More than 3 years have passed since last update.

【Rails】Rake taskでバッチ処理を実装してみた

Posted at

はじめに

環境

Rails: 5.2.3
Ruby: 2.6.3
MySQL: 5.6.40

内容

  • usersテーブルのquestion_countカラムが更新されていないバグがあり、 バッチを作成し、一括で正しい値に更新できるようにしました。
  • 既存のメソッドを使用しているため分かりにくい箇所があるかもしれませんがご容赦ください。
user.rb
has_many :questions, dependent: false
has_many :only_questions_visible_to_user, -> { where(question_id: nil).visible_to_user }, class_name: 'Question', dependent: false

scope :visible_to_user, -> { where(is_invalid: false).where(deleted: false) }

def update_question_count!
  update!(question_count: count_questions)
end

private

# question_count を更新する時の集計に利用するメソッド
#
# @return [Integer]
def count_questions
  only_questions_visible_to_user.size
end

question.rb
belongs_to :user, optional: true

実装したコード

  • ログを出力して途中経過、更新に失敗したもの認識しやすいようにしてみました。
  • 一度のみの実行で、以降は必要なくなるため、one_shotディレクトリ配下に置いて実行後に削除します。
lib/tasks/one_shot/update_users_question_count.rake
# frozen_string_literal: true

namespace :user do
  desc 'Update users_question_count'
  task update_question_count: :environment do |_task|
    index = 0
    updated_question_counts = 0
    user_count = User.count
    logger = Logger.new($stdout)
    logger.info 'Start'

    User.find_each do |user|
      begin
        if user.question_count != user.only_questions_visible_to_user.size
          user.update_question_count!
          updated_question_counts += 1
        end
      rescue ActiveRecord::RecordInvalid => e
        logger.info "Failed to update user_id: #{user.id}"
        logger.info("#{e.class}: #{e.message}")
        next
      end

      index += 1
      case index
      when 4000, 8000, 12_000, 16_000
        logger.info "Progress: #{index}/#{user_count}"
      end
    end
    logger.info "Updated User Count: #{updated_user_counts}"
    logger.info 'Finished'
  end
end

バッチ実行

bundle exec rake user:update_question_count

  • 約19,000レコードの更新処理で45secほどかかりました。
  • 更新に失敗したカラムが表示されるので別途対応が容易になりました。 スクリーンショット 2020-10-26 午後2.36.25.png
4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2