Rails + Delayed Job な環境で、Delayed Job を使って実行する処理がありました。
例えばこんな感じです。
# Delayed Job で実行 # call_heavy_api中で外部APIを呼んでいるが、その処理が重いとする Task.delay.call_heavy_api({ foo: 'bar' })
そんな中、Delayed Job を使って実行する処理 (上記例では call_heavy_api
の中身) をデバッグしたくなったところ、同僚からやり方を聞いたため、メモを残します。
目次
環境
- macOS
- RubyMine 2021.1.1
設定
Delayed Jobs は Rake タスクなので、以下の設定を RubyMine に行います。
- Run > Edit Configurations ...
- Rakeタスクを追加
- Name: 任意
- Configurationタブ
- Task name:
jobs:work
- Task name:
- Bundlerタブ
Run the script in context of the bundle (bundle exec)
にチェックを入れる- bundlerを使っているため
実際のアプリで確認
Rails + Delayed Job なアプリを作って確認してみます。
Railsアプリを作成
環境構築
# railsの準備 % bundle init
Gemfileを作成
# Gemfile # frozen_string_literal: true source "https://rubygems.org" git_source(:github) {|repo_name| "https://github.com/#{repo_name}" } gem "rails"
% rails new delayed_job_debug --api % cd delayed_job_debug
delayed_job_debugのGemfileに、Delayed JobをActiveRecordで使うためのgemを追記。
# delayed_job_debug/Gemfile # ... gem 'delayed_job_active_record'
インストール
bundle install
Delayed Job の準備をします。
% bin/rails g delayed_job:active_record Running via Spring preloader in process 13171 create bin/delayed_job chmod bin/delayed_job create db/migrate/20210517154917_create_delayed_jobs.rb % bin/rake db:migrate Running via Spring preloader in process 13208 == 20210517154917 CreateDelayedJobs: migrating ================================ -- create_table(:delayed_jobs) -> 0.0035s -- add_index(:delayed_jobs, [:priority, :run_at], {:name=>"delayed_jobs_priority"}) -> 0.0013s == 20210517154917 CreateDelayedJobs: migrated (0.0050s) =======================
config/application.rb
にて、Active JobのバックエンドとしてDelayed Job を指定
# config/application.rb config.active_job.queue_adapter = :delayed_job
アプリ追加
重いAPIを呼んでいるモデルを作ります。
今回はDBがなくても確認できるため、モデルファイル app/models/task.rb
を作るだけにします。
class Task class << self # 外部APIの処理が重いとする def call_heavy_api(params) Rails.logger.warn(params) 'success' end end end
上記のメソッドを呼んでいるコントローラを作ります。
% bin/rails g controller tasks Running via Spring preloader in process 13248 create app/controllers/tasks_controller.rb invoke test_unit
生成されたファイル app/controllers/task_controller.rb
に追記します。
class TasksController < ApplicationController def create Task.delay.call_heavy_api({ foo: 'bar' }) render json: { status: 'SUCCESS', data: 'done' } end end
config/routes
へ追記します。
Rails.application.routes.draw do # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html post 'tasks/' => 'tasks#create' end
Railsアプリの動作確認
実行します。
TerminalからcurlでPOSTします。
% curl -X POST -H "Content-Type: application/json" -d '{}' http://127.0.0.1:3500/tasks/ {"status":"SUCCESS","data":"done"}
DBに値が入っています。
Delayed Job をターミナルから実行します。
% bin/rake jobs:work Running via Spring preloader in process 32682 [Worker(host:kamijonoMacBook-Pro.local pid:32682)] Starting job worker [Worker(host:kamijonoMacBook-Pro.local pid:32682)] Job Task.call_heavy_api (id=3) RUNNING [Worker(host:kamijonoMacBook-Pro.local pid:32682)] Job Task.call_heavy_api (id=3) COMPLETED after 0.0080 [Worker(host:kamijonoMacBook-Pro.local pid:32682)] 1 jobs processed at 12.7021 j/s, 0 failed
Sever development log に実行内容も表示されました。
[Worker(host:kamijonoMacBook-Pro.local pid:32682)] Job Task.call_heavy_api (id=3) RUNNING {:foo=>"bar"}
確認できたため、TerminalでDelayed Job をキャンセルしておきます。
デバッグ実行
RubyMineの設定
メニューの Run > Edit Configurations... を選択します。
左上の +
ボタンを押して Rake
を選択し、以下の内容を追加します。
項目 | 値 |
---|---|
Name | 任意 (job) |
Configuration - Task name | jobs:work |
Bundler - Run the script... | チェックを入れる |
動作確認
Terminalから curl で POST し、DBに保存されることを確認します。
% curl -X POST -H "Content-Type: application/json" -d '{}' http://127.0.0.1:3500/tasks/ {"status":"SUCCESS","data":"done"}
確認したいところにブレークポイントを設置します。
先ほど作成した設定を選択し、デバッグ実行します。
なお、初回は ruby-debug-ide
のインストールが提案されるため、インストールします。
しばらく待つと、ブレークポイントで止まりました。変数の中身なども確認できます。
ソースコード
確認したRailsアプリはGithubに上げました。
https://github.com/thinkAmi-sandbox/delayed_job_debug-sample