From 475fc0483821e89df8f2c1f73772c11b71920893 Mon Sep 17 00:00:00 2001 From: Splines <37160523+Splines@users.noreply.github.com> Date: Wed, 17 Jan 2024 23:21:59 +0100 Subject: [PATCH] Migrate `unread_comments` flag (fix inconsistencies) (#587) * Add dummy migration * Implement migration for unread comment flag * Remove unnecessary comment * Declare migration as not idempotent * Use array.length instead of counting * Throw error to prevent revert of migration * Fix severe flaws in unread comments migration * Simplify Reader retrieval * Use the more explicit `.nil?` method * Update migration date * Fix annoying bug: don't use `.select!` but `.select` * Polish migration e.g. update comment, more suitable name for the method etc. * Rename method according to #585 --- ...000_fix_unread_comments_inconsistencies.rb | 56 +++++++++++++++++++ db/schema.rb | 2 +- 2 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 db/migrate/20240116180000_fix_unread_comments_inconsistencies.rb diff --git a/db/migrate/20240116180000_fix_unread_comments_inconsistencies.rb b/db/migrate/20240116180000_fix_unread_comments_inconsistencies.rb new file mode 100644 index 000000000..3392da3dc --- /dev/null +++ b/db/migrate/20240116180000_fix_unread_comments_inconsistencies.rb @@ -0,0 +1,56 @@ +# Fixes the unread_comments flag for all users. Unintended behavior was +# introduced in pull request #515. Migration introduced in #587. +# Behavior fixed in #585. +# +# This migration is generally *not* idempotent since users might have interacted +# with the website since the migration was run and thus they will probably have +# different unread comments flags as the ones at the time of the migration. +# +# This migration is not reversible as we don't store the previous state of +# the unread_comments flag. +class FixUnreadCommentsInconsistencies < ActiveRecord::Migration[7.0] + def up + num_fixed_users = 0 + + User.find_each do |user| + had_user_unread_comments = user.unread_comments # boolean + has_user_unread_comments = user_unread_comments?(user) + + has_flag_changed = (had_user_unread_comments != has_user_unread_comments) + user.update(unread_comments: has_user_unread_comments) if has_flag_changed + num_fixed_users += 1 if has_flag_changed + end + + Rails.logger.debug { "Ran through #{User.count} users (unread comments flag)" } + Rails.logger.debug { "Fixed #{num_fixed_users} users (unread comments flag)" } + end + + # Checks and returns whether the user has unread comments. + def user_unread_comments?(user) + # Check for unread comments -- directly via Reader + readers = Reader.where(user: user) + readers.each do |reader| + thread = Commontator::Thread.find_by(id: reader.thread_id) + next if thread.nil? + + latest_thread_comment_by_any_user = thread.comments.max_by(&:created_at) + next if latest_thread_comment_by_any_user.blank? + + latest_thread_comment_time = latest_thread_comment_by_any_user.created_at + has_user_unread_comments = reader.updated_at < latest_thread_comment_time + + return true if has_user_unread_comments + end + + # User might still have unread comments but no related Reader objects + # -> Check for unread comments -- via Media + unseen_media = user.subscribed_media_with_latest_comments_not_by_creator.select do |m| + m[:medium].visible_for_user?(user) + end + unseen_media.present? + end + + def down + raise ActiveRecord::IrreversibleMigration + end +end diff --git a/db/schema.rb b/db/schema.rb index 923aed6fb..0eb8c6842 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.0].define(version: 2023_11_01_100015) do +ActiveRecord::Schema[7.0].define(version: 2024_01_16_180000) do # These are extensions that must be enabled in order to support this database enable_extension "pgcrypto" enable_extension "plpgsql"