Module: IndexedSearch::Collision
- Included in:
- Word
- Defined in:
- lib/indexed_search/collision.rb
Overview
This implements a kind of optimistic duplication-prevention behavior without using any slow locking or anything like that.
The way it works is: certain column(s) get a unique index on them at the database level, so that you cannot create duplicate entries for them. If you were to try, you’d cause an ActiveRecord::RecordNotUnique error.
The expected scenario is like such: you look up and find the records you need, and if any aren’t found, you do a (relatively expensive) generation process for the new ones and insert them. You wrap this entire process in a special function that catches any insertion errors, and retries (including the looking-up of what is in there again).
This may sound similar to find_or_create_by_ already built into ActiveRecord, but it has one key difference: if your generation process is quite expensive, you only have to do it for missing records. If most of the time records should be found and not need to be generated, then this can give you significant time savings.
Other potential alternatives (each with other different drawbacks) include: MySQL’s INSERT ON DUPLICATE UPDATE and INSERT IGNORE and ANSI SQL’s MERGE
Defined Under Namespace
Classes: TooManyCollisionsException
Instance Method Summary collapse
-
#retrying_on_collision(retry_count = 0) ⇒ Object
usage like this:.
Instance Method Details
#retrying_on_collision(retry_count = 0) ⇒ Object
usage like this:
extend IndexedSearch::Collision def find_or_create_foos_ids(foos)
do
ids_hash = quick_find_current_foos_ids(foos)
foos.collect { |foo| ids_hash[foo] || expensive_create_foo_and_return_id(foo) }
end
end
or something else similar… :)
61 62 63 64 65 66 67 |
# File 'lib/indexed_search/collision.rb', line 61 def (retry_count=0) yield rescue ActiveRecord::RecordNotUnique raise TooManyCollisionsException.new('Too many db uniqueness collisions') if retry_count >= max_collision_retries sleep(rand(wait_time_seconds[retry_count])) (retry_count + 1) { yield } end |