Compare commits

...
Author SHA1 Message Date
Pranav c8cc046358 Contact changes 2024-10-28 23:35:16 -07:00
Pranav 399df7304d feat: Cache contacts count on account 2024-10-28 23:24:02 -07:00
6 changed files with 64 additions and 14 deletions
@@ -17,7 +17,7 @@ class Api::V1::Accounts::ContactsController < Api::V1::Accounts::BaseController
before_action :set_include_contact_inboxes, only: [:index, :search, :filter]
def index
@contacts_count = resolved_contacts.count
@contacts_count = Current.account.contactable_contacts_count
@contacts = fetch_contacts(resolved_contacts)
end
@@ -0,0 +1,15 @@
class UpdateContactableContactsCountJob < ApplicationJob
queue_as :default
def perform(account_id)
account = Account.find_by(id: account_id)
return unless account
# rubocop:disable Rails/SkipsModelValidations
account.update_column(
:contactable_contacts_count,
account.contacts.contactable.count
)
# rubocop:enable Rails/SkipsModelValidations
end
end
+13 -12
View File
@@ -2,18 +2,19 @@
#
# Table name: accounts
#
# id :integer not null, primary key
# auto_resolve_duration :integer
# custom_attributes :jsonb
# domain :string(100)
# feature_flags :bigint default(0), not null
# limits :jsonb
# locale :integer default("en")
# name :string not null
# status :integer default("active")
# support_email :string(100)
# created_at :datetime not null
# updated_at :datetime not null
# id :integer not null, primary key
# auto_resolve_duration :integer
# contactable_contacts_count :integer default(0)
# custom_attributes :jsonb
# domain :string(100)
# feature_flags :bigint default(0), not null
# limits :jsonb
# locale :integer default("en")
# name :string not null
# status :integer default("active")
# support_email :string(100)
# created_at :datetime not null
# updated_at :datetime not null
#
# Indexes
#
+17
View File
@@ -63,9 +63,14 @@ class Contact < ApplicationRecord
after_update_commit :dispatch_update_event
after_destroy_commit :dispatch_destroy_event
before_save :sync_contact_attributes
after_commit :schedule_counter_cache_update
enum contact_type: { visitor: 0, lead: 1, customer: 2 }
scope :contactable, lambda {
where("email != '' OR phone_number != '' OR identifier != ''")
}
scope :order_on_last_activity_at, lambda { |direction|
order(
Arel::Nodes::SqlLiteral.new(
@@ -223,4 +228,16 @@ class Contact < ApplicationRecord
def dispatch_destroy_event
Rails.configuration.dispatcher.dispatch(CONTACT_DELETED, Time.zone.now, contact: self)
end
def schedule_counter_cache_update
if saved_change_to_email? ||
saved_change_to_phone_number? ||
saved_change_to_identifier? ||
destroyed?
UpdateContactableContactsCountJob
.set(wait: 5.seconds)
.perform_later(account_id)
end
end
end
@@ -0,0 +1,16 @@
class AddCounterCacheToAccounts < ActiveRecord::Migration[7.0]
def up
add_column :accounts, :contactable_contacts_count, :integer, default: 0
# Initialize the counter for existing records in batches
Account.in_batches(of: 100) do |batch|
batch.ids.each do |account_id|
UpdateContactableContactsCountJob.perform_later(account_id)
end
end
end
def down
remove_column :accounts, :contactable_contacts_count
end
end
+2 -1
View File
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.0].define(version: 2024_09_23_215335) do
ActiveRecord::Schema[7.0].define(version: 2024_10_29_060838) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_stat_statements"
enable_extension "pg_trgm"
@@ -56,6 +56,7 @@ ActiveRecord::Schema[7.0].define(version: 2024_09_23_215335) do
t.jsonb "limits", default: {}
t.jsonb "custom_attributes", default: {}
t.integer "status", default: 0
t.integer "contactable_contacts_count", default: 0
t.index ["status"], name: "index_accounts_on_status"
end