Mongoid 3中Rails模型的强一致性

jst*_*tim 6 ruby ruby-on-rails-3 mongoid3

我希望特定模型的所有数据库交互都通过集群中的mongo主数据库,因此我将模型设置为使用强一致性.

class Photo
  include Mongoid::Document
  with consistency: :strong

  field :number, type: Integer
  # let's say a photo number is unique in the db
  validate :unique_number
end
Run Code Online (Sandbox Code Playgroud)

但这似乎不起作用,因为当我将两张照片非常靠近地保存在一起时,我仍然遇到验证错误.

photo1 # db has number=1 for this object
photo1.update_attributes(number: 2)
photo2.number = 1
photo2.save! # <= this raises a validation exception
Run Code Online (Sandbox Code Playgroud)

我对强一致性的理解是,这里不应该有比赛.它应该执行写入然后执行读取,因为它完全不在主要内容,所以不应该发生冲突.我错过了什么?

jst*_*tim 0

事实证明,with(consistency: :strong)在类级别的调用仅将其应用于下一个查询。因此,在加载类时会调用类方法,为第一个查询设置强一致性,但后续查询不会触发相同的类方法,从而使它们的持久性操作以最终一致性进行操作。来自 Mongoid 3.1.7文档:

告诉下一个持久性[原文如此]操作存储在特定的集合、数据库或会话中。

此方法不强制可以传入的持久性选项(就像类中的其他一些方法一样),因此我们也可以传入consistency: :strong.

黑客修复

为了将其应用于每个*持久性操作,我将其添加到default_scope.

class App
  default_scope -> { with(consistency: :strong); where({}) }
end
Run Code Online (Sandbox Code Playgroud)

在这种情况下,默认作用域期望返回一个 Mongoid Criteria 对象,因此我们where在设置正在进行的持久性操作的一致性级别后返回一个 noop 子句。

* 如果开发人员决定调用unscoped并剥离default_scope.