Ran
|
Files
460
|
Run time
24s
|
Badge
Embed ▾
README BADGES
|
travis-ci
Prevent further cases of perma id clashes Wrapping `RevisionComponent#save` in an advisory lock, does not suffice for cases where the revision component is created through an association, i.e revision.file_usages.create!(...) In this case `CollectionAssociation#_create_record` [1] already starts the transaction before the lock is required. Since the transaction is then committed only after the advisory lock is already released, the following race condition can occur: Thread 1: Thread 2: | | BEGIN | GET LOCK | SELECT MAX perma_id | INSERT revision component | RELEASE LOCK | | BEGIN | GET LOCK | SELECT MAX perma_id COMMIT | | INSERT revision component | RELEASE LOCK | COMMIT Since the first transaction is not yet finished, the second thread does not yet see the newly inserted perma id and calculates the same maximum. To ensure that the lock is acquired before the transaction starts, we add a new class method `create_with_lock!` which then delegates to `create!`. For existing revision components (and models that behave like revision components like `Page`) this race condition has never been a problem since concurrent inserts are not that likely within a revision (and we do not care about non-unique perma ids accross entries). We only noticed the problem for file usages now since those are created by a batch of requests when multiple files are uploaded at the same time. So for now we use the new `create_with_lock!` method only in `DraftEntry.create_file!`. [1] https://github.com/rails/rails/blob/b9ca94cae/activerecord/lib... (continued)
17194 of 17321 relevant lines covered (99.27%)
29.98 hits per line
Coverage | ∆ | File | Lines | Relevant | Covered | Missed | Hits/Line |
---|