Tuesday, January 15, 2013

Resque Hooks y Scheduler


Existen diferentes tecnologías que se pueden utilizar para programar jobs en segundo plano: entre ellas utilizando un almacén de datos NoSQL como Redis y Resque para su gestión.

En este artículo me gustaría hablar sobre los hooks y sobre resque-scheduler. Los hooks sirven para añadir comportamiento adicional a un plugin, en este caso al tratamiento y ejecución de un job y el segundo 'resque-scheduler' es una extensión para Resque que añade soporte para tratar jobs en un futuro. Veámos ambos conceptos con un poco más de tranquilidad y con ejemplos sencillos. Yo creo que ambos conceptos van un poco de la mano:

Job Hooks

Estos son algunos de los hooks que hay disponibles:


  • before_enqueue
  • after_enqueue
  • before_perform
  • after_perform
  • on_failure_retry  
  • etc

Veamos por ejemplo el funcionamiento del hook on_failure_retry, un hook interesante ya que va añadir un compartimiento  adicional en el caso de que el job que ejecutemos falle.

Imaginemos que tenemos un job que lo que hace es enviar emails en segundo plano a los usuarios de una aplicación:




require 'resque'
class EnvioEmailsJob < Jobs::Base
   def self.perform(opts = {})
      mail = UsuariosMailer.email_users(opts) # => a Mail::Message object
      mail.deliver   # sends the email
   end
end


Ahora vamos a añadir un hook y darle el comportamiento deseado en el caso de que el job que procesa el email fallara. Este es un punto interesante porque en determinadas aplicaciones podría ser un punto crítico y necesario para el correcto funcionamiento de la misma.
A continuación defino como sería el código para añadir el hook y su funcionalidad, en este caso vamos a modificar su comportamiento a través del plugin resque-scheduler, que entre otras cosas tiene una función que nos permite reencolar el job que ha fallado y decirle cuando queremos que se ejecute, porque de otro modo se ejecutaría de manera recursiva y no queremos que suceda eso:


module Jobs
  # Callbacks in jobs execution.
  # Esta clase debe ser la superclase de cualquier trabajo para controlar su      ejecución.
  
  class Base
      def self.on_failure_retry(e, *args)     
         next_execution = time_now.change(:min => 50)
         # función de resque-scheduler para reencolar el job y se ejecute en un    momento determinado, en este caso cada 50 minutos.
         Resque.enqueue_at(next_execution, self, *args)
      end 
  end
end

Scheduled Jobs

Son tareas programadas, como vimos en el ejemplo anterior la sintaxis es de la forma:

Resque.enqueue_in(5.days, SendFollowupEmail) # ejecutar un job en 5 días
# ó
Resque.enqueue_at(5.days.from_now, SomeJob) #  ejecutar un job a una hora especifica.

 




No comments:

Post a Comment