How can I make the following controller threadsafe in rails 4 with postgresql:
def controller_action
if Model.exists(column_name:"some_value")
else
@model=Model.new(column_name:"some_value")
@model.save
end
end
I am running puma, so my concern is that if two threads run this controller at the same time, and a row doesn't exist with the specified value of column_name, two records will be created whereas I only want 1.
Assume that threads have a 1:1 relationship with connections. So if you have 100 threads that need to access the database, you should crank the connection pool up to 100. If you have more worker threads than connections, you need to use a Queue (or some other thread safe data structure) to manage communication between them.
Contrary to the comments, concurrent inserts on the same table are entirely permissible in PostgreSQL, so there's a race condition here.
To make this safe you must have a
unique
constraint (orprimary key
) oncolumn_name
. Duplicate inserts will then throw an exception which you can catch and retry with an update.If you don't have a unique constraint, then you must
LOCK TABLE ... IN EXCLUSIVE MODE
to prevent concurrent upserts. Or use one of the concurrency-safe methods described in:How to UPSERT (MERGE, INSERT ... ON DUPLICATE UPDATE) in PostgreSQL?