diff --git a/app/services/user_stat_count_updater.rb b/app/services/user_stat_count_updater.rb index af640417177..38810e5c689 100644 --- a/app/services/user_stat_count_updater.rb +++ b/app/services/user_stat_count_updater.rb @@ -22,6 +22,18 @@ class UserStatCountUpdater elsif post.post_type == Post.types[:regular] stat.public_send(action, :post_count) end + rescue ActiveRecord::StatementInvalid => e + if e.cause.is_a?(PG::CheckViolation) + # There are still spots in the code base which results in the counter cache going out of sync. However, + # we have a job that runs on a daily basis which will correct the count. Therefore, avoid raising an error for now + # and log the exception instead. + Discourse.warn_exception( + e, + message: "Attempted to insert negative count into UserStat#post_count or UserStat#topic_count" + ) + else + raise + end end end end diff --git a/spec/services/user_stat_count_updater_spec.rb b/spec/services/user_stat_count_updater_spec.rb new file mode 100644 index 00000000000..a765e97072d --- /dev/null +++ b/spec/services/user_stat_count_updater_spec.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +require 'rails_helper' + +describe UserStatCountUpdater do + fab!(:user) { Fabricate(:user) } + fab!(:user_stat) { user.user_stat } + fab!(:post) { Fabricate(:post) } + + before do + @orig_logger = Rails.logger + Rails.logger = @fake_logger = FakeLogger.new + end + + after do + Rails.logger = @orig_logger + end + + it 'should log the exception when a negative count is inserted' do + UserStatCountUpdater.decrement!(post, user_stat: user_stat) + + expect(@fake_logger.warnings.first).to include("PG::CheckViolation") + end +end