find_or_create_by using mongoid and sidekiq leads to duplication

Viewed 1525

Rails 4.0.2, Mongoid git alpha, sidekiq 2.17.0

Using a worker to parse a CSV file and put the contents into mongo, but running into several issues... Most obvious is a product with the same name end up as duplicate documents while using find_or_create_by.

class Category
  include Mongoid::Document
  field :title, type: String

  has_many :products
end

Class Product
  include Mongoid::Document
  field :name, type: String

  belongs_to: :category
end

Class ProductWorker
  include Sidekiq::Worker

  def perform(category, name)
    category = Category.find_or_create_by( title: category )
    product = Product.find_or_create_by(name: name)
    product.category = category
    product.save
  end
end

With a CSV file with only two products in the same category, I'll end up with two entries for category with the same name, each product in separate categories. When I remove sidekiq async and perform it on the model directly I get the correct result of 1 category with two relational products.

It makes sense that if the workers perform the find_and_create_by fast enough, both workers will find nil and thus create new objects. How can I prevent this?

2 Answers
Related