feat: add conversation status counter cache with per-account backfill on feature enable

This commit is contained in:
Tanmay Deep Sharma
2026-02-24 16:24:10 +05:30
parent d0525660ab
commit d4992ad4c6
4 changed files with 41 additions and 25 deletions
@@ -0,0 +1,7 @@
class Internal::BackfillConversationCountersJob < ApplicationJob
queue_as :low
def perform(account)
Internal::BackfillConversationCountersService.new(account: account).perform
end
end
+8
View File
@@ -144,6 +144,7 @@ class Account < ApplicationRecord
before_validation :validate_limit_keys
after_create_commit :notify_creation
after_destroy :remove_account_sequences
after_save :backfill_conversation_counters_if_needed
def agents
users.where(account_users: { role: :agent })
@@ -208,6 +209,13 @@ class Account < ApplicationRecord
"execute format('create sequence IF NOT EXISTS camp_dpid_seq_%s', NEW.id);"
end
def backfill_conversation_counters_if_needed
return unless saved_change_to_feature_flags?
return unless feature_counter_cache_optimization?
Internal::BackfillConversationCountersJob.perform_later(self)
end
def validate_limit_keys
# method overridden in enterprise module
end
@@ -0,0 +1,26 @@
class Internal::BackfillConversationCountersService
# Backfills the conversation status counter cache columns on accounts
# (open_conversations_count, resolved_conversations_count, pending_conversations_count, snoozed_conversations_count).
#
# Safe to re-run to correct any drift.
#
# Usage:
# Internal::BackfillConversationCountersService.new.perform
# Internal::BackfillConversationCountersService.new(account: Account.find(id)).perform
#
def initialize(account: nil)
@account = account
end
def perform
scope = @account ? Account.where(id: @account.id) : Account.all
scope.find_each do |account|
account.update(
open_conversations_count: account.conversations.open.count,
resolved_conversations_count: account.conversations.resolved.count,
pending_conversations_count: account.conversations.pending.count,
snoozed_conversations_count: account.conversations.snoozed.count
)
end
end
end
@@ -1,25 +0,0 @@
class BackfillStatusConversationCounters < ActiveRecord::Migration[7.1]
def up
Account.find_each do |account|
# Count conversations by status for this account
open_count = account.conversations.open.count
resolved_count = account.conversations.resolved.count
pending_count = account.conversations.pending.count
snoozed_count = account.conversations.snoozed.count
# Update the counter cache columns
# rubocop:disable Rails/SkipsModelValidations
account.update_columns(
open_conversations_count: open_count,
resolved_conversations_count: resolved_count,
pending_conversations_count: pending_count,
snoozed_conversations_count: snoozed_count
)
# rubocop:enable Rails/SkipsModelValidations
end
end
def down
# No-op
end
end