background jobs - com backgroundrb

31
Background Jobs com BackgrounDRb da série "Palestras na Softa" blog.softa.com.br Recomende: workingwithrails.com/person/9354

Upload: juan-maiz

Post on 10-May-2015

1.371 views

Category:

Technology


1 download

TRANSCRIPT

Page 1: Background Jobs - Com BackgrounDRb

Background Jobscom BackgrounDRb

da série "Palestras na Softa"

blog.softa.com.brRecomende: workingwithrails.com/person/9354

Page 2: Background Jobs - Com BackgrounDRb

BackgrounDRb

BackgrounDRb é um agendador e servidor de tarefas em Ruby. Seu objetivo principal é ser utilizado com aplicações Ruby on Rails - plugin - para desafogar tarefas de longa duração. É feito com PACKET e não DRb. Mas pra entender o conceito, vamos lá...

Page 3: Background Jobs - Com BackgrounDRb

DRb

Isso é um "tipo" de digressão.DRb é o Distributed Ruby.

Sim, um CORBA simplificado do Ruby. Serialização de objetos sobre TCP. DRb em Ruby é Standard Library.http://ruby-doc.org/stdlib/libdoc/drb/rdoc/index.html

Page 4: Background Jobs - Com BackgrounDRb

Hello DRb World

Clone: git://github.com/softa/hello_drb_world.git

Page 5: Background Jobs - Com BackgrounDRb

Simple (server)

require 'drb'class TestServer def doit "Hello, Distributed World" endendserver = TestServer.newDRb.start_service('druby://localhost:9000', server)DRb.thread.join

Page 6: Background Jobs - Com BackgrounDRb

Simple (client)

require 'drb'DRb.start_service()obj = DRbObject.new(nil, 'druby://localhost:9000')p obj.doit

Page 7: Background Jobs - Com BackgrounDRb

Math (server)require 'drb'class MathServer attr_accessor :total def initialize(initial_value) @total = initial_value end def sum(value) @total += value; end def subtract(value) @total -= value; end def multiply(value) @total *= value; end def divide(value) @total /= value; endend

DRb.start_service('druby://localhost:9000', MathServer.new(0))DRb.thread.join

Page 8: Background Jobs - Com BackgrounDRb

Math (client)

require 'drb'DRb.start_service()math = DRbObject.new(nil, 'druby://localhost:9000')puts math.sum(10)puts math.multiply(2)puts math.subtract(5)puts math.divide(3)

Page 9: Background Jobs - Com BackgrounDRb

Math

$ ruby client.rb 1020155

$ ruby client.rb 1530258

Page 10: Background Jobs - Com BackgrounDRb

Chat (server and client)

Open the files... please

Page 11: Background Jobs - Com BackgrounDRb

Agora... BackgrounDRb

Fim da digressão.

Page 12: Background Jobs - Com BackgrounDRb

Instalação do BackgrounDRb

GEMS necessárias:sudo gem install chronic packet Instalando:script/plugin install git://github.com/gnufied/backgroundrb.gitsudo su postgrescreateuser hello_backgroundrb_world^drake db:create rake backgroundrb:setup(...gera migrações...)rake db:migrate DONE!

Page 13: Background Jobs - Com BackgrounDRb

Instalação do BackgrounDRb

Todo o código em: http://github.com/softa/hello_backgroundrb_world

Page 14: Background Jobs - Com BackgrounDRb

Iniciando do BackgrounDRb

script/backgroundrb startscript/backgroundrb start -e ENVIRONMENT

Page 15: Background Jobs - Com BackgrounDRb

Config básico

config/backgroundrb.yml --- :backgroundrb: :port: 11006 :ip: 0.0.0.0

Page 16: Background Jobs - Com BackgrounDRb

Conceitos-chave

ServerUm server que recebe as chamadas. Deve ser startado uma vez junto com o web server.MiddleManClasse disponível (Factory) no Rails para chamar as tarefas dos workers em background, programar execuções ou busca informação sobre as tarefas.WorkerÉ uma classes que define as tarefas possíveis de se utilizar. Cada worker inicia um processo próprio ao iniciar o server.JobÉ a execução de um método de um worker.

Page 17: Background Jobs - Com BackgrounDRb

Conceitos-chave

cacheHash com informações sobre a execução de um job.job_keyVariável disponível no Worker para referenciar unicamente um Job.assync_*Executa o método * em background agora.enq_*Executa o método * em background no futuro.

Page 18: Background Jobs - Com BackgrounDRb

Rake

rake -T backgroundrb# Generate a migration for the backgroundrb queue table. rake backgroundrb:queue_migration# Drops and recreate backgroundrb queue tablerake backgroundrb:redo_queue # Remove backgroundrb from your rails application rake backgroundrb:remove # Setup backgroundrb in your rails application rake backgroundrb:setup # update backgroundrb config files from your rails applicationrake backgroundrb:update # Generate documentation for the backgroundrb pluginrake doc:plugins:backgroundrb

Page 19: Background Jobs - Com BackgrounDRb

Geradorscript/generate worker WorkerName [options]Rails Info: -v, --version Show the Rails version number and quit. -h, --help Show this help message and quit.General Options: -p, --pretend Run but do not make any changes. -f, --force Overwrite files that already exist. -s, --skip Skip files that already exist. -q, --quiet Suppress normal output. -t, --backtrace Debugging: show backtrace on errors. -c, --svn Modify files with subversion. (Note: svn must be in path) -g, --git Modify files with git. (Note: git must be in path)

Description: The worker generator creates stubs for a new BackgrounDRb worker.

The generator takes a worker name as its argument. The worker name may be given in CamelCase or under_score and should not be suffixed with 'Worker'.

The generator creates a worker class in lib/workers and a test suite in test/unit.

Example: ./script/generate worker Tail

This will create an Tail worker: Model: lib/workers/tail_worker.rb Test: test/unit/tail_worker_test.rb

Page 20: Background Jobs - Com BackgrounDRb

Executar apenas um método(com Ajax!)script/generate worker Counter

CounterWorker:: start

CounterController:: start_counting

CounterController:: show_count

MiddleMan

CounterController:: get_count

Ajax

MiddleMan

Page 21: Background Jobs - Com BackgrounDRb

Worker

class CounterWorker < BackgrounDRb::MetaWorker set_worker_name :counter_worker def create(args = nil) end def start cache[job_key] = 0 add_periodic_timer(2) { increment } end def increment cache[job_key] += 1 logger.warn "((#{cache[job_key]}))" endend

Page 22: Background Jobs - Com BackgrounDRb

Controller

script/generate controller Count start_counting show_count get_countdef start_counting t = Time.now.to_s session[:job_key] = t MiddleMan.worker(:counter_worker) .async_start(:job_key => t) redirect_to :action => :show_countend

Page 23: Background Jobs - Com BackgrounDRb

Controller

MiddleMan.worker(:counter_worker) .async_start(:job_key => t)

Page 24: Background Jobs - Com BackgrounDRb

Controller

def show_countend # app/views/counter/show_count<h1>Count#show_count</h1><div id="count"></div><script> new Ajax.PeriodicalRequest('count','/counter/get_count')</script>

Page 25: Background Jobs - Com BackgrounDRb

Controller

def get_count return render :text => MiddleMan.worker(:counter_worker).ask_result(session[:job_key])end

Page 26: Background Jobs - Com BackgrounDRb

Resultado

Page 27: Background Jobs - Com BackgrounDRb

Executar um método no futuro

friend = Contact.find_by_name 'Rafael Lunardini' MiddleMan.worker(:birthday_worker) .enq_send_congrats(:args => friend, :scheduled_at => friend.birthdate_in_this_year) task = Task.find_by_name 'Reunião Unicórnio' MiddleMan.worker(:task_worker) .enq_notice(:args => task, :scheduled_at => task.next_date)

Page 28: Background Jobs - Com BackgrounDRb

Executar um método periodicamente

# config/backgroundrb.yml--- :backgroundrb: :port: 11006 :ip: 0.0.0.0:schedules: :nightly_worker: :make_nightly_stuff: :trigger_args: 0 30 4 * * * * Igual ao CRON, hum?

Page 29: Background Jobs - Com BackgrounDRb

Executar um método periodicamente

Também rola isso: :schedules::foo_worker::foobar::trigger_args::start: <%= Time.now + 5.seconds %>:end: <%= Time.now + 10.minutes %>:repeat_interval: <%= 1.minute %>

Page 30: Background Jobs - Com BackgrounDRb

Advanced stuff

class ConnectorWorker < BackgrounDRb::MetaWorker set_worker_name :connector_worker def chat require 'drb' DRb.start_service() @chat = DRbObject.new(nil, 'druby://localhost:9000') @chat.login("Bot") add_periodic_timer(5) { talk } end def talk @chat.send_message("Bot", "i'm talking...") endend

Page 31: Background Jobs - Com BackgrounDRb

Advanced stuffclass TimeServerdef receive_data(p_data)enddef post_initadd_periodic_timer(2) { say_hello_world }enddef connection_completedenddef say_hello_worldp "***************** : invoking hello world #{Time.now}" send_data("Hello World\n")endendclass ServerWorker < BackgrounDRb::MetaWorker set_worker_name :server_worker def create(args = nil) start_server("0.0.0.0",11009,TimeServer) do |client_connection| client_connection.say_hello_world end endend