Find_or_create ActiveRecord :: Backup RecordNotUnique not working

Use of rubies 2.1.2 and rails 4.1.4. I have a unique restriction on the email column in my database. If there is a race condition when one thread creates a user and another tries to create a unique record exception at the same time. I try to handle this exception by repeating so that when it retries, it will find the client during SELECT in find_or_create.

However, it does not seem to work. It ends with retries and then throws an exception again.

Here is what I did initially:

retries = 10
begin
  user = User.find_or_create_by(:email => email)
rescue ActiveRecord::RecordNotUnique
  retry unless (retries-=1).zero? 
  raise   
end

Then I thought that connecting to the database cached the result of the SELECT query, making him think that the user still does not exist and continues to try to create it. To fix this, I tried using Model.uncached to disable query caching:

retries = 10
begin
  User.uncached do
    user = User.find_or_create_by(:email => email)
  end
rescue ActiveRecord::RecordNotUnique
  retry unless (retries-=1).zero? 
  raise   
end

`

This also does not work. I'm not sure what else needs to be done to fix this problem? Should I increase the number of attempts? Add a sleep delay between attempts? Is there a better way to clear the query cache (if this is a problem?)

Any ideas?

Thank!

+4
source share
1 answer

Postgres, upsert (https://github.com/jesjos/active_record_upsert), "ON CONFLICT DO NOTHING/UPDATE" .

User.upsert(email: email)

, , , :

class User < ActiveRecord::Base
  upsert_keys [:email]
end

: , , , SQL- , BEGIN/COMMIT.

0

Source: https://habr.com/ru/post/1663290/


All Articles