summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStan Hu <stanhu@gmail.com>2015-10-17 00:55:33 -0700
committerStan Hu <stanhu@gmail.com>2015-10-17 00:58:14 -0700
commitca3ce5c26c60de421e010491cf9166f2090c8cc8 (patch)
treec16a7a99b45bf48c13daa3804e92e2075c9a5149
parentc856a7a5934fba13598be09507c2090888f57a39 (diff)
downloadgitlab-ce-ca3ce5c26c60de421e010491cf9166f2090c8cc8.tar.gz
Fix nonatomic database update potentially causing project star counts to go negative
The counter_cache decrement function is called when a project star is deleted, but there was no guarantee multiple workers would not attempt to delete the same item simultaneously. Use an atomic update to prevent the count from going negative. Closes #3067
-rw-r--r--CHANGELOG1
-rw-r--r--app/models/user.rb15
2 files changed, 10 insertions, 6 deletions
diff --git a/CHANGELOG b/CHANGELOG
index a1161a7a527..2c8df909441 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -5,6 +5,7 @@ v 8.2.0 (unreleased)
- Highlight comment based on anchor in URL
v 8.1.0 (unreleased)
+ - Fix nonatomic database update potentially causing project star counts to go negative (Stan Hu)
- Fix error preventing displaying of commit data for a directory with a leading dot (Stan Hu)
- Speed up load times of issue detail pages by roughly 1.5x
- Add a system note and update relevant merge requests when a branch is deleted or re-added (Stan Hu)
diff --git a/app/models/user.rb b/app/models/user.rb
index 17ccb3b8788..3b346c55edb 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -706,12 +706,15 @@ class User < ActiveRecord::Base
end
def toggle_star(project)
- user_star_project = users_star_projects.
- where(project: project, user: self).take
- if user_star_project
- user_star_project.destroy
- else
- UsersStarProject.create!(project: project, user: self)
+ UsersStarProject.transaction do
+ user_star_project = users_star_projects.
+ where(project: project, user: self).lock(true).first
+
+ if user_star_project
+ user_star_project.destroy
+ else
+ UsersStarProject.create!(project: project, user: self)
+ end
end
end