use counter culture and move the optimisation under feature flag
This commit is contained in:
@@ -12,6 +12,7 @@ gem 'bootsnap', require: false
|
||||
gem 'acts-as-taggable-on'
|
||||
gem 'attr_extras'
|
||||
gem 'browser'
|
||||
gem 'counter_culture'
|
||||
gem 'hashie'
|
||||
gem 'jbuilder'
|
||||
gem 'kaminari'
|
||||
|
||||
@@ -191,6 +191,9 @@ GEM
|
||||
commonmarker (0.23.10)
|
||||
concurrent-ruby (1.3.5)
|
||||
connection_pool (2.5.3)
|
||||
counter_culture (3.12.1)
|
||||
activerecord (>= 4.2)
|
||||
activesupport (>= 4.2)
|
||||
crack (1.0.0)
|
||||
bigdecimal
|
||||
rexml
|
||||
@@ -1039,6 +1042,7 @@ DEPENDENCIES
|
||||
byebug
|
||||
climate_control
|
||||
commonmarker
|
||||
counter_culture
|
||||
csv-safe
|
||||
database_cleaner
|
||||
datadog (~> 2.0)
|
||||
|
||||
@@ -2,6 +2,9 @@ class ConversationFinder
|
||||
attr_reader :current_user, :current_account, :params
|
||||
|
||||
DEFAULT_STATUS = 'open'.freeze
|
||||
# Filter params that affect conversation count
|
||||
# NOTE: When adding a new filter, add it here to prevent incorrect cache usage
|
||||
FILTER_PARAMS = %i[inbox_id team_id labels q source_id conversation_type].freeze
|
||||
SORT_OPTIONS = {
|
||||
'last_activity_at_asc' => %w[sort_on_last_activity_at asc],
|
||||
'last_activity_at_desc' => %w[sort_on_last_activity_at desc],
|
||||
@@ -167,10 +170,25 @@ class ConversationFinder
|
||||
end
|
||||
|
||||
def set_count_for_all_conversations
|
||||
# Check if filtering by status only (no other filters applied)
|
||||
filtering_by_status_only = FILTER_PARAMS.none? { |key| params[key].present? }
|
||||
|
||||
# Use cache if feature is enabled, filtering by status only, and status is not 'all'
|
||||
use_cache = current_account.feature_enabled?(:counter_cache_optimization) &&
|
||||
filtering_by_status_only &&
|
||||
params[:status] != 'all'
|
||||
|
||||
all_count = if use_cache
|
||||
status = params[:status] || DEFAULT_STATUS
|
||||
current_account.public_send("#{status}_conversations_count")
|
||||
else
|
||||
@conversations.count
|
||||
end
|
||||
|
||||
[
|
||||
@conversations.assigned_to(current_user).count,
|
||||
@conversations.unassigned.count,
|
||||
current_account.conversations_count
|
||||
all_count
|
||||
]
|
||||
end
|
||||
|
||||
|
||||
@@ -97,7 +97,9 @@ class Conversation < ApplicationRecord
|
||||
).sort_on_last_user_message_at
|
||||
}
|
||||
|
||||
belongs_to :account, counter_cache: true
|
||||
belongs_to :account
|
||||
counter_culture :account,
|
||||
column_name: proc { |model| "#{model.status}_conversations_count" }
|
||||
belongs_to :inbox
|
||||
belongs_to :assignee, class_name: 'User', optional: true, inverse_of: :assigned_conversations
|
||||
belongs_to :assignee_agent_bot, class_name: 'AgentBot', optional: true
|
||||
|
||||
@@ -241,3 +241,7 @@
|
||||
display_name: Required Conversation Attributes
|
||||
enabled: false
|
||||
premium: true
|
||||
- name: counter_cache_optimization
|
||||
display_name: Counter Cache Optimization
|
||||
enabled: false
|
||||
chatwoot_internal: true
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
class AddConversationsCountToAccounts < ActiveRecord::Migration[7.1]
|
||||
def change
|
||||
add_column :accounts, :conversations_count, :integer, default: 0, null: false
|
||||
end
|
||||
end
|
||||
@@ -1,11 +0,0 @@
|
||||
class BackfillConversationsCount < ActiveRecord::Migration[7.1]
|
||||
def up
|
||||
Account.find_each do |account|
|
||||
Account.reset_counters(account.id, :conversations)
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
# No-op
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,8 @@
|
||||
class AddStatusConversationCountersToAccounts < ActiveRecord::Migration[7.1]
|
||||
def change
|
||||
add_column :accounts, :open_conversations_count, :integer, default: 0, null: false
|
||||
add_column :accounts, :resolved_conversations_count, :integer, default: 0, null: false
|
||||
add_column :accounts, :pending_conversations_count, :integer, default: 0, null: false
|
||||
add_column :accounts, :snoozed_conversations_count, :integer, default: 0, null: false
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,25 @@
|
||||
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
|
||||
+5
-2
@@ -10,7 +10,7 @@
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema[7.1].define(version: 2026_02_03_062518) do
|
||||
ActiveRecord::Schema[7.1].define(version: 2026_02_03_125200) do
|
||||
# These extensions should be enabled to support this database
|
||||
enable_extension "pg_stat_statements"
|
||||
enable_extension "pg_trgm"
|
||||
@@ -73,7 +73,10 @@ ActiveRecord::Schema[7.1].define(version: 2026_02_03_062518) do
|
||||
t.integer "status", default: 0
|
||||
t.jsonb "internal_attributes", default: {}, null: false
|
||||
t.jsonb "settings", default: {}
|
||||
t.integer "conversations_count", default: 0, null: false
|
||||
t.integer "open_conversations_count", default: 0, null: false
|
||||
t.integer "resolved_conversations_count", default: 0, null: false
|
||||
t.integer "pending_conversations_count", default: 0, null: false
|
||||
t.integer "snoozed_conversations_count", default: 0, null: false
|
||||
t.index ["status"], name: "index_accounts_on_status"
|
||||
end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user