はじめに
非同期処理を簡単に実装できるSidekiqを使ってみました。
Githubのリポジトリはこちらになります。
https://github.com/mperham/sidekiq
今回はRAILS CASTの記事をもとに実施します。
実行環境
- Ruby 2.4.2
- Rails 5.1.4
前準備
今回作成するものは、下図のような、コードを入力するとシンタックスハイライトをあててくれるPygmentsのAPIを叩きます。
APIはSidekiqにより別プロセスで実行します。
Redisのインストール
Sidekiqを使用するためにはRedisを起動させる必要があります。
Macを使用されている方はHomebrewでインストールすれば良いかと思います。
1 | $ brew install redis |
Railsの準備
プロジェクト作成
もととなるRailsプロジェクトを作成します。
scaffold
で簡易的に作成してしまいます。
1 2 3 4 5 | $ rails _5.1.4_ new sidekiq_sample $ bundle install $ rails generate scaffold snippets \ > language:string plain_code:text highlighted_code:text $ rails db:migrate |
作成されるテーブルは下記スキーマのようになるかと思います。
(
NOT NULL
制約などはつける必要があります。)
1 2 3 4 5 6 7 | create_table "snippets", force: :cascade do |t| t.string "language", null: false t.text "plain_code", null: false t.text "highlighted_code" t.datetime "created_at", null: false t.datetime "updated_at", null: false end |
新規登録時にAPIを叩く
RAILS CASTに従い、
scafold
で生成された
create
メソッドに追記します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | # 修正後のcreateメソッド def create @snippet = Snippet.new(snippet_params) respond_to do |format| if @snippet.save uri = URI.parse("https://pygments.simplabs.com/") request = Net::HTTP.post_form(uri, lang: @snippet.language, code: @snippet.plain_code) @snippet.update_attribute(:highlighted_code, request.body) format.html { redirect_to @snippet, notice: 'Snippet was successfully created.' } format.json { render :show, status: :created, location: @snippet } else format.html { render :new } format.json { render json: @snippet.errors, status: :unprocessable_entity } end end end |
細かい修正は割愛します。
ただ、APIの返却値はHTMLの文字列です。
そのため、ビューで表示する際に、html_safeでタグを活かした方が良いと思います。
後々のため、空文字チェックだけしておきます。
1 2 3 | <% if @snippet.highlighted_code.present? %> <%= @snippet.highlighted_code.html_safe %> <% end %> |
Sidekiqの準備
Workerを作る
app
ディレクトリの下に新たに
workers
ディレクトリを作成します。
その中に
pygments_worker.rb
を作成します。
1 2 3 4 5 6 7 8 9 10 | class PygmentsWorker include Sidekiq::Worker def perform(snippet_id) snippet = Snippet.find(snippet_id) uri = URI.parse("https://pygments.simplabs.com/") request = Net::HTTP.post_form(uri, lang: snippet.language, code: snippet.plain_code) snippet.update_attribute(:highlighted_code, request.body) end end |
perform
で処理を定義してあげます。
先ほど
snippets_controller.rb
で追記した処理をほぼそのまま移しています。
もともと
snippets_controller.rb
に記載していた処理を書き換えます。
1 2 3 4 5 6 7 8 9 | # 修正後のcreateメソッド respond_to do |format| if @snippet.save PygmentsWorker.perform_async(@snippet.id) format.html { redirect_to @snippet, notice: 'Snippet was successfully created.' } format.json { render :show, status: :created, location: @snippet } else # 以下省略 |
perform_async
で定義した
perform
を非同期で実行してくれます。
試してみる
Sidekiqを起動させるためには、Redisを起動させておく必要があります。
brew
でインストールし、特に何もいじっていなければ下記のコマンドで起動するかと思います。
1 | $ redis-server /usr/local/etc/redis.conf |
次にSidekiqを起動します。
1 | $ bundle exec sidekiq |
最後に、Railsのサーバーを起動します。
1 | $ rails server |
さいごに
Sidekiqを簡単に試してみました。
外部APIを使用する場合や重い処理を実行する際には使えそうです。
Sidekiqはいろいろできそうなので、ぜひ公式Wikiを見てください。
https://github.com/mperham/sidekiq/wiki