Is find_or_create_by thread safe in Mongoid?

孤街浪徒 提交于 2019-12-23 19:12:01

问题


I have a web app that uses Mongoid's find_or_create_by method.

poll = Poll.find_or_create_by(fields)

Before we go into production, I am trying to run through the failure scenarios, and it occurred to me that multiple users could try to access this resource using this method. Is there any likelihood that it could create multiple instances of the same object? What can I do to prevent that?


回答1:


Disclaimer: I'm new to Mongoid and Rails so I could be totally wrong.

Looking at modifiable.rb and many.rb it doesn't appear to lock on any resource.

It looks to me like it simply does a "where().first" query and then if that does not return anything it performs a "create" query:

 def find_or(method, attrs = {}, &block)
    where(attrs).first || send(method, attrs, &block)
  end

For find_or_create_by, "send" would call "create_document":

def create_document(method, attrs = nil, &block)
    klass.__send__(method,
      selector.reduce(attrs || {}) do |hash, (key, value)|
        unless key.to_s =~ /\$/ || value.is_a?(Hash)
          hash[key] = value
        end
        hash
      end, &block)
  end

Conclusion: To me this appears to be a convenience method, do not expect it to be "thread-safe". I wish there was more documentation available on this method.




回答2:


sometimes it is not worth to implement a thread-safe code in MRI. because most of the time we have to go multiprocess deployments. so the easiest solution is database level uniqueness validations.

class Person
  include Mongoid::Document
  field :ssn
  index({ ssn: 1 }, { unique: true })
end

so when save failed rollback the transaction. keep in mind that model level uniqueness validation is also error-prone.



来源:https://stackoverflow.com/questions/13072866/is-find-or-create-by-thread-safe-in-mongoid

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!