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
Background jobs with realtime results – RailsCl...
Search
Sergey Nartimov
September 15, 2012
Programming
5
210
Background jobs with realtime results – RailsClub'Moscow 2012
Sergey Nartimov
September 15, 2012
Tweet
Share
More Decks by Sergey Nartimov
See All by Sergey Nartimov
PubSub at Rails
lest
0
120
Rails in production - RubyConfBY 22 Mar 2015
lest
1
140
Sequel - BRUG 21 Feb 2015
lest
0
77
Elixir – Belarus Ruby User Group 25 Jan 2014
lest
3
650
Authentication Security – RUBYSPB
lest
2
150
Geospatial applications on Rails
lest
8
400
Design patterns – Belarus Ruby on Rails User Group 23 Feb 2013
lest
8
640
Ruby Stdlib – Minsk.rb October 2012
lest
10
340
Other Decks in Programming
See All in Programming
Django NinjaによるAPI開発の効率化とリプレースの実践
kashewnuts
1
290
color-scheme: light dark; を完全に理解する
uhyo
7
510
Datadog Workflow Automation で圧倒的価値提供
showwin
1
310
クリーンアーキテクチャから見る依存の向きの大切さ
shimabox
5
1.1k
ソフトウェアエンジニアの成長
masuda220
PRO
12
2.2k
dbt Pythonモデルで実現するSnowflake活用術
trsnium
0
270
機能が複雑化しても 頼りになる FactoryBotの話
tamikof
1
240
DRFを少しずつ オニオンアーキテクチャに寄せていく DjangoCongress JP 2025
nealle
2
290
コードを読んで理解するko build
bells17
1
120
なぜイベント駆動が必要なのか - CQRS/ESで解く複雑系システムの課題 -
j5ik2o
14
4.8k
AIレビュー導入によるCIツールとの共存と最適化
kamo26sima
1
560
Djangoにおける複数ユーザー種別認証の設計アプローチ@DjangoCongress JP 2025
delhi09
PRO
4
510
Featured
See All Featured
Into the Great Unknown - MozCon
thekraken
35
1.6k
Designing for humans not robots
tammielis
250
25k
Build The Right Thing And Hit Your Dates
maggiecrowley
34
2.5k
Imperfection Machines: The Place of Print at Facebook
scottboms
267
13k
Optimising Largest Contentful Paint
csswizardry
34
3.1k
StorybookのUI Testing Handbookを読んだ
zakiyama
28
5.5k
Facilitating Awesome Meetings
lara
53
6.3k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
53k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
175
52k
How STYLIGHT went responsive
nonsquared
99
5.4k
Stop Working from a Prison Cell
hatefulcrawdad
268
20k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
29
1.1k
Transcript
Фоновые задания с результатами в реальном времени Сергей Нартымов Brainspec
https://github.com/lest twitter: @just_lest
О себе • Rails, Rubinius, Elixir contributor • Señor software
engineer at Brainspec • Консалтинг, обучение, разработка Сергей Нартымов Brainspec https://github.com/lest twitter: @just_lest
Длительные операции • Отправка персонализированнх нотификаций • Обработка загружаемых файлов
• Генерация больших отчетов • Взаимодействие с медленным API
Принцип работы Браузер Приложение
Принцип работы Браузер Очередь заданий Приложение
Принцип работы Браузер Очередь заданий Рабочие процессы Приложение
Преимущества • Отзывчивость интерфейса • Распределение нагрузки
DelayedJob • https://github.com/collectiveidea/delayed_job • Выделен из Shopify • Задания хранятся
в базе данных • Сериализация с помощью YAML
DelayedJob class Device def deliver # long running method end
handle_asynchronously :deliver end
DelayedJob class Device def deliver # long running method end
handle_asynchronously :deliver end device = Device.new device.deliver
DelayedJob class LongTasks def send_mailer # Some other code end
handle_asynchronously :send_mailer, :priority => 20 def in_the_future # Some other code end # 5.minutes.from_now will be evaluated when in_the_future is called handle_asynchronously :in_the_future, :run_at => Proc.new { 5.minutes.from_now } end
DelayedJob object.delay(:queue => 'tracking').method Delayed::Job.enqueue job, :queue => 'tracking' handle_asynchronously
:tweet_later, :queue => 'tweets'
DelayedJob bundle exec rake jobs:work QUEUE=tracking rake jobs:work QUEUES=mailers,tasks rake
jobs:work
None
DelayedJob
Resque • https://github.com/defunkt/resque • Разработан и используется в Github •
Задания хранятся в Redis • Для сериализации используется JSON
Resque class Archive @queue = :file_serve def self.perform(repo_id, branch =
'master') repo = Repository.find(repo_id) repo.create_archive(branch) end end
Resque class Repository def async_create_archive(branch) Resque.enqueue(Archive, self.id, branch) end end
Resque QUEUE=file_serve rake resque:work QUEUES=critical,archive,high,low rake resque:work VERBOSE=1 QUEUE=* rake
resque:work
None
Resque plugins • resque-scheduler • resque-retry • resque-throttle • resque-workers-lock
• ...
Sidekiq • https://github.com/mperham/sidekiq • Выполняет задания в потоках • Используется
Celluloid • Задания хранятся в Redis • Сериализует данные в JSON
Sidekiq # app/workers/hard_worker.rb class HardWorker include Sidekiq::Worker def perform(name, count)
puts 'Doing hard work' end end
Sidekiq # app/workers/hard_worker.rb class HardWorker include Sidekiq::Worker def perform(name, count)
puts 'Doing hard work' end end HardWorker.perform_async('bob', 5)
Sidekiq class ImportantWorker include Sidekiq::Worker sidekiq_options :queue => :critical def
perform(*important_args) puts "Doing critical work" end end
Sidekiq bundle exec sidekiq
Sidekiq bundle exec sidekiq -c 100
Sidekiq bundle exec sidekiq bundle exec sidekiq \ -q critical,2
-q default
Sidekiq • Повторное выполнение в случае ошибок • Выполнение заданий
по расписанию • Совместимость с Resque
None
Что использовать?
Что использовать? • DelayedJob • Resque • Sidekiq
Общие советы • Храните в очереди идентификаторы, а не состояние
• Используйте after_commit в ActiveRecord для добавления задания в очередь • Избегайте блокировок
Rails 4 Queue Rails.queue.push SomeJob.new Rails.queue[:mail_queue].push MailJob.new
Результаты фоновых заданий
Результаты фоновых заданий • Обновить страницу вручную
Результаты фоновых заданий • Обновить страницу вручную • Автоматичекое обновление
через AJAX
Результаты фоновых заданий • Обновить страницу вручную • Автоматичекое обновление
через AJAX • Push результатов в браузер – WebSockets, long polling, ...
Push данных Очередь заданий Рабочие процессы Приложение Браузер
Push данных Очередь заданий Рабочие процессы Приложение Браузер Push сервер
Push данных Очередь заданий Рабочие процессы Приложение Браузер Push сервер
Push данных Очередь заданий Рабочие процессы Приложение Браузер Push сервер
Pusher • http://pusher.com/ • Сервис • Есть бесплатный тариф
Pusher
Pusher Pusher['my-channel'].trigger('my-event', {'message' => 'hello world'})
Pusher <script src="http://js.pusher.com/1.12/pusher.min.js"></script> var channel = pusher.subscribe('my-channel'); channel.bind('my-event', function(data) {
alert('Received my-event with message: ' + data.message); }); Pusher['my-channel'].trigger('my-event', {'message' => 'hello world'})
Faye • http://faye.jcoglan.com/
Faye • http://faye.jcoglan.com/ • Open source
Faye • http://faye.jcoglan.com/ • Open source • Серверная часть на
любой вкус – Ruby/EventMachine и Node.JS
Faye • http://faye.jcoglan.com/ • Open source • Серверная часть на
любой вкус – Ruby/EventMachine и Node.JS • Можно масштабировать
Faye • http://faye.jcoglan.com/ • Open source • Серверная часть на
любой вкус – Ruby/EventMachine и Node.JS • Можно масштабировать • Более тесная итеграция с приложением
Faye require 'faye' faye = Faye::RackAdapter.new(:mount => '/faye') faye.listen(9292)
Faye require 'faye' faye = Faye::RackAdapter.new(:mount => '/faye') faye.listen(9292) var
Faye = require('faye'), server = new Faye.NodeAdapter({mount: '/'}); server.listen(9292);
Faye <script src="http://localhost:9292/faye"></script> var client = new Faye.Client('http://localhost:9292/faye'); client.subscribe('/messages', function(message)
{ alert('Got a message: ' + message.text); });
Faye client = Faye::Client.new('http://localhost:9292/faye') client.publish('/messages', 'text' => 'Hello world')
None
Масштабирование Faye
Faye & Rails • Private Pub https://github.com/ryanb/private_pub • d'Anthès https://github.com/phenomena/danthes
Faye, Pusher, etc. • Уведомления • Обновление комментариев • Совместное
редактирование
Спасибо Сергей Нартымов Brainspec https://github.com/lest twitter: @just_lest