Data fix migration to recompute unread conversations count. Fixes #8308

Current code that trigger incremental changes to users.unread_conversations_count
 appears to be correct. Believe the problem is a legacy data problem where data was
 incorrect from previous code issues and wasn't fixed previously.

 Test Plan:
 * setup a user with conversations
 * in the database, modify users.unread_conversations_count to be wrong (high or low)
 * run the migration and the conversation count should be corrected

Change-Id: Ibe5c1db2fb494e9800f89e9316f2a9519df77c43
Reviewed-on: https://gerrit.instructure.com/10702
Tested-by: Jenkins <jenkins@instructure.com>
Reviewed-by: Jon Jensen <jon@instructure.com>
This commit is contained in:
Mark Ericksen 2012-05-02 16:27:53 -06:00
parent 89ba5c1258
commit 8150cf2528
3 changed files with 129 additions and 0 deletions

View File

@ -0,0 +1,13 @@
class FixUserConversationsCountsForAll < ActiveRecord::Migration
tag :postdeploy
self.transactional = false
def self.up
DataFixup::RecomputeUnreadConversationsCount.send_later_if_production(:run)
end
def self.down
# The migration is non-destructive and only updates counts to reflect already existing data.
#raise ActiveRecord::IrreversibleMigration
end
end

View File

@ -0,0 +1,17 @@
module DataFixup::RecomputeUnreadConversationsCount
def self.run
# Include "last_message_at IS NOT NULL" to prevent it from counting unread deleted messages.
User.find_ids_in_batches do |ids|
User.connection.execute(User.send(:sanitize_sql_array, [<<-SQL, ids]))
UPDATE users u SET unread_conversations_count = (
SELECT COUNT(*)
FROM conversation_participants p
WHERE p.workflow_state = 'unread'
AND p.user_id = u.id
AND p.last_message_at IS NOT NULL
)
WHERE id IN (?)
SQL
end
end
end

View File

@ -0,0 +1,99 @@
#
# Copyright (C) 2011 Instructure, Inc.
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
#
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper.rb')
require 'db/migrate/20120502212620_fix_user_conversations_counts_for_all.rb'
describe FixUserConversationsCountsForAll do
describe "up" do
it "should fix incorrect entries and correctly count already correct entries" do
# Setup user with correct unread_conversations_count (2 unread convos)
u1 = user
2.times do
c = u1.initiate_conversation([u1.id], false)
c.add_message('Hello')
c.add_message('Hello again')
c.update_attribute(:workflow_state, 'unread')
end
# unread_conversations_count == 2
# Setup user with wrong unread_conversations_count (negative)
u2 = user
1.times do
c = u2.initiate_conversation([u2.id], false)
c.add_message('Hello')
c.add_message('Hello again')
c.update_attribute(:workflow_state, 'unread')
end
# unread_conversations_count == 1
u2.update_attribute(:unread_conversations_count, -3)
# Setup user with wrong unread_conversations_count (too many)
u3 = user
3.times do
c = u3.initiate_conversation([u3.id], false)
c.add_message('Hello')
c.add_message('Hello again')
c.update_attribute(:workflow_state, 'unread')
end
# unread_conversations_count == 3
u3.update_attribute(:unread_conversations_count, 10)
FixUserConversationsCountsForAll.up
u1.reload.unread_conversations_count.should == 2
u2.reload.unread_conversations_count.should == 1
u3.reload.unread_conversations_count.should == 3
end
it "should not count deleted entries" do
# Setup user with some deleted conversations
u1 = user
2.times do
c = u1.initiate_conversation([u1.id], false)
c.add_message('Hello')
c.add_message('Hello again')
c.update_attribute(:workflow_state, 'unread')
end
1.times do
c = u1.initiate_conversation([u1.id], false)
c.add_message('Deleted myself')
c.add_message('Empty yo')
c.update_attribute(:workflow_state, 'unread')
c.remove_messages(:all) # delete conversation (and all messages)
end
# unread_conversations_count == 2
# Setup user with only deleted conversations (should have count 0)
u2 = user
3.times do
c = u2.initiate_conversation([u2.id], false)
c.add_message('Hello')
c.add_message('Hello again')
c.update_attribute(:workflow_state, 'unread')
c.remove_messages(:all) # delete conversation (and all messages)
end
# unread_conversations_count == 0
FixUserConversationsCountsForAll.up
u1.reload.unread_conversations_count.should == 2
u2.reload.unread_conversations_count.should == 0
end
end
end