首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >优先级如何在read_ahead中与delayed_job交互?

优先级如何在read_ahead中与delayed_job交互?
EN

Stack Overflow用户
提问于 2016-03-01 21:49:56
回答 1查看 1K关注 0票数 3

当delayed_job从队列中取出一个新作业时,它是否首先按照优先级对队列进行排序?如果没有,那么我猜低优先级的作业可以在高优先级之前运行,因为"read_ahead“。

来自delayed_job文档:

默认行为是在找到可用作业时从队列中读取5个作业。您可以通过设置Delayed::Worker.read_ahead来配置它。

示例:我添加了100个优先级为10的作业(先运行较低的优先级)。然后我添加了一个优先级为0的作业。如果我使用默认的read_ahead 5,delayed_job是否需要先处理96个作业,然后才能找到一个高优先级的作业?

EN

回答 1

Stack Overflow用户

发布于 2016-05-16 21:54:06

我有一个类似的问题,并深入到源代码中寻找答案--这是假设您在使用delayed_job_active_record。在后端/活动记录中:

代码语言:javascript
复制
  class Job < ::ActiveRecord::Base
    scope :by_priority, lambda { order("priority ASC, run_at ASC") }

    def self.reserve(worker, max_run_time = Worker.max_run_time) # rubocop:disable CyclomaticComplexity
      # scope to filter to records that are "ready to run"
      ready_scope = ready_to_run(worker.name, max_run_time)

      # scope to filter to the single next eligible job
      ready_scope = ready_scope.where("priority >= ?", Worker.min_priority) if Worker.min_priority
      ready_scope = ready_scope.where("priority <= ?", Worker.max_priority) if Worker.max_priority
      ready_scope = ready_scope.where(queue: Worker.queues) if Worker.queues.any?
      ready_scope = ready_scope.by_priority

      reserve_with_scope(ready_scope, worker, db_time_now)
    end

    def self.reserve_with_scope(ready_scope, worker, now)
      # Optimizations for faster lookups on some common databases
      case connection.adapter_name
      when "PostgreSQL"
        quoted_table_name = connection.quote_table_name(table_name)
        subquery_sql      = ready_scope.limit(1).lock(true).select("id").to_sql
        reserved          = find_by_sql(["UPDATE #{quoted_table_name} SET locked_at = ?, locked_by = ? WHERE id IN (#{subquery_sql}) RETURNING *", now, worker.name])
        reserved[0]
      when "MySQL", "Mysql2"
        now = now.change(usec: 0)
        count = ready_scope.limit(1).update_all(locked_at: now, locked_by: worker.name)
        return nil if count == 0
        where(locked_at: now, locked_by: worker.name, failed_at: nil).first
      when "MSSQL", "Teradata"
        subsubquery_sql = ready_scope.limit(1).to_sql
        subquery_sql = "SELECT id FROM (#{subsubquery_sql}) AS x"
        quoted_table_name = connection.quote_table_name(table_name)
        sql = ["UPDATE #{quoted_table_name} SET locked_at = ?, locked_by = ? WHERE id IN (#{subquery_sql})", now, worker.name]
        count = connection.execute(sanitize_sql(sql))
        return nil if count == 0
        where(locked_at: now, locked_by: worker.name, failed_at: nil).first
      else
        reserve_with_scope_using_default_sql(ready_scope, worker, now)
      end
    end

    def self.reserve_with_scope_using_default_sql(ready_scope, worker, now)
      # This is our old fashion, tried and true, but slower lookup
      ready_scope.limit(worker.read_ahead).detect do |job|
        count = ready_scope.where(id: job.id).update_all(locked_at: now, locked_by: worker.name)
        count == 1 && job.reload
      end
    end

因此,看起来优先级优先--当DelayedJob找到下一个要保留和运行的可用作业时,它首先按优先级排列,然后再尝试用"read_ahead“限制结果。

事实上,最后一个方法reserve_with_scope_using_default_sql是唯一提到"read_ahead“的地方,所以如果您使用的是Postgres或MySQL,那么它只会自动选择最高优先级的作业(限制1),而忽略"read_ahead”。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35734246

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档