非同期処理を簡単に実装できるSidekiqを使ってみました。
Githubのリポジトリはこちらになります。
https://github.com/mperham/sidekiq
今回はRAILS CASTの記事をもとに実施します。
今回作成するものは、下図のような、コードを入力するとシンタックスハイライトをあててくれるPygmentsのAPIを叩きます。
APIはSidekiqにより別プロセスで実行します。
Sidekiqを使用するためにはRedisを起動させる必要があります。
Macを使用されている方はHomebrewでインストールすれば良いかと思います。
$ brew install redis
もととなるRailsプロジェクトを作成します。scaffold
で簡易的に作成してしまいます。
$ 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`制約などはつける必要があります。)
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
RAILS CASTに従い、`scafold`で生成された`create`メソッドに追記します。
# 修正後の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でタグを活かした方が良いと思います。
後々のため、空文字チェックだけしておきます。
<% if @snippet.highlighted_code.present? %> <%= @snippet.highlighted_code.html_safe %> <% end %>
`app`ディレクトリの下に新たに`workers`ディレクトリを作成します。
その中に`pygments_worker.rb`を作成します。
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`に記載していた処理を書き換えます。
# 修正後の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`でインストールし、特に何もいじっていなければ下記のコマンドで起動するかと思います。
$ redis-server /usr/local/etc/redis.conf
次にSidekiqを起動します。
$ bundle exec sidekiq
最後に、Railsのサーバーを起動します。
$ rails server
Sidekiqを簡単に試してみました。
外部APIを使用する場合や重い処理を実行する際には使えそうです。
Sidekiqはいろいろできそうなので、ぜひ公式Wikiを見てください。
https://github.com/mperham/sidekiq/wiki