From 991bc5a2659fc4cadab6038f67c400c0661b7e5a Mon Sep 17 00:00:00 2001 From: Shivam Mishra Date: Thu, 21 May 2026 17:21:17 +0530 Subject: [PATCH] feat: expand workspace cache_keys to canned responses and agents Adds CannedResponse and AccountUser to the per-account cacheable_models so their cache keys are exposed via /cache_keys and broadcast over ActionCable on mutation. The endpoint now delegates to Account#cache_keys instead of listing the three models inline, so future additions only need to touch the concern. AccountUser uses bespoke field-gated callbacks rather than the blanket AccountCacheRevalidator: active_at is bumped on every page navigation and would otherwise invalidate the agent cache constantly. User adds a cross-account callback so name/email/display_name/confirmed_at changes propagate, since those fields appear in the agent serializer but live on the User model. --- app/controllers/api/v1/accounts_controller.rb | 6 +----- app/models/account_user.rb | 6 ++++++ app/models/canned_response.rb | 2 ++ app/models/concerns/cache_keys.rb | 2 +- app/models/user.rb | 8 ++++++++ 5 files changed, 18 insertions(+), 6 deletions(-) diff --git a/app/controllers/api/v1/accounts_controller.rb b/app/controllers/api/v1/accounts_controller.rb index 865b387b9..9f976f2f7 100644 --- a/app/controllers/api/v1/accounts_controller.rb +++ b/app/controllers/api/v1/accounts_controller.rb @@ -94,11 +94,7 @@ class Api::V1::AccountsController < Api::BaseController end def cache_keys_for_account - { - label: fetch_value_for_key(params[:id], Label.name.underscore), - inbox: fetch_value_for_key(params[:id], Inbox.name.underscore), - team: fetch_value_for_key(params[:id], Team.name.underscore) - } + @account.cache_keys end def fetch_account diff --git a/app/models/account_user.rb b/app/models/account_user.rb index bbcb0e010..0f4071536 100644 --- a/app/models/account_user.rb +++ b/app/models/account_user.rb @@ -36,10 +36,16 @@ class AccountUser < ApplicationRecord accepts_nested_attributes_for :account + AGENT_CACHE_RELEVANT_COLUMNS = %w[role availability auto_offline custom_role_id].freeze + after_create_commit :notify_creation, :create_notification_setting after_destroy :notify_deletion, :remove_user_from_account after_save :update_presence_in_redis, if: :saved_change_to_availability? + after_commit -> { account.update_cache_key('account_user') }, on: [:create, :destroy] + after_update_commit -> { account.update_cache_key('account_user') }, + if: -> { saved_changes.keys.intersect?(AGENT_CACHE_RELEVANT_COLUMNS) } + validates :user_id, uniqueness: { scope: :account_id } def create_notification_setting diff --git a/app/models/canned_response.rb b/app/models/canned_response.rb index b70f1c32d..b641f3faf 100644 --- a/app/models/canned_response.rb +++ b/app/models/canned_response.rb @@ -11,6 +11,8 @@ # class CannedResponse < ApplicationRecord + include AccountCacheRevalidator + validates :content, presence: true validates :short_code, presence: true validates :account, presence: true diff --git a/app/models/concerns/cache_keys.rb b/app/models/concerns/cache_keys.rb index b37d7faa6..5cb0c9e08 100644 --- a/app/models/concerns/cache_keys.rb +++ b/app/models/concerns/cache_keys.rb @@ -8,7 +8,7 @@ module CacheKeys included do class_attribute :cacheable_models - self.cacheable_models = [Label, Inbox, Team] + self.cacheable_models = [Label, Inbox, Team, CannedResponse, AccountUser] end def cache_keys diff --git a/app/models/user.rb b/app/models/user.rb index 4aa38bbcd..436f88b5e 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -116,8 +116,12 @@ class User < ApplicationRecord has_many :macros, foreign_key: 'created_by_id', inverse_of: :created_by # rubocop:enable Rails/HasManyOrHasOneDependent + AGENT_CACHE_RELEVANT_COLUMNS = %w[name email display_name confirmed_at].freeze + before_validation :set_password_and_uid, on: :create after_destroy :remove_macros + after_update_commit :bump_account_user_cache_keys, + if: -> { saved_changes.keys.intersect?(AGENT_CACHE_RELEVANT_COLUMNS) } scope :order_by_full_name, -> { order('lower(name) ASC') } @@ -217,6 +221,10 @@ class User < ApplicationRecord def remove_macros macros.personal.destroy_all end + + def bump_account_user_cache_keys + accounts.each { |account| account.update_cache_key('account_user') } + end end User.include_mod_with('Audit::User')