FIX: remove faulty "ensure consistency" badge job

This commit is contained in:
Sam 2014-08-11 09:21:06 +10:00
parent b8d7fb8735
commit 22cd259687
6 changed files with 55 additions and 35 deletions

View file

@ -9,8 +9,6 @@ module Jobs
Group.refresh_automatic_groups! Group.refresh_automatic_groups!
Notification.ensure_consistency! Notification.ensure_consistency!
UserAction.ensure_consistency! UserAction.ensure_consistency!
UserBadge.ensure_consistency!
# ensure consistent
UserStat.update_view_counts(13.hours.ago) UserStat.update_view_counts(13.hours.ago)
end end
end end

View file

@ -773,8 +773,8 @@ end
# uploaded_avatar_id :integer # uploaded_avatar_id :integer
# email_always :boolean default(FALSE), not null # email_always :boolean default(FALSE), not null
# mailing_list_mode :boolean default(FALSE), not null # mailing_list_mode :boolean default(FALSE), not null
# primary_group_id :integer
# locale :string(10) # locale :string(10)
# primary_group_id :integer
# registration_ip_address :inet # registration_ip_address :inet
# last_redirected_to_top_at :datetime # last_redirected_to_top_at :datetime
# disable_jump_reply :boolean default(FALSE), not null # disable_jump_reply :boolean default(FALSE), not null

View file

@ -17,34 +17,6 @@ class UserBadge < ActiveRecord::Base
after_destroy do after_destroy do
Badge.decrement_counter 'grant_count', self.badge_id Badge.decrement_counter 'grant_count', self.badge_id
end end
# Make sure we don't have duplicate badges.
def self.ensure_consistency!
dup_ids = exec_sql("SELECT u1.id
FROM user_badges u1, user_badges u2, badges
WHERE u1.badge_id = badges.id
AND u1.user_id = u2.user_id
AND u1.badge_id = u2.badge_id
AND (NOT badges.multiple_grant)
AND u1.granted_at > u2.granted_at
LIMIT 1000").to_a
dup_ids << exec_sql("SELECT u1.id
FROM user_badges u1, user_badges u2, badges
WHERE u1.badge_id = badges.id
AND u1.user_id = u2.user_id
AND u1.badge_id = u2.badge_id
AND badges.multiple_grant
AND u1.post_id = u2.post_id
AND u1.granted_at > u2.granted_at
LIMIT 1000").to_a
dup_ids.flatten!
dup_ids.map! {|row| row['id'].to_i }
dup_ids.uniq!
UserBadge.where(id: dup_ids).destroy_all
end
end end
# == Schema Information # == Schema Information
@ -58,9 +30,11 @@ end
# granted_by_id :integer not null # granted_by_id :integer not null
# post_id :integer # post_id :integer
# notification_id :integer # notification_id :integer
# seq :integer default(0), not null
# #
# Indexes # Indexes
# #
# index_user_badges_on_badge_id_and_user_id (badge_id,user_id) # index_user_badges_on_badge_id_and_user_id (badge_id,user_id)
# index_user_badges_on_badge_id_and_user_id_and_post_id (badge_id,user_id,post_id) UNIQUE # index_user_badges_on_badge_id_and_user_id_and_post_id (badge_id,user_id,post_id) UNIQUE
# index_user_badges_on_badge_id_and_user_id_and_seq (badge_id,user_id,seq) UNIQUE
# #

View file

@ -23,17 +23,27 @@ class BadgeGranter
if user_badge.nil? || (@badge.multiple_grant? && @post_id.nil?) if user_badge.nil? || (@badge.multiple_grant? && @post_id.nil?)
UserBadge.transaction do UserBadge.transaction do
user_badge = UserBadge.create!(badge: @badge, user: @user, seq = 0
if @badge.multiple_grant?
seq = UserBadge.where(badge: @badge, user: @user).maximum(:seq)
seq = (seq || -1) + 1
end
user_badge = UserBadge.create!(badge: @badge,
user: @user,
granted_by: @granted_by, granted_by: @granted_by,
granted_at: Time.now, granted_at: Time.now,
post_id: @post_id) post_id: @post_id,
seq: seq)
if @granted_by != Discourse.system_user if @granted_by != Discourse.system_user
StaffActionLogger.new(@granted_by).log_badge_grant(user_badge) StaffActionLogger.new(@granted_by).log_badge_grant(user_badge)
end end
if SiteSetting.enable_badges? if SiteSetting.enable_badges?
notification = @user.notifications.create(notification_type: Notification.types[:granted_badge], data: { badge_id: @badge.id, badge_name: @badge.name }.to_json) notification = @user.notifications.create(
notification_type: Notification.types[:granted_badge],
data: { badge_id: @badge.id, badge_name: @badge.name }.to_json)
user_badge.update_attributes notification_id: notification.id user_badge.update_attributes notification_id: notification.id
end end
end end

View file

@ -0,0 +1,34 @@
class AddUserBadgeUniqueIndex < ActiveRecord::Migration
def up
# used to keep badges distinct
add_column :user_badges, :seq, :integer, default: 0, null: false
# invent artificial seq for badges
execute "
UPDATE user_badges ub1 SET seq = X.seq
FROM (
SELECT ub.id, rank() OVER (PARTITION BY user_id ORDER BY granted_at) seq
FROM user_badges ub
JOIN badges b ON b.id = ub.badge_id
WHERE b.multiple_grant
) X
WHERE ub1.id = X.id
"
# delete all single award dupes
execute "
DELETE FROM user_badges ub1
WHERE ub1.id NOT IN (
SELECT MIN(ub.id)
FROM user_badges ub
GROUP BY ub.user_id, ub.badge_id, ub.seq
)
"
add_index :user_badges, [:badge_id, :user_id, :seq], unique: true, where: 'post_id IS NULL'
end
def down
remove_column :user_badges, :seq, :integer
end
end

View file

@ -50,9 +50,13 @@ describe BadgeGranter do
describe 'grant' do describe 'grant' do
it 'grants a badge' do it 'grants multiple badges' do
badge = Fabricate(:badge, multiple_grant: true)
user_badge = BadgeGranter.grant(badge, user)
user_badge = BadgeGranter.grant(badge, user) user_badge = BadgeGranter.grant(badge, user)
user_badge.should be_present user_badge.should be_present
UserBadge.where(user_id: user.id).count.should == 2
end end
it 'sets granted_at' do it 'sets granted_at' do