繁体   English   中英

如何确保ActiveRecord将更改保存到数据库

[英]How can I ensure that ActiveRecord is saving changes to the database

我有一个复杂的系统,涉及许多Resque工人,工作和监视过程。 这些作业具有父子依赖关系,并且它们通过一系列状态(使用state-machine )运行,这就是监视过程的原因。 我们依靠数据库状态来确保跨进程跟踪是同步的。

这是一个大概的想法:

class ParentMonitor < ActiveRecord::Base
  has_many children, class: ChildMonitor

  state_machine :state, initial: :work_needed do
    event :succeed do
      transition :work_needed => :work_succeeded
    end

    event :fail do
      transition :work_needed => :work_failed
    end
  end

  def child_transition
    return if children.any? { |child| child.work_needed? }

    if children.any? { |child| child.work_succeeded? }
      succeed
    else
      fail
    end
  end
end

class ChildMonitor < ActiveRecord::Base
  belongs_to: owner, class: ParentMonitor

  state_machine :state, initial: :work_needed do
    event :succeed do
      transition :work_needed => :work_succeeded
    end
    after_transition :to => :work_succeeded, :do => :notify_owner

    event :fail do
      transition :work_needed => :work_failed
    end
    after_transition :to => :work_failed, :do => :notify_owner
  end

  def notify_owner
    owner.child_transition
  end    
end

发生的事情是,对于前几个这样的工作(例如,数百个工作中有十二个或两个),即使所有孩子都处于work_succeededwork_failed状态, work_needed仍处于work_needed状态。 通过跟踪和测试,我确定每次调用ParentMonitor#child_transition ,都将依次减少处于“需要工作”状态的子级列表,直到在某个时候它会加载数据库并将所有子级替换为“需要的工作”。 即使某些内容以前已经完成。

另外,直到它突然开始记录更新之前,我在前几个孩子的日志文件中看不到任何UPDATE日志。 该日志记录与似乎要重置其所有子状态的记录同时进行。

它使我认为更改是由于某种缓存状态而在内存中发生的,但是我在整个过程中添加了reloadsavefind调用,它们似乎并没有影响更改。 我也尝试过将这些调用包装在非uncache但这无济于事。

事实证明这是由该写了在长时间运行的事务举行,因为状态机宝石保持打开的状态变化和任何结束之间的交易造成的事实after挂钩。 我们已经编写了在主要监视循环中运行了几个小时的钩子。

我们通过在状态更改之间而不是在回调中执行操作来解决此问题。

顺便说一句,错误行为与最新的《 红皮书》完全相同,这是在大多数RDMBS中实现的“弱隔离”并发的副作用:

异常示例包括读取另一个事务产生的中间数据,读取中止的数据,在执行同一事务期间读取同一项目的两个或多个不同值,以及由于并行写入同一项目而“丢失”事务的某些影响

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM