【问题标题】:Delayed Jobs on Rails 2: can't save in "perform" method/how to know when job is done?Rails 2 上的延迟作业:无法保存“执行”方法/如何知道作业何时完成?
【发布时间】:2011-05-26 19:12:07
【问题描述】:

我正在使用 Rails 2 的延迟作业插件,每次我尝试修改模型并将其保存在延迟作业所需的“执行”方法中时,它都会失败(没有错误消息或任何东西,它只是在数据库中列为故障)。

我的一个 Rails 模型文件(视频)中有“执行”方法,并且我将该模型的一个实例(假设为@video)传递给 Delayed::Job.enqueue

您无法在队列中进行数据库修改是一个已知问题吗?我做错了什么吗(它只会在尝试保存时失败,而不是在我实际更改属性时失败,这听起来像是数据库修改问题)。

如果这是预期的:我该如何解决?我正在尝试将“完成”属性保存为 true,因此我知道模型何时准备好进入下一步。是否有一些标准方法可以确定延迟的工作何时完成?

编辑:我已经确认调用 perform Standalone(没有延迟工作)在保存方面没有问题(没有错误或警告,或任何东西)。当我通过 DelayedJobs 调用它时,它在到达保存行的第二秒立即失败(没有超时)。

编辑:等等,我想我知道发生了什么:我的“执行”是“after_create”回调的一部分......这一切都很好,直到我尝试保存。看起来当我保存时,它会再次调用 perform AGAIN (虽然已经在执行),并且不会与 Delayed Jobs 一起飞行(也不应该)。出于某种原因,我认为 after_create 只会被调用一次(而不是在每次保存之后)。等等,一个简单的测试表明情况确实如此。 hrrm... 那么为什么在延迟作业中执行时会在我保存时调用两次,而在我不保存时调用一次?

我的代码:

after_create :start_transcodes

 def start_transcodes
     Delayed::Job.enqueue self  
 end
     def perform
      puts "performing"
      self.flash_status = 100
      self.save!
      puts "done"
     end

我看到了什么:

    performing
    performing
2 jobs processed at 3.3406 j/s, 2 failed ...

我从来没有看到它说“完成”。

我在 Rails 日志中看到的是:

"* [JOB] Video failed with NameError: undefined local variable or method `flush_deletes' for #<Paperclip::Attachment:0xb6e51da0> - 2 failed attempts
undefined local variable or method `flush_deletes' for #<Paperclip::Attachment:0xb6e51da0>"

我正在为这个类使用回形针插件,我可以整天调用 save (即使在那个 perform 方法中)并且没有问题。我也可以整天调用 save(再次,甚至在执行中)并且看不到我的 after_create 方法被调用了不止一次——除非我正在使用延迟作业。(可能是在做某种自动重试?)

我要去看看我的回形针插件,看看发生了什么......

【问题讨论】:

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


    【解决方案1】:

    如果你的保存失败,它与delayed_job 无关(至少不应该如此,除非保存时间超过MAX_RUN_TIME。)

    尝试通过不使用延迟作业来诊断保存问题。

    还可以查看日志中的delayed_job.log 文件

    【讨论】:

    • 但是当我单独运行“执行”(没有延迟作业)时,没有任何问题,没有失败或错误或任何事情。如果它只是在延迟工作下出现问题,那是不是意味着它是一个延迟工作问题?我会检查日志文件,谢谢你的提示。
    • 呃,没有delayed_job.log文件。您是在谈论延迟作业如何写入正常的 Rails 日志文件(在这种情况下是开发日志?)?如果是这样,就像我说的那样,我没有收到任何错误消息,它只是说“2 个作业以 0.2683 j/s 的速度处理,2 个失败……”等等……两个作业?我想我明白了,请稍等……
    【解决方案2】:

    好的,不确定到底发生了什么,但我在我的 lib 目录中创建了一个骨架“TranscodeJob”类。这个类通过引用我希望它处理的视频进行初始化,然后处理它,保存它,并且可以很好地与延迟作业一起播放。

    基本上,将我的整个复杂的 Video 对象(包括回形针插件)传递给 Delayed Job 看起来有点吓人,而传递一个简单的对象,没有比它需要的更多信息,让事情变得容易得多。

    下面是我使用的代码,它运行良好(如果运行良好,我可以一点一点地添加我长时间运行的代码并确认它继续这样做,但它之前运行良好,只是在保存时打嗝)

    class TranscodeJob
     def initialize(video_id)
         @video_id = video_id           
     end
    
     #delayed jobs expected method
     def perform
          @video = Video.find(@video_id)
          @video.flash_status = 100
          @video.save!
     end
    

    结束

    这段代码仍然是从 after_create 过滤器调用的,我没有看到它被调用了两次,所以看起来我把 DelayedJobs 自动重试误认为是递归或其他什么。

    【讨论】:

      猜你喜欢
      • 2012-04-20
      • 1970-01-01
      • 2014-10-14
      • 2023-04-03
      • 2015-03-11
      • 1970-01-01
      • 1970-01-01
      • 2012-03-29
      • 1970-01-01
      相关资源
      最近更新 更多