【问题标题】:Check whether I am in a delayed_job process or not检查我是否处于delayed_job 进程中
【发布时间】:2013-01-29 07:27:06
【问题描述】:

我有一个使用delayed_job 的Rails 应用程序。我想检测我是否处于delayed_job 进程中;像

if in_delayed_job?
  # do something only if it is a delayed_job process...
else
  # do something only if it is not a delayed_job process...
end

但我不知道怎么做。这是我现在使用的:

IN_DELAYED_JOB = begin
  basename        = File.basename $0
  arguments       = $*
  rake_args_regex = /\Ajobs:/

  ( basename == 'delayed_job' ) ||
  ( basename == 'rake' && arguments.find{ |v| v =~ rake_args_regex } )
end

另一个解决方案是,正如@MrDanA 所说:

$ DELAYED_JOB=true script/delayed_job start
# And in the app:
IN_DELAYED_JOB = ENV['DELAYED_JOB'].present?

但恕我直言,它们是弱解决方案。谁能提出更好的解决方案?

【问题讨论】:

  • 这是一种方法吗?向它发送一个标志以指示该作业是否是从延迟作业中调用的怎么样。它可以默认为 false,仅在从延迟作业实际调用时设置。如果您找不到其他任何东西,快速简便的解决方案。
  • 是的,这是另一种解决方案(我认为您的意思是DELAYED_JOB=true script/delayed_job start),但我认为这也是一个弱解决方案,因为我必须记住在使用延迟作业启动应用程序时设置或取消设置变量与否
  • 延迟作业启动时是否会自动运行此方法?我假设您正在做这样的事情:user.delay.send_email 在您的代码中某处。然后您可以将该行更改为user.delay.send_email(true),其中true 表示它被作为延迟作业的一部分调用。
  • 如何尝试停止(杀死)为该进程生成的工作人员,因为您会知道所生成的工作人员的 pid。如果它给出没有此类进程的错误,您可以假设您在外面的工作..
  • @MrDanA 问题是我想知道我是否在延迟作业过程中延迟作业方法之外...

标签: ruby-on-rails ruby delayed-job


【解决方案1】:

我处理这些问题的方式是通过一个偏执狂工人。我使用delayed_job 进行上传到我网站的视频转码。在视频模型中,我有一个名为 video_processing 的字段,默认设置为 0/null。每当视频被delayed_job 转码时(无论是创建还是更新视频文件),它都会使用delayed_job 中的钩子,并在作业开始时更新video_processing。作业完成后,已完成的钩子会将字段更新为 0。

在我的视图/控制器中我可以做到video.video_processing? ? "Video Transcoding in Progress" : "Video Fished Transcoding"

【讨论】:

  • 我使用delayed_job 来达到同样的目的;你用什么转码?我为avconv (libav.org/avconv.html) 写了一个Ruby wrapper 无论如何,我的问题是另一个:我想知道我的进程是否是delayed_job 进程
  • 我使用ffmpeg 对视频进行编码。我正在使用carrierwavecarrierwave-videodelayed_jobcarrierwave_backgrounder 来处理上传、转码、后台处理,并将上传发送到后台处理器进行转码。
  • 不知道carrierwave-video的存在,谢谢
  • 我为此提取了自己的存储库,因为我需要qt-faststart MP4。否则,它会在播放之前强制加载完整的视频。我没有使用 OGV 或 WEBM,所以效果很好。您可以查看我的存储库以查看更改。
【解决方案2】:

也许是这样的。在您的类中添加一个字段并在您调用从延迟作业中完成所有工作的方法时设置它:

class User < ActiveRecord::Base
  attr_accessor :in_delayed_job

   def queue_calculation_request
     Delayed::Job.enqueue(CalculationRequest.new(self.id))
   end

   def do_the_work
     if (in_delayed_job)
       puts "Im in delayed job"
     else
       puts "I was called directly"
     end
   end

   class CalculationRequest < Struct.new(:id)
     def perform
       user = User.find(id)
       user.in_delayed_job = true
       user.do_the_work
     end

     def display_name
       "Perform the needeful user Calculations"
     end
   end
end

这是它的外观:

来自延迟的作业:

Worker(host:Johns-MacBook-Pro.local pid:67020)] Starting job worker
Im in delayed job
[Worker(host:Johns-MacBook-Pro.local pid:67020)] Perform the needeful user Calculations completed after 0.2787
[Worker(host:Johns-MacBook-Pro.local pid:67020)] 1 jobs processed at 1.5578 j/s, 0 failed ...

从控制台

user = User.first.do_the_work
  User Load (0.8ms)  SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1  [["id", 101]]
I was called directly

【讨论】:

  • 问题是我想知道我是否在delayed_job procss outsidedelayed_job 方法...
  • 在上面的 do_the_work 中,如果你从 delay_job 以外的其他地方进来,in_delayed_job 将为 nil。你能扩展一下你所说的外部延迟工作方法的含义吗?
  • 对不起@JohnNaegle,我之前没有看到你的评论。我错了,我想说我需要知道我是否在之前开始工作,即DelayedJob 引导Rails 应用程序时,因为我需要在Rails 中使用它初始化器。您建议的方法是正确的,但仅适用于作业启动后加载的代码。
【解决方案3】:

这对我有用:

def delayed_job_worker?
  (ENV["_"].include? "delayed_job")
end

Unix 会将“_”环境变量设置为当前命令。

如果您有一个名为“not_a_delayed_job”的 bin 脚本,那就错了,但不要这样做。

【讨论】:

    【解决方案4】:

    ENV['PROC_TYPE'] 怎么样
    只说到heroku......但是当你是一个工人测功机时,这被设置为'工人' 我用它作为我的“我在 DJ”

    【讨论】:

    • 哦...如果您已经分叉了您的网络工作者以包括一个 DJ 工作者(因为为什么不使用第二个网络工作者)... 那么该工作者也处理 DJ 并且将 env 设置为“工人”
    【解决方案5】:

    您可以为延迟作业创建插件,例如在config/initializers目录下创建文件is_dj_job_plugin.rb

    class IsDjJobPlugin < Delayed::Plugin
    
      callbacks do |lifecycle|
        lifecycle.around(:invoke_job) do |job, *args, &block|
          begin
            old_is_dj_job = Thread.current[:is_dj_job]
            Thread.current[:is_dj_job] = true
            block.call(job, *args) # Forward the call to the next callback in the callback chain
            Thread.current[:is_dj_job] = old_is_dj_job
          end
        end
      end
    
      def self.is_dj_job?
        Thread.current[:is_dj_job] == true
      end
    end
    
    Delayed::Worker.plugins << IsDjJobPlugin
    

    然后您可以通过以下方式进行测试:

    class PrintDelayedStatus
      def run
        puts IsDjJobPlugin.is_dj_job? ? 'delayed' : 'not delayed'
      end
    end
    
    PrintDelayedStatus.new.run
    PrintDelayedStatus.new.delay.run
    

    【讨论】:

      猜你喜欢
      • 2020-04-16
      • 1970-01-01
      • 1970-01-01
      • 2011-03-10
      • 1970-01-01
      • 1970-01-01
      • 2013-03-05
      • 2012-08-31
      相关资源
      最近更新 更多