dependent :: destroy - 我可以延迟这个延迟工作吗?

时间:2015-07-16 15:25:20

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

我有两个模型,一个存储事件,另一个是日历模型的连接模型。连接模型与远程Calendar API集成,并在创建或删除时通过API调用自行管理(通过before_save和before_destroy回调)。

当一次删除一个连接模型记录时,这很有用,但由于我已经依赖于::在我的事件模型中定义的has_many关联上销毁(我不希望远程日历中的孤立事件),删除单个事件将导致N api调用(其中N是连接模型记录的数量,假设可能是数千个),这很容易导致超时。

理想情况下,我想延迟CalendarEvent.destroy调用,但仅限于从删除事件调用它时。例如:

Event.destroy [在所有CalendarEvent(连接模型)记录上调用delay.destroy] CalendarEvent.destroy [destroy without delayed_job]

有没有办法通过has_many调用来延迟这个?

有没有办法通过依赖传递自定义destroy方法:?

在CalendarEvent.destroy方法中,是否有办法知道是否从依赖的:: destroy定义调用它?

2 个答案:

答案 0 :(得分:1)

  

有没有办法通过has_many调用来延迟这个?

没有。

  

有没有办法通过依赖传递自定义destroy方法:?

也没有; the docs中只有少数已接受的选项:

  

:destroy导致所有相关对象也被销毁。

     

:delete_all导致所有关联对象直接从数据库中删除(因此不会执行回调)。

     

:nullify导致外键设置为NULL。回调不会被执行。

     

:如果存在任何关联记录,restrict_with_exception会引发异常。

     

:如果存在任何关联对象,restrict_with_error会将错误添加到所有者。

  

在CalendarEvent.destroy方法中,是否有办法知道是否从依赖的:: destroy定义中调用它?

你可以在技术上嗅探caller中的堆栈轨迹,但这听起来并不是一个好主意。

我删除dependent:选项并构建一个自定义after_destroy,以延迟方式清理CalendarEvent个对象。

after_destroy :destroy_calendar_events

def destroy_calendar_events
  calendar_events.each {|event| event.delay.destroy }
end

很久以前,我工作的一家公司用Async Observer解决了这个问题,它提供了async_destroy方法,但这是基于Beanstalk的,需要进行调整。如果你想烘烤一些东西,代码可能会很有趣。

答案 1 :(得分:1)

Kristján的答案可能会奏效,但我遇到了外键问题。没有依赖的外键::: destroy不想工作。

然后我遇到了delayed_job的问题,如果我试图延迟API服务对象本身,想要在DB条目中存储我的延迟作业的RSA密钥。让人惊讶。它无论如何都没有验证(空)键,所以它在2个方面失败了。

然后我尝试在创建新API对象的对象实例上延迟一个方法。当然它失败了,因为延迟的作业试图加载对象(已经被破坏)来运行作业。咂额头,尖叫,拉头发,重复。

最终工作的是调用类方法(或者它实际上可能是外部服务对象等),只传入字符串(不计入任何可以删除的对象以提供必要的信息)。

class CalendarEvent

  # bunch o' stuff

  def destroy
    self.class.delay.remove_remote_event!(user, remote_calendar_id, remote_id)
  super
  end

  def self.remove_remote_event!(user, remote_calendar_id, remote_id)
    EpGoogle::Interfaces::Calendar.new(user.email).delete_event(remote_calendar_id, remote_id)
  end

end

...然后DelayedJob能够成功运行任务。

它并不像我想的那样棒,因为如果作业失败,远程事件可能会孤立,但对我的用例来说这已经足够了。

相关问题