From 93a1ab9030a358348addd55d5e18caaaec2d3a37 Mon Sep 17 00:00:00 2001 From: Eugen Rochko Date: Sun, 28 Oct 2018 06:40:45 +0100 Subject: [PATCH] Add progress indicators to MigrateAccountConversations (#9101) * Add progress indicators to MigrateAccountConversations * Avoid running expensive query for explain * Use exec_query instead of execute --- ...024224956_migrate_account_conversations.rb | 50 +++++++++++++++---- 1 file changed, 41 insertions(+), 9 deletions(-) diff --git a/db/migrate/20181024224956_migrate_account_conversations.rb b/db/migrate/20181024224956_migrate_account_conversations.rb index 1821e8c27..47f7375ba 100644 --- a/db/migrate/20181024224956_migrate_account_conversations.rb +++ b/db/migrate/20181024224956_migrate_account_conversations.rb @@ -14,12 +14,29 @@ class MigrateAccountConversations < ActiveRecord::Migration[5.2] sleep 1 end - local_direct_statuses.find_each do |status| + total = estimate_rows(local_direct_statuses) + estimate_rows(notifications_about_direct_statuses) + migrated = 0 + started_time = Time.zone.now + last_time = Time.zone.now + + local_direct_statuses.includes(:account, mentions: :account).find_each do |status| AccountConversation.add_status(status.account, status) + migrated += 1 + + if Time.zone.now - last_time > 1 + say_progress(migrated, total, started_time) + last_time = Time.zone.now + end end - notifications_about_direct_statuses.find_each do |notification| + notifications_about_direct_statuses.includes(:account, mention: { status: [:account, mentions: :account] }).find_each do |notification| AccountConversation.add_status(notification.account, notification.target_status) + migrated += 1 + + if Time.zone.now - last_time > 1 + say_progress(migrated, total, started_time) + last_time = Time.zone.now + end end end @@ -28,16 +45,31 @@ class MigrateAccountConversations < ActiveRecord::Migration[5.2] private + def estimate_rows(query) + result = exec_query("EXPLAIN #{query.to_sql}").first + result['QUERY PLAN'].scan(/ rows=([\d]+)/).first&.first&.to_i || 0 + end + + def say_progress(migrated, total, started_time) + status = "Migrated #{migrated} rows" + + percentage = 100.0 * migrated / total + status += " (~#{sprintf('%.2f', percentage)}%, " + + remaining_time = (100.0 - percentage) * (Time.zone.now - started_time) / percentage + + status += "#{(remaining_time / 60).to_i}:" + status += sprintf('%02d', remaining_time.to_i % 60) + status += ' remaining)' + + say status, true + end + def local_direct_statuses - Status.unscoped - .local - .where(visibility: :direct) - .includes(:account, mentions: :account) + Status.unscoped.local.where(visibility: :direct) end def notifications_about_direct_statuses - Notification.joins(mention: :status) - .where(activity_type: 'Mention', statuses: { visibility: :direct }) - .includes(:account, mention: { status: [:account, mentions: :account] }) + Notification.joins(mention: :status).where(activity_type: 'Mention', statuses: { visibility: :direct }) end end