lundi 14 novembre 2016

Unusual ActiveRecord Behavior

I'm encountering an unexpected situation with finding/creating particular records in the following table during periods of high contention. I believe there is a race condition in the database.

  create_table "business_objects", force: :cascade do |t| 
    t.string   "obj_id",     limit: 255 
    t.string   "obj_type",   limit: 255 
    t.datetime "created_at",             precision: 6, null: false
  end 

  add_index "business_objects", ["obj_type", "obj_id"], name: "index_business_objects_on_obj_type_and_obj_id", unique: true, using: :btree

Offending code:

def find_or_create_this
 attributes = self.attributes.slice('obj_id', 'obj_type')
 BusinessObject.find_or_create_by!(attributes) 
rescue ActiveRecord::RecordNotUnique
  BusinessObject.find_by!(attributes)
end

The find in the find_or_create_by! returns nil and triggers the create! which raises a ActiveRecord::RecordNotUnique error. The rescue block catches it and attempts to find the record which caused the not unique error but it also returns nil. My expectation is that if the index uniqueness constraint is violated than the record should be committed to the table. What am I missing?

Aucun commentaire:

Enregistrer un commentaire