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
390
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
責務を分離するための例外設計 - PHPカンファレンス 2024
kajitack
6
1.4k
Webエンジニア主体のモバイルチームの 生産性を高く保つためにやったこと
igreenwood
0
340
テストコードのガイドライン 〜作成から運用まで〜
riku929hr
5
710
各クラウドサービスにおける.NETの対応と見解
ymd65536
0
110
Fibonacci Function Gallery - Part 1
philipschwarz
PRO
0
220
競技プログラミングへのお誘い@阪大BOOSTセミナー
kotamanegi
0
360
return文におけるstd::moveについて
onihusube
1
1.1k
フロントエンドのディレクトリ構成どうしてる? Feature-Sliced Design 導入体験談
osakatechlab
8
4.1k
Kaigi on Railsに初参加したら、その日にLT登壇が決定した件について
tama50505
0
100
php-conference-japan-2024
tasuku43
0
320
range over funcの使い道と非同期N+1リゾルバーの夢 / about a range over func
mackee
0
110
Recoilを剥がしている話
kirik
5
6.8k
Featured
See All Featured
Making Projects Easy
brettharned
116
5.9k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
44
6.9k
The Invisible Side of Design
smashingmag
298
50k
Agile that works and the tools we love
rasmusluckow
328
21k
Building Flexible Design Systems
yeseniaperezcruz
327
38k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
365
25k
Why You Should Never Use an ORM
jnunemaker
PRO
54
9.1k
The Cost Of JavaScript in 2023
addyosmani
45
7k
Done Done
chrislema
181
16k
Speed Design
sergeychernyshev
25
670
A better future with KSS
kneath
238
17k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
191
16k
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