カテゴリー: BackEnd

RailsでSidekiqを使ってみた

はじめに

非同期処理を簡単に実装できる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でインストールすれば良いかと思います。

$ brew install redis

Railsの準備

プロジェクト作成

もととなる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

新規登録時にAPIを叩く

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 %>

Sidekiqの準備

Workerを作る

`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

naoki85

シェア
執筆者:
naoki85
タグ: Rails

最近の投稿

go 1.24の tool directive でツールを管理する

はじめに プロダクト開発を行う…

1か月 前

uvの本番環境用dockerのマルチステージビルド

はじめに uvで本番環境のdo…

2か月 前

Go 1.24で追加されたweak pointer

はじめに 前回の記事では、Go…

3か月 前

Next.jsでサイトマップの実装

はじめに Next.jsでサイ…

4か月 前