Question

Is there a way to deal with concurrency when using find_or_create_by in mongoid ?

I'm using Tag.find_or_create_by(name: "foo") to tag some items in my application.

In the Tag model I'm also using a uniqueness validation: validates_uniqueness_of :name

However, when a user sends multiple posts requests in a short period of time, then I get duplicate tags in my database.

I think I understand why this behaviour happens, but I have no idea how to make it work as intended. Any idea ?

Thanks !

Was it helpful?

Solution

I would flip this to two operations to make this atomic: 1) find 2) if not found then UPSERT

EDIT: Or, use a UNIQUE index and catch/dismiss unique exceptions thrown.

EDIT2:

To make this a "real answer" I'll elaborate.

To keep this a one transaction operation, you can ensure a unique index (http://docs.mongodb.org/manual/tutorial/create-a-unique-index/) on the fields you wish. Using find_or_create_by in a multithreaded fashion will work correctly, as long as you have the ability to catch and dismiss exceptions/errors that occur when a duplicate key is found (you'll have to look into the language your using)

Or convert this to two transactions. First do a find based on your criteria, if no result is found do an insert. Doing a normal insert here would also produce issues, however using an upsert operation (update with upsert option - http://docs.mongodb.org/manual/reference/method/db.collection.update/) this will insure uniqueness.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top