Prioridade é uma decisão, não um padrão

Prévia grátis 3 min de leitura

Nenhum job desta aplicação chama queue_with_priority; uma busca por priority em app/jobs/ não encontra nada. Mesmo assim todo job tem uma prioridade, porque toda linha de solid_queue_jobs tem: o db/queue_schema.rb define a coluna como null: false. Esta aula trata de onde vem esse número quando ninguém pediu um.

Dois padrões, e não um

O ActiveJob::QueuePriority, incluído em todo job:

module ActiveJob
  module QueuePriority
    module ClassMethods
      mattr_accessor :default_priority

      def queue_with_priority(priority = nil, &block)
        if block_given?
          self.priority = block
        else
          self.priority = priority
        end
      end
    end

    included do
      class_attribute :priority, instance_accessor: false, default: default_priority
    end

    def priority
      if @priority.is_a?(Proc)
        @priority = instance_exec(&@priority)
      end
      @priority
    end
  end
end

O default_priority é um mattr_accessor simples que a aplicação nunca define, então é nil. Um job que nunca chama queue_with_priority devolve nil no #priority: não 0, nil. O próprio comentário do Rails sobre o atributo, em active_job/core.rb, diz o que o número significa quando existe: # Priority that the job will have (lower is more priority).

O nil nunca chega ao banco. Este é o SolidQueue::Job.attributes_from_active_job:

def attributes_from_active_job(active_job)
  {
    queue_name: active_job.queue_name || DEFAULT_QUEUE_NAME,
    active_job_id: active_job.job_id,
    priority: active_job.priority || DEFAULT_PRIORITY,
    scheduled_at: active_job.scheduled_at,
    class_name: active_job.class.name,
    arguments: active_job.serialize,
    concurrency_key: active_job.concurrency_key
  }
end

DEFAULT_PRIORITY = 0 é uma constante do SolidQueue::Job. Então há dois padrões, de duas bibliotecas. O padrão do Rails é "sem opinião", nil, e o do Solid Queue é o piso que ele coloca no último momento possível, o INSERT. O curso de nível Pleno "Solid Queue: arquitetura de jobs" mostrou o que o número guardado controla quando já está na tabela: order(priority: :asc, job_id: :asc), a ordenação que toda reserva de jobs prontos usa. Esta aula para um passo antes, na decisão que o número representa.

O queue_with_priority, rodando

Este é um job descartável, rodado com bin/rails runner no banco da fila de desenvolvimento, dentro de uma transação desfeita depois:

class PriorityProbeJob < ApplicationJob
  self.queue_adapter = :solid_queue # desenvolvimento usa :async
  queue_as :probe
  queue_with_priority 20
  def perform(*); end
end

j1 = PriorityProbeJob.perform_later
SolidQueue::Job.find_by(active_job_id: j1.job_id).priority
stored priority = 20

20, o número da classe. O queue_with_priority define o priority da classe, o ActiveJob::Core#initialize o copia para a instância como @priority = self.class.priority, e o attributes_from_active_job o grava direto na linha.

O que os jobs da aplicação nunca decidiram

# app/jobs/partners/fetch_site_icon_job.rb
class Partners::FetchSiteIconJob < ApplicationJob
  queue_as :default
  # nenhum queue_with_priority em lugar nenhum deste arquivo
end

Então o Partners::FetchSiteIconJob#priority é nil, o attributes_from_active_job coloca o DEFAULT_PRIORITY, e toda linha que o job cria leva priority: 0. Ninguém decidiu que 0 era o certo para ele; ninguém decidiu nada, e 0 é onde a cadeia termina. O mesmo vale para todos os outros jobs da aplicação. É um fato sobre a aplicação, e não uma crítica: os jobs que dividem uma fila nunca precisaram de ordem entre si. O resto do curso trata do que muda quando precisarem.

Pontos-chave

  • O ActiveJob::QueuePriority#priority é nil até um job chamar queue_with_priority: o padrão do Rails é não ter opinião, e não 0.
  • O SolidQueue::Job.attributes_from_active_job coloca DEFAULT_PRIORITY = 0 só ao montar a linha, com active_job.priority || DEFAULT_PRIORITY. Esse piso é do Solid Queue, e não do Rails.
  • queue_with_priority 20 chega a solid_queue_jobs.priority sem mudança: entra 20, fica 20.
  • Nenhum job da aplicação chama queue_with_priority, então todos recebem prioridade 0 por padrão, e não por decisão.
Aula 1 de 7 · grátis

Continue com a aula 2

Prioridade estática vs dinâmica, e quem vence

Compara o queue_with_priority fixo e com bloco ao .set(priority:), que sobrescreve o valor da classe quando presente.

Com uma conta grátis você também tem os quizzes, seu progresso e suas anotações, e a discussão.

Digite para buscar...