Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Sidekiq
Search
Tymon Tobolski
July 01, 2015
Programming
1
160
Sidekiq
Tymon Tobolski
July 01, 2015
Tweet
Share
More Decks by Tymon Tobolski
See All by Tymon Tobolski
Only possible with Elixir - ubots Case Study
teamon
0
250
Fun with Elixir Macros
teamon
1
490
Elixir GenStage & Flow
teamon
2
1k
Elixir - Bydgoszcz Web Development Meetup
teamon
2
860
Git - Monterail style
teamon
1
180
Rails Assets wroc_love.rb
teamon
1
730
Angular replacements for jQuery-based libraries
teamon
1
350
Angular replacements for jQuery-based libraries
teamon
2
320
Rails Assets LRUG
teamon
0
7.5k
Other Decks in Programming
See All in Programming
スマホから Youtube Shortsを見られないようにする
lemolatoon
27
34k
実践Claude Code:20の失敗から学ぶAIペアプログラミング
takedatakashi
18
8.6k
デミカツ切り抜きで面倒くさいことはPythonにやらせよう
aokswork3
0
260
When Dependencies Fail: Building Antifragile Applications in a Fragile World
selcukusta
0
110
Webサーバーサイド言語としてのRustについて
kouyuume
1
4.9k
AI駆動で0→1をやって見えた光と伸びしろ
passion0102
1
840
bootcamp2025_バックエンド研修_WebAPIサーバ作成.pdf
geniee_inc
0
130
TFLintカスタムプラグインで始める Terraformコード品質管理
bells17
2
430
『毎日の移動』を支えるGoバックエンド内製開発
yutautsugi
2
290
Cursorハンズオン実践!
eltociear
2
1.2k
Things You Thought You Didn’t Need To Care About That Have a Big Impact On Your Job
hollycummins
0
250
EMこそClaude Codeでコード調査しよう
shibayu36
0
420
Featured
See All Featured
Code Review Best Practice
trishagee
72
19k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
132
19k
Reflections from 52 weeks, 52 projects
jeffersonlam
353
21k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
30
2.9k
Writing Fast Ruby
sferik
630
62k
Testing 201, or: Great Expectations
jmmastey
45
7.7k
KATA
mclloyd
PRO
32
15k
Embracing the Ebb and Flow
colly
88
4.9k
Facilitating Awesome Meetings
lara
57
6.6k
Documentation Writing (for coders)
carmenintech
75
5.1k
Code Reviewing Like a Champion
maltzj
526
40k
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.2k
Transcript
SIDEKIQ BACKGROUND JOBS IN RUBY © Tymon Tobolski, 2015
WHAT & WHY © Tymon Tobolski, 2015
class CommentsController < ApplicationController def create @comment = @post.comments.create!(comment_params) Notifications.notify_commenters(@comment)
head :ok end end © Tymon Tobolski, 2015
class Notifications def self.notify_commenters(comment) comment.post.comments_authors.each do |user| send_email_about_new_comment(user, comment) end
end end © Tymon Tobolski, 2015
SYNCHRONOUS DELIVERY class CommentsController < ApplicationController def create @comment =
@post.comments.create!(comment_params) # T = 10ms Notifications.notify_commenters(@comment) # T = 100.000ms, boom, timeout! head :ok end end class Notifications def self.notify_commenters(comment) comment.post.comments_authors.each do |user| send_email_about_new_comment(user, comment) # T += 1000ms end end end © Tymon Tobolski, 2015
ASYNCHRONOUS DELIVERY class CommentsController < ApplicationController def create @comment =
@post.comments.create!(comment_params) # T = 10ms NotifyCommentersWorker.perform_async(@comment.id) # T = 11ms, \o/ head :ok end end class Notifications def self.notify_commenters(comment) comment.post.comments_authors.each do |user| send_email_about_new_comment(user, comment) # T += 1000ms still, but we don't care anymore end end end © Tymon Tobolski, 2015
SIDEKIQ WORKER # app/workers/notify_commenters_worker.rb class NotifyCommentersWorker include Sidekiq::Worker def perform(comment_id)
comment = Comment.find(comment_id) Notifications.notify_commenters(comment) end end © Tymon Tobolski, 2015
MAGIC? © Tymon Tobolski, 2015
REDIS © Tymon Tobolski, 2015
REDIS.IO Redis is an open source, BSD licensed, advanced key-value
cache and store. It is often referred to as a data structure server since keys can contain strings, hashes, lists, sets, sorted sets, bitmaps and hyperloglogs, blah blah blah ... © Tymon Tobolski, 2015
REDIS.IO Redis is an open source, BSD licensed, advanced key-value
cache and store. It is often referred to as a data structure server since keys can contain strings, hashes, lists, sets, sorted sets, bitmaps and hyperloglogs, blah blah blah ... © Tymon Tobolski, 2015
LIST IN REDIS WORLD ... is really a list and
an array and a stack and a queue © Tymon Tobolski, 2015
QUEUE FIFO - FIRST IN, FIRST OUT ACTION QUEUE STATUS
--------------------------- [] PUSH 1 [1] PUSH 2 [2,1] PUSH 3 [3,2,1] POP [3,2] PUSH 4 [4,3,2] POP [4,3] POP [4] © Tymon Tobolski, 2015
QUEUE FIFO - FIRST IN, FIRST OUT ACTION mylist CONTENT
-------------------------------- (nil) LPUSH mylist 1 [1] LPUSH mylist 2 [2,1] LPUSH mylist 3 [3,2,1] RPOP mylist [3,2] LPUSH mylist 4 [4,3,2] RPOP mylist [4,3] RPOP mylist [4] © Tymon Tobolski, 2015
FLOW © Tymon Tobolski, 2015
RULES Sidekiq Best Practices © Tymon Tobolski, 2015
ALWAYS USE IDS BAD: NotifyCommentersWorker.perform_async(@comment) GOOD: NotifyCommentersWorker.perform_async(@comment.id) Job arguments MUST
be serializable to JSON def perform(comment_id) comment = Comment.find(comment_id) # ... end © Tymon Tobolski, 2015
IDEMPOTENT AND TRANSACTIONAL JOBS Sidekiq will execute your job at
least once. def perform(...) # ... User.where(id: id1).update_all(["balance = balance + ?", amount]) User.where(id: id2).update_all(["balance = balance - ?", amount]) # ... end © Tymon Tobolski, 2015
IDEMPOTENT AND TRANSACTIONAL JOBS Sidekiq will execute your job at
least once. def perform(...) # ... ActiveRecord.transation do User.where(id: id1).update_all(["balance = balance + ?", amount]) User.where(id: id2).update_all(["balance = balance - ?", amount]) end # ... end © Tymon Tobolski, 2015
CONCURRENCY & PARALLELISM def process(...) User.find_each do |user| send_email_to(user) end
end © Tymon Tobolski, 2015
CONCURRENCY & PARALLELISM def process(...) User.select(:id).find_each do |user| SendEmailWorker.perform_async(user.id) end
end © Tymon Tobolski, 2015
FOREMAN / HEROKU # Procfile web: bin/rails server -p $PORT
worker: bin/sidekiq © Tymon Tobolski, 2015
SIDEKIQ WEB © Tymon Tobolski, 2015
SIDEKIQ WEB # Gemfile gem 'sinatra', :require => nil #
config/routes.rb require 'sidekiq/web' authenticate :user, lambda { |u| u.admin? } do mount Sidekiq::Web => '/sidekiq' end © Tymon Tobolski, 2015
QUESTIONS? © Tymon Tobolski, 2015