mirror of
https://github.com/glitch-soc/mastodon.git
synced 2026-03-29 03:00:33 +02:00
Fix last_status_at not accurately tracking last status time for remote accounts (#37619)
This commit is contained in:
@@ -20,8 +20,8 @@ module Account::Counters
|
||||
to: :account_stat
|
||||
|
||||
# @param [Symbol] key
|
||||
def increment_count!(key)
|
||||
update_count!(key, 1)
|
||||
def increment_count!(key, status_created_at: nil)
|
||||
update_count!(key, 1, status_created_at:)
|
||||
end
|
||||
|
||||
# @param [Symbol] key
|
||||
@@ -31,11 +31,11 @@ module Account::Counters
|
||||
|
||||
# @param [Symbol] key
|
||||
# @param [Integer] value
|
||||
def update_count!(key, value)
|
||||
def update_count!(key, value, status_created_at: nil)
|
||||
raise ArgumentError, "Invalid key #{key}" unless ALLOWED_COUNTER_KEYS.include?(key)
|
||||
raise ArgumentError, 'Do not call update_count! on dirty objects' if association(:account_stat).loaded? && account_stat&.changed? && account_stat.changed_attribute_names_to_save == %w(id)
|
||||
|
||||
result = updated_account_stat(key, value.to_i)
|
||||
result = updated_account_stat(key, value.to_i, status_created_at:)
|
||||
|
||||
# Reload account_stat if it was loaded, taking into account newly-created unsaved records
|
||||
if association(:account_stat).loaded?
|
||||
@@ -50,25 +50,27 @@ module Account::Counters
|
||||
|
||||
private
|
||||
|
||||
def updated_account_stat(key, value)
|
||||
def updated_account_stat(key, value, status_created_at: nil)
|
||||
status_created_at = Time.now.utc if status_created_at.nil? || status_created_at > Time.now.utc
|
||||
|
||||
AccountStat.upsert(
|
||||
initial_values(key, value),
|
||||
initial_values(key, value, status_created_at:),
|
||||
on_duplicate: Arel.sql(
|
||||
duplicate_values(key, value).join(', ')
|
||||
duplicate_values(key, value, status_created_at:).join(', ')
|
||||
),
|
||||
unique_by: :account_id
|
||||
)
|
||||
end
|
||||
|
||||
def initial_values(key, value)
|
||||
def initial_values(key, value, status_created_at: nil)
|
||||
{ :account_id => id, key => [value, 0].max }.tap do |values|
|
||||
values.merge!(last_status_at: Time.current) if key == :statuses_count
|
||||
values.merge!(last_status_at: status_created_at) if key == :statuses_count
|
||||
end
|
||||
end
|
||||
|
||||
def duplicate_values(key, value)
|
||||
def duplicate_values(key, value, status_created_at: nil)
|
||||
["#{key} = (account_stats.#{key} + #{value})", 'updated_at = CURRENT_TIMESTAMP'].tap do |values|
|
||||
values << 'last_status_at = CURRENT_TIMESTAMP' if key == :statuses_count && value.positive?
|
||||
values << AccountStat.sanitize_sql_array(['last_status_at = GREATEST(account_stats.last_status_at, ?::timestamp)', status_created_at]) if key == :statuses_count && value.positive?
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -481,7 +481,7 @@ class Status < ApplicationRecord
|
||||
def increment_counter_caches
|
||||
return if direct_visibility?
|
||||
|
||||
account&.increment_count!(:statuses_count)
|
||||
account&.increment_count!(:statuses_count, status_created_at: created_at)
|
||||
reblog&.increment_count!(:reblogs_count) if reblog?
|
||||
thread&.increment_count!(:replies_count) if in_reply_to_id.present? && distributable?
|
||||
end
|
||||
|
||||
@@ -21,6 +21,28 @@ RSpec.describe Account::Counters do
|
||||
|
||||
expect(account.statuses_count).to eq increment_by
|
||||
end
|
||||
|
||||
it 'updates last_status_at when discovering a new post' do
|
||||
status_created_at = Time.now.utc
|
||||
|
||||
expect { account.increment_count!(:statuses_count, status_created_at:) }
|
||||
.to(change { account.reload.last_status_at })
|
||||
end
|
||||
|
||||
it 'does not update last_status_at when discovering an older post' do
|
||||
account_stat = Fabricate(
|
||||
:account_stat,
|
||||
account: account,
|
||||
last_status_at: 1.day.ago.utc,
|
||||
statuses_count: 10
|
||||
)
|
||||
|
||||
status_created_at = 2.days.ago.utc
|
||||
|
||||
expect { account.increment_count!(:statuses_count, status_created_at:) }
|
||||
.to change { account_stat.reload.statuses_count }
|
||||
.and(not_change { account_stat.reload.last_status_at })
|
||||
end
|
||||
end
|
||||
|
||||
describe '#decrement_count!' do
|
||||
|
||||
Reference in New Issue
Block a user