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 – RailsClub'Moscow 2012
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
110
Rails in production - RubyConfBY 22 Mar 2015
lest
1
130
Sequel - BRUG 21 Feb 2015
lest
0
71
Elixir – Belarus Ruby User Group 25 Jan 2014
lest
3
640
Authentication Security – RUBYSPB
lest
2
140
Geospatial applications on Rails
lest
8
370
Design patterns – Belarus Ruby on Rails User Group 23 Feb 2013
lest
8
640
Ruby Stdlib – Minsk.rb October 2012
lest
10
330
Other Decks in Programming
See All in Programming
地方こそサーバーレス、その意義に迫るサーバーレスPHP / Serverless PHP: The Rural Areas, and Why Serverless PHP Matters
seike460
PRO
2
100
Good first issues of TypeProf
mame
4
590
RaaP
ksss
0
160
Adding Security to Microcontroller Ruby
sylph01
1
160
哲学史とモデリング
tanakahisateru
2
430
slow types ってなんだろう?
karad
0
210
GoでParserを書く
karupanerura
3
380
欠陥を早期に発見するための Software Engineer in Test とその重要性 / What is Software Engineer in Test and How they works
orgachem
PRO
17
2.4k
otelcol receiver 自作RTA / Pepabo Tech Conference #22 春のSREまつり
arthur1
0
980
Escolhendo (ou não) o melhor ORM para o seu projeto
andreiacsilva
1
160
Enjoy Creative Coding with Ruby (RubyKaigi2024)
chobishiba
0
680
2024 コーディング研修
ckazu
2
660
Featured
See All Featured
Building an army of robots
kneath
300
41k
From Idea to $5000 a Month in 5 Months
shpigford
377
45k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
8
3.5k
Fantastic passwords and where to find them - at NoRuKo
philnash
39
2.5k
Music & Morning Musume
bryan
41
5.6k
Product Roadmaps are Hard
iamctodd
45
9.8k
Why Our Code Smells
bkeepers
PRO
331
56k
Ruby is Unlike a Banana
tanoku
96
10k
Building Your Own Lightsaber
phodgson
100
5.7k
[RailsConf 2023] Rails as a piece of cake
palkan
28
4.1k
Statistics for Hackers
jakevdp
790
220k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
126
32k
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