Si está viendo esto en https://github.com/collectiveidea/delayed_job, está leyendo la documentación de la rama maestra. Ver documentación para la última versión (4.1.13).
Retrasado :: trabajo (o DJ) encapsula el patrón común de ejecutar tareas más largas en segundo plano.
Es una extracción directa de Shopify donde la tabla de trabajo es responsable de una multitud de tareas centrales. Entre esas tareas están:
Enviar boletines masivos
cambio de tamaño de imagen
Descargas HTTP
Actualización de colecciones inteligentes
Actualización de Solr, nuestro servidor de búsqueda, después de que cambie el producto
importaciones por lotes
cheques de spam
Síganos en Twitter para obtener actualizaciones y avisos sobre nuevos lanzamientos.
demandado_job 3.0.0 solo admite rieles 3.0+.
demandado_job admite múltiples backends para almacenar la cola de trabajo. Vea el wiki para otros backends.
Si planea usar demandado_job con un registro activo, agregue delayed_job_active_record
a su Gemfile
.
gem 'demandado_job_active_record'
Si planea usar demandado_job con Mongoid, agregue delayed_job_mongoid
a su Gemfile
.
gema 'demandado_job_mongoid'
Ejecute bundle install
para instalar las gemas Backend y Deleted_Job.
El backend de registros activo requiere una tabla de empleos. Puede crear esa tabla ejecutando el siguiente comando:
rails generate delayed_job:active_record rake db:migrate
Para Rails 4.2+, vea a continuación
En el modo de desarrollo, si está utilizando Rails 3.1+, su código de aplicación recargará automáticamente cada 100 trabajos o cuando la cola termine. Ya no necesita reiniciar el trabajo retrasado cada vez que actualiza su código en desarrollo.
En Rails 4.2+, establezca queue_adapter en config/application.rb
config.active_job.queue_adapter =: demandado_job
Consulte la Guía Rails para obtener más detalles.
Si está utilizando la gema Protected_Attributes, debe aparecer antes de demandado_job en su archivo gem. Si sus trabajos están fallando con:
ActiveRecord::StatementInvalid: PG::NotNullViolation: ERROR: null value in column "handler" violates not-null constraint
Entonces esta es la solución que estás buscando.
Job retrasado 3.0.0 introduce una nueva columna en la tabla Deleted_Jobs.
Si está actualizando desde el trabajo retrasado 2.x, ejecute el generador de actualización para crear una migración para agregar la columna.
rails generate delayed_job:upgrade rake db:migrate
Llamar .delay.method(params)
en cualquier objeto y se procesará en segundo plano.
# sin [email protected]! (@dispositivo)# con [email protected]! (@dispositivo)
Si siempre se ejecuta un método en segundo plano, puede llamar #handle_asynchronously
después de la declaración del método:
dispositivo de clase Def entregar# método de ejecución de larga duración fin handle_asynchrony: entreténddevice = dispositivo.newdevice.deliver
#handle_asynchronously
y #delay
toman estos parámetros:
:priority
(número): los números más bajos se ejecutan primero; El valor predeterminado es 0 pero se puede reconfigurar (ver más abajo)
:run_at
(hora): ejecute el trabajo después de este tiempo (probablemente en el futuro)
:queue
(cadena): cola nombrada para poner este trabajo, una alternativa a las prioridades (ver más abajo)
Estos parámetros pueden ser objetos PROC, permitiendo la evaluación del tiempo de llamada del valor.
Por ejemplo:
Tasks de clase def send_mailer# algún otro código fin Handle_asynchrony: send_mailer ,: priority => 20 def in_the_future# algún otro código fin # 5.Minutes.From_Now se evaluará cuando se llama a In_The_Future Handle_asynchrony: in_the_future ,: run_at => proc.new {5.minutes.from_now} Def Self.When_To_run2.Hours.From_Now fin class << Selfdef Call_a_class_method # Otro Otro CodeENDHANDLE_ASYNCHRONY: Call_a_class_method ,: run_at => Proc.new {When_to_run} fin Attr_reader: How_important Def Call_an_instance_method# algún otro código fin Handle_asynchrony: call_an_instance_method ,: priority => proc.new {| i | I.how_important} final
Si alguna vez desea llamar a un método D handle_asynchronously
'D sin un trabajo retrasado, por ejemplo, al depurar algo en la consola, simplemente agregue _without_delay
al nombre del método. Por ejemplo, si su método original era foo
, llame foo_without_delay
.
El trabajo retrasado utiliza una sintaxis especial para rieles. No llame al método .deliver
cuando use .delay
.
# sin demandado_jobnotifier.signup (@user) .deliver# con demandado_jobnotifier.delay.signup (@user)# demandado_job ejecutándose en un tinotifier específico.delay (run_at: 5.minutes.from_now) .signup (@user)# cuando usa parámetros , el método .with debe llamarse antes del methodentifier .delay. Con (foo: 1, bar: 2) .delay.signup (@user)
También es posible que desee considerar el uso de un trabajo activo con Action Mailer que proporciona una conveniente sintaxis .deliver_later
que reenvía al trabajo retrasado bajo el hogar.
DJ 3 introduce colas con estilo de resque con el estilo de resque sin dejar de conservar la prioridad al estilo DJ. El objetivo es proporcionar un sistema para las tareas de agrupación que deben trabajarse por grupos de trabajadores separados, que pueden escalarse y controlarse individualmente.
Los trabajos se pueden asignar a una cola configurando la opción queue
:
Object.delay (: queue => 'Tracking'). MethodDelayed :: Job.enqueue Job ,: Queue => 'Tracking'handle_asynChrony: tweet_later,: queue =>' tweets '
Puede configurar las prioridades predeterminadas para colas con nombre:
Retrasado :: trabajador.queue_attributes = { High_priority: {prioridad: -10}, Low_priority: {Priority: 10}}
Las prioridades de cola configuradas se pueden anular con la prioridad del método de retraso
object.delay (: queue => 'high_priority', prioridad: 0) .method
Puede iniciar procesos para trabajar solo ciertas colas con las opciones queue
y queues
definidas a continuación. Los procesos iniciados sin especificar una cola ejecutarán trabajos desde cualquier cola. Para tener efectivamente un proceso que ejecuta trabajos donde no se especifica una cola, establezca un nombre de cola predeterminado con Delayed::Worker.default_queue_name
y haga que los procesos ejecuten esa cola.
script/delayed_job
se puede utilizar para administrar un proceso de fondo que comenzará a trabajar fuera de los trabajos.
Para hacerlo, agregue gem "daemons"
a su Gemfile
y asegúrese de que rails generate delayed_job
.
Entonces puedes hacer lo siguiente:
RAILS_ENV=production script/delayed_job start RAILS_ENV=production script/delayed_job stop # Runs two workers in separate processes. RAILS_ENV=production script/delayed_job -n 2 start RAILS_ENV=production script/delayed_job stop # Set the --queue or --queues option to work from a particular queue. RAILS_ENV=production script/delayed_job --queue=tracking start RAILS_ENV=production script/delayed_job --queues=mailers,tasks start # Use the --pool option to specify a worker pool. You can use this option multiple times to start different numbers of workers for different queues. # The following command will start 1 worker for the tracking queue, # 2 workers for the mailers and tasks queues, and 2 workers for any jobs: RAILS_ENV=production script/delayed_job --pool=tracking --pool=mailers,tasks:2 --pool=*:2 start # Runs all available jobs and then exits RAILS_ENV=production script/delayed_job start --exit-on-complete # or to run in the foreground RAILS_ENV=production script/delayed_job run --exit-on-complete
Rails 4: Reemplace el script/demandado_job con bin/demandado_job
Los trabajadores pueden estar ejecutándose en cualquier computadora, siempre que tengan acceso a la base de datos y su reloj esté sincronizado. Tenga en cuenta que cada trabajador verificará la base de datos al menos cada 5 segundos.
También puede invocar rake jobs:work
que comenzará a trabajar fuera de los trabajos. Puede cancelar la tarea de rastrillo con CTRL-C
.
Si solo desea ejecutar todos los trabajos disponibles y salir, puede usar rake jobs:workoff
Trabaje en colas estableciendo la variable de entorno QUEUE
o QUEUES
.
QUEUE=tracking rake jobs:work QUEUES=mailers,tasks rake jobs:work
La siguiente sintaxis reiniciará trabajos retrasados:
RAILS_ENV=production script/delayed_job restart
Para reiniciar múltiples trabajadores de DelayDed_Job:
RAILS_ENV=production script/delayed_job -n2 restart
Rails 4: Reemplace el script/demandado_job con bin/demandado_job
Los trabajos son objetos rubí simples con un método llamado desempeño. Cualquier objeto que responda para realizar se puede meter en la tabla de trabajos. Los objetos de trabajo se serializan a YAML para que luego puedan ser resucitados por el corredor de trabajo.
NewsletterJob = struct.new (: texto,: correos electrónicos) hacer Def Performmails.E cada {| E | NewsletTermailer.deliver_text_to_email (texto, e)} EndendDelayed :: Job.enqueue Newsletterjob.new ('lorem ipsum ...', clientes.pluck (: correo electrónico))
Para establecer un intento máximo de porjón que anule el retraso :: Worker.max_attempts puede definir un método max_attempts en el trabajo
NewsletterJob = struct.new (: texto,: correos electrónicos) hacer Def Performmails.E cada {| E | NewsletTermailer.deliver_text_to_email (texto, e)} fin def max_attempts3 endender
Para establecer un tiempo de ejecución máximo por trabajo que anule el retrasado :: trabajador.max_run_time puede definir un método max_run_time en el trabajo
Nota: Esto solo se puede usar para establecer un MAX_RUN_TIME que sea más bajo que el retrasado :: Worker.max_run_time. De lo contrario, el bloqueo en el trabajo expiraría y otro trabajador comenzaría a trabajar en el trabajo en progreso.
NewsletterJob = struct.new (: texto,: correos electrónicos) hacer Def Performmails.E cada {| E | NewsletterMailer.deliver_text_to_email (texto, e)} fin def max_run_time120 # segundos endender
Para establecer un valor predeterminado por Job para destruir trabajos fallidos que anulan el retrasado :: Worker.destroy_failed_jobs puede definir un destruye_failed_jobs? Método en el trabajo
NewsletterJob = struct.new (: texto,: correos electrónicos) hacer Def Performmails.E cada {| E | NewsletTermailer.deliver_text_to_email (texto, e)} fin Def destruye_failed_jobs? Falso endender
Para establecer un nombre de cola predeterminado para un trabajo personalizado que anula Retraso :: Worker.default_queue_name, puede definir un método queue_name en el trabajo
NewsletterJob = struct.new (: texto,: correos electrónicos) hacer Def Performmails.E cada {| E | NewsletTermailer.deliver_text_to_email (texto, e)} fin Def queue_name'Newsletter_queue ' endender
En error, el trabajo se programa nuevamente en 5 segundos + n ** 4, donde n es el número de intentos. Puede definir su propio método reschedule_at
para anular este comportamiento predeterminado.
NewsletterJob = struct.new (: texto,: correos electrónicos) hacer Def Performmails.E cada {| E | NewsletTermailer.deliver_text_to_email (texto, e)} fin Def REPRSEDULE_AT (Current_Time, intentos) Current_Time + 5.seconds endender
Puede definir ganchos en su trabajo que se llamará en diferentes etapas del proceso:
Nota: Si está utilizando ActiveJob, estos ganchos no están disponibles para sus trabajos. Deberá usar las devoluciones de llamada de ActiveJob. Puede encontrar detalles aquí https://guides.rubyonrails.org/active_job_basics.html#callbacks
clase ParanoidNeWSletterJob <NewsletterJob Def Enqueue (Job) Record_stat 'Newsletter_job/Enqueue' fin Def Performmails.E cada {| E | NewsletterMailer.deliver_text_to_email (texto, e)} fin Def antes (trabajo) Record_stat 'Newsletter_job/inicio' fin Def After (Job) Record_stat 'Newsletter_job/After' fin Def Success (Job) Record_stat 'Newsletter_job/Success' fin ERROR DEF DEF (trabajo, excepción) aerbrake.notify (excepción) fin faula def falla (trabajo) Page_sysadmin_in_the_middle_of_the_night endender
La biblioteca gira en torno a una tabla de jobs retrasada que se ve de la siguiente manera:
create_table: demandado_jobs ,: force => true do | tabla | table.integer: priority ,: default => 0 # permite que algunos trabajos salten al frente de la cola Tabla.integer: intentos ,: default => 0 # proporciona reintentos, pero aún eventualmente falla. Table.text: Handler # Cadena codificada de YAML del objeto que funcionará table.text: last_error # Razón para la última falla (ver la nota a continuación) table.datetime: run_at # cuándo ejecutar. Podría ser TIME.ZONE.NOW para inmediatamente, o en algún momento en el futuro. table.datetime: Locked_at # Establecer cuando un cliente está trabajando en este objeto TABLE.DATETIME: fallado_at # Establecer cuando todos los reintentos han fallado (en realidad, por defecto, el registro se elimina en su lugar) table.String: Locked_by # ¿Quién está trabajando en este objeto (si está bloqueado) table.string: cola # El nombre de la cola en este trabajo está en tabla.timestampsend
En error, el trabajo se programa nuevamente en 5 segundos + n ** 4, donde n es el número de intentos o utilizando el método reschedule_at
definido del trabajo.
El Worker.max_attempts
predeterminado.max_attempts es 25. Después de esto, el trabajo se elimina (predeterminado) o se deja en la base de datos con el conjunto "fallido_at". Con el valor predeterminado de 25 intentos, el último reintento será 20 días después, con el último intervalo casi 100 horas.
El Worker.max_run_time
predeterminado.max_run_time es 4. HOURS. Si su trabajo lleva más tiempo que eso, otra computadora podría recogerlo. Depende de usted asegurarse de que su trabajo no exceda esta vez. Debe establecer esto al tiempo más largo que crea que el trabajo podría tomar.
Por defecto, eliminará los trabajos fallidos (y siempre elimina los trabajos exitosos). Si desea mantener trabajos fallidos, establezca Delayed::Worker.destroy_failed_jobs = false
. Los trabajos fallidos se marcarán con no nulo fallido_at.
Por defecto, todos los trabajos están programados con priority = 0
, que es la máxima prioridad. Puede cambiar esto estableciendo Delayed::Worker.default_priority
a otra cosa. Los números más bajos tienen mayor prioridad.
El comportamiento predeterminado es leer 5 empleos de la cola al encontrar un trabajo disponible. Puede configurar esto configurando Delayed::Worker.read_ahead
.
Por defecto, todos los trabajos se colocarán sin una cola con nombre. Se puede especificar una cola con nombre predeterminada utilizando Delayed::Worker.default_queue_name
.
Si no se encuentran trabajos, el trabajador duerme por la cantidad de tiempo especificada por la opción de retraso del sueño. Establecer Delayed::Worker.sleep_delay = 60
para un tiempo de sueño de 60 segundos.
Es posible deshabilitar los trabajos retrasados para fines de prueba. Establecer Delayed::Worker.delay_jobs = false
para ejecutar todos los trabajos en tiempo real.
O Delayed::Worker.delay_jobs
puede ser un proceso que decide si ejecutar trabajos en línea por trabajo:
Retrasado :: trabajador.delay_jobs = -> (trabajo) { Job.Queue! = 'Inline'}
Es posible que deba aumentar las excepciones sobre las señales de signo, Delayed::Worker.raise_signal_exceptions = :term
hará que el trabajador plantee una SignalException
que hace que el trabajo en funcionamiento aborte y sea desbloqueado, lo que hace que el trabajo esté disponible para otros trabajadores. El valor predeterminado para esta opción es falso.
Aquí hay un ejemplo de cambio de parámetros de trabajo en rieles:
# config/initializers/delayed_job_config.rbDelayed::Worker.destroy_failed_jobs = falseDelayed::Worker.sleep_delay = 60Delayed::Worker.max_attempts = 3Delayed::Worker.max_run_time = 5.minutesDelayed::Worker.read_ahead = 10Delayed::Worker.default_queue_name = 'Default'Delayed :: Worker.delay_jobs =! Rails.env.test? Deletado :: Worker.raise_signal_exceptions =: TermDelayed :: Worker.Logger = logger.new (file.join (Rails.Root,' log '' ',' ', demandado_job.log '))
Puede invocar rake jobs:clear
para eliminar todos los trabajos en la cola.
Los buenos lugares para obtener ayuda son:
Google grupos donde puede unirse a nuestra lista de correo.
Flujo de stackover