From 8ba8752bf67dd1f5aadc5d349cb244b26f32b42a Mon Sep 17 00:00:00 2001 From: Sojan Date: Tue, 9 Aug 2022 14:38:15 +0200 Subject: [PATCH] chore: Remove cascading Indexes --- app/models/account.rb | 4 +- app/models/account_user.rb | 5 --- app/models/agent_bot.rb | 4 -- app/models/article.rb | 5 --- app/models/campaign.rb | 5 --- app/models/category.rb | 5 --- app/models/contact_inbox.rb | 5 --- app/models/conversation.rb | 8 +--- app/models/csat_survey_response.rb | 8 ---- app/models/dashboard_app.rb | 5 --- app/models/data_import.rb | 4 -- app/models/macro.rb | 5 --- app/models/mention.rb | 5 --- app/models/message.rb | 3 +- app/models/note.rb | 6 --- app/models/team.rb | 4 -- app/models/team_member.rb | 5 --- ...20220809104508_revert_cascading_indexes.rb | 44 +++++++++++++++++++ db/schema.rb | 34 +------------- spec/models/notification_spec.rb | 15 +++++++ 20 files changed, 65 insertions(+), 114 deletions(-) create mode 100644 db/migrate/20220809104508_revert_cascading_indexes.rb diff --git a/app/models/account.rb b/app/models/account.rb index 9a719f881..7c7336642 100644 --- a/app/models/account.rb +++ b/app/models/account.rb @@ -55,7 +55,7 @@ class Account < ApplicationRecord has_many :csat_survey_responses, dependent: :destroy_async has_many :custom_attribute_definitions, dependent: :destroy_async has_many :custom_filters, dependent: :destroy_async - has_many :dashboard_apps, dependent: :destroy + has_many :dashboard_apps, dependent: :destroy_async has_many :data_imports, dependent: :destroy_async has_many :email_channels, dependent: :destroy_async, class_name: '::Channel::Email' has_many :facebook_pages, dependent: :destroy_async, class_name: '::Channel::FacebookPage' @@ -67,7 +67,7 @@ class Account < ApplicationRecord has_many :messages, dependent: :destroy_async has_many :notes, dependent: :destroy_async has_many :notification_settings, dependent: :destroy_async - has_many :notifications, dependent: :destroy + has_many :notifications, dependent: :destroy_async has_many :portals, dependent: :destroy_async, class_name: '::Portal' has_many :sms_channels, dependent: :destroy_async, class_name: '::Channel::Sms' has_many :teams, dependent: :destroy_async diff --git a/app/models/account_user.rb b/app/models/account_user.rb index 526160c5d..a6bf3988a 100644 --- a/app/models/account_user.rb +++ b/app/models/account_user.rb @@ -19,11 +19,6 @@ # index_account_users_on_user_id (user_id) # uniq_user_id_per_account_id (account_id,user_id) UNIQUE # -# Foreign Keys -# -# fk_rails_... (account_id => accounts.id) ON DELETE => cascade -# fk_rails_... (user_id => users.id) ON DELETE => cascade -# class AccountUser < ApplicationRecord include AvailabilityStatusable diff --git a/app/models/agent_bot.rb b/app/models/agent_bot.rb index 6a38167dc..72f6b2618 100644 --- a/app/models/agent_bot.rb +++ b/app/models/agent_bot.rb @@ -16,10 +16,6 @@ # # index_agent_bots_on_account_id (account_id) # -# Foreign Keys -# -# fk_rails_... (account_id => accounts.id) ON DELETE => cascade -# class AgentBot < ApplicationRecord include AccessTokenable diff --git a/app/models/article.rb b/app/models/article.rb index 3ad63bcaa..1044e1107 100644 --- a/app/models/article.rb +++ b/app/models/article.rb @@ -23,11 +23,6 @@ # index_articles_on_associated_article_id (associated_article_id) # index_articles_on_author_id (author_id) # -# Foreign Keys -# -# fk_rails_... (associated_article_id => articles.id) -# fk_rails_... (author_id => users.id) -# class Article < ApplicationRecord include PgSearch::Model diff --git a/app/models/campaign.rb b/app/models/campaign.rb index 1201a79db..7f4cbde69 100644 --- a/app/models/campaign.rb +++ b/app/models/campaign.rb @@ -28,11 +28,6 @@ # index_campaigns_on_inbox_id (inbox_id) # index_campaigns_on_scheduled_at (scheduled_at) # -# Foreign Keys -# -# fk_rails_... (account_id => accounts.id) ON DELETE => cascade -# fk_rails_... (inbox_id => inboxes.id) ON DELETE => cascade -# class Campaign < ApplicationRecord include UrlHelper validates :account_id, presence: true diff --git a/app/models/category.rb b/app/models/category.rb index 14c455e29..d0db67b94 100644 --- a/app/models/category.rb +++ b/app/models/category.rb @@ -23,11 +23,6 @@ # index_categories_on_parent_category_id (parent_category_id) # index_categories_on_slug_and_locale_and_portal_id (slug,locale,portal_id) UNIQUE # -# Foreign Keys -# -# fk_rails_... (associated_category_id => categories.id) -# fk_rails_... (parent_category_id => categories.id) -# class Category < ApplicationRecord belongs_to :account belongs_to :portal diff --git a/app/models/contact_inbox.rb b/app/models/contact_inbox.rb index bc4eb6484..dcbd2f56b 100644 --- a/app/models/contact_inbox.rb +++ b/app/models/contact_inbox.rb @@ -19,11 +19,6 @@ # index_contact_inboxes_on_pubsub_token (pubsub_token) UNIQUE # index_contact_inboxes_on_source_id (source_id) # -# Foreign Keys -# -# fk_rails_... (contact_id => contacts.id) ON DELETE => cascade -# fk_rails_... (inbox_id => inboxes.id) ON DELETE => cascade -# class ContactInbox < ApplicationRecord include Pubsubable diff --git a/app/models/conversation.rb b/app/models/conversation.rb index e3791a9d3..a63ecfa84 100644 --- a/app/models/conversation.rb +++ b/app/models/conversation.rb @@ -37,12 +37,6 @@ # index_conversations_on_status_and_account_id (status,account_id) # index_conversations_on_team_id (team_id) # -# Foreign Keys -# -# fk_rails_... (campaign_id => campaigns.id) ON DELETE => cascade -# fk_rails_... (contact_inbox_id => contact_inboxes.id) ON DELETE => cascade -# fk_rails_... (team_id => teams.id) ON DELETE => cascade -# class Conversation < ApplicationRecord include Labelable @@ -88,7 +82,7 @@ class Conversation < ApplicationRecord has_many :mentions, dependent: :destroy_async has_many :messages, dependent: :destroy_async, autosave: true has_one :csat_survey_response, dependent: :destroy_async - has_many :notifications, as: :primary_actor, dependent: :destroy + has_many :notifications, as: :primary_actor, dependent: :destroy_async before_save :ensure_snooze_until_reset before_create :mark_conversation_pending_if_bot diff --git a/app/models/csat_survey_response.rb b/app/models/csat_survey_response.rb index 119d5c615..92ea25ebe 100644 --- a/app/models/csat_survey_response.rb +++ b/app/models/csat_survey_response.rb @@ -21,14 +21,6 @@ # index_csat_survey_responses_on_conversation_id (conversation_id) # index_csat_survey_responses_on_message_id (message_id) UNIQUE # -# Foreign Keys -# -# fk_rails_... (account_id => accounts.id) ON DELETE => cascade -# fk_rails_... (assigned_agent_id => users.id) ON DELETE => cascade -# fk_rails_... (contact_id => contacts.id) ON DELETE => cascade -# fk_rails_... (conversation_id => conversations.id) ON DELETE => cascade -# fk_rails_... (message_id => messages.id) ON DELETE => cascade -# class CsatSurveyResponse < ApplicationRecord belongs_to :account belongs_to :conversation diff --git a/app/models/dashboard_app.rb b/app/models/dashboard_app.rb index 1f1b73d5c..c8558fb4c 100644 --- a/app/models/dashboard_app.rb +++ b/app/models/dashboard_app.rb @@ -15,11 +15,6 @@ # index_dashboard_apps_on_account_id (account_id) # index_dashboard_apps_on_user_id (user_id) # -# Foreign Keys -# -# fk_rails_... (account_id => accounts.id) -# fk_rails_... (user_id => users.id) -# class DashboardApp < ApplicationRecord belongs_to :user belongs_to :account diff --git a/app/models/data_import.rb b/app/models/data_import.rb index b83cf596a..b86ebac23 100644 --- a/app/models/data_import.rb +++ b/app/models/data_import.rb @@ -16,10 +16,6 @@ # # index_data_imports_on_account_id (account_id) # -# Foreign Keys -# -# fk_rails_... (account_id => accounts.id) ON DELETE => cascade -# class DataImport < ApplicationRecord belongs_to :account validates :data_type, inclusion: { in: ['contacts'], message: I18n.t('errors.data_import.data_type.invalid') } diff --git a/app/models/macro.rb b/app/models/macro.rb index 0b9c77d9f..df002d680 100644 --- a/app/models/macro.rb +++ b/app/models/macro.rb @@ -18,11 +18,6 @@ # index_macros_on_created_by_id (created_by_id) # index_macros_on_updated_by_id (updated_by_id) # -# Foreign Keys -# -# fk_rails_... (created_by_id => users.id) -# fk_rails_... (updated_by_id => users.id) -# class Macro < ApplicationRecord belongs_to :account belongs_to :created_by, diff --git a/app/models/mention.rb b/app/models/mention.rb index 00a3a859d..0e0fe762a 100644 --- a/app/models/mention.rb +++ b/app/models/mention.rb @@ -17,11 +17,6 @@ # index_mentions_on_user_id (user_id) # index_mentions_on_user_id_and_conversation_id (user_id,conversation_id) UNIQUE # -# Foreign Keys -# -# fk_rails_... (conversation_id => conversations.id) ON DELETE => cascade -# fk_rails_... (user_id => users.id) ON DELETE => cascade -# class Mention < ApplicationRecord include SortHandler diff --git a/app/models/message.rb b/app/models/message.rb index 4b8a62e3b..68e4e34af 100644 --- a/app/models/message.rb +++ b/app/models/message.rb @@ -85,8 +85,9 @@ class Message < ApplicationRecord belongs_to :contact, required: false belongs_to :sender, polymorphic: true, required: false - has_many :attachments, dependent: :destroy_async, autosave: true, before_add: :validate_attachments_limit + has_many :attachments, dependent: :destroy, autosave: true, before_add: :validate_attachments_limit has_one :csat_survey_response, dependent: :destroy_async + has_many :notifications, as: :primary_actor, dependent: :destroy_async after_create_commit :execute_after_create_commit_callbacks diff --git a/app/models/note.rb b/app/models/note.rb index c33fd79b2..c1a49ba07 100644 --- a/app/models/note.rb +++ b/app/models/note.rb @@ -16,12 +16,6 @@ # index_notes_on_contact_id (contact_id) # index_notes_on_user_id (user_id) # -# Foreign Keys -# -# fk_rails_... (account_id => accounts.id) ON DELETE => cascade -# fk_rails_... (contact_id => contacts.id) ON DELETE => cascade -# fk_rails_... (user_id => users.id) ON DELETE => cascade -# class Note < ApplicationRecord before_validation :ensure_account_id validates :content, presence: true diff --git a/app/models/team.rb b/app/models/team.rb index 28e37f0cf..eac2b7532 100644 --- a/app/models/team.rb +++ b/app/models/team.rb @@ -15,10 +15,6 @@ # index_teams_on_account_id (account_id) # index_teams_on_name_and_account_id (name,account_id) UNIQUE # -# Foreign Keys -# -# fk_rails_... (account_id => accounts.id) ON DELETE => cascade -# class Team < ApplicationRecord belongs_to :account has_many :team_members, dependent: :destroy_async diff --git a/app/models/team_member.rb b/app/models/team_member.rb index d73cd7c09..f5d364007 100644 --- a/app/models/team_member.rb +++ b/app/models/team_member.rb @@ -14,11 +14,6 @@ # index_team_members_on_team_id_and_user_id (team_id,user_id) UNIQUE # index_team_members_on_user_id (user_id) # -# Foreign Keys -# -# fk_rails_... (team_id => teams.id) ON DELETE => cascade -# fk_rails_... (user_id => users.id) ON DELETE => cascade -# class TeamMember < ApplicationRecord belongs_to :user belongs_to :team diff --git a/db/migrate/20220809104508_revert_cascading_indexes.rb b/db/migrate/20220809104508_revert_cascading_indexes.rb new file mode 100644 index 000000000..345e86333 --- /dev/null +++ b/db/migrate/20220809104508_revert_cascading_indexes.rb @@ -0,0 +1,44 @@ +class RevertCascadingIndexes < ActiveRecord::Migration[6.1] + def change + remove_foreign_key 'account_users', 'accounts' if foreign_key_exists? 'account_users', 'accounts' + remove_foreign_key 'account_users', 'users' if foreign_key_exists? 'account_users', 'users' + remove_foreign_key 'agent_bots', 'accounts' if foreign_key_exists? 'agent_bots', 'accounts' + remove_foreign_key 'campaigns', 'accounts' if foreign_key_exists? 'campaigns', 'accounts' + remove_foreign_key 'campaigns', 'inboxes' if foreign_key_exists? 'campaigns', 'inboxes' + remove_foreign_key 'conversations', 'campaigns' if foreign_key_exists? 'conversations', 'campaigns' + remove_foreign_key 'conversations', 'contact_inboxes' if foreign_key_exists? 'conversations', 'contact_inboxes' + remove_foreign_key 'conversations', 'teams' if foreign_key_exists? 'conversations', 'teams' + remove_foreign_key 'csat_survey_responses', 'accounts' if foreign_key_exists? 'csat_survey_responses', 'accounts' + remove_foreign_key 'csat_survey_responses', 'contacts' if foreign_key_exists? 'csat_survey_responses', 'contacts' + remove_foreign_key 'csat_survey_responses', 'conversations' if foreign_key_exists? 'csat_survey_responses', 'conversations' + remove_foreign_key 'csat_survey_responses', 'messages' if foreign_key_exists? 'csat_survey_responses', 'messages' + remove_foreign_key 'csat_survey_responses', 'users', column: 'assigned_agent_id' if foreign_key_exists? 'csat_survey_responses', 'users', + column: 'assigned_agent_id' + remove_foreign_key 'data_imports', 'accounts' if foreign_key_exists? 'data_imports', 'accounts' + remove_foreign_key 'mentions', 'conversations' if foreign_key_exists? 'mentions', 'conversations' + remove_foreign_key 'mentions', 'users' if foreign_key_exists? 'mentions', 'users' + remove_foreign_key 'notes', 'accounts' if foreign_key_exists? 'notes', 'accounts' + remove_foreign_key 'notes', 'contacts' if foreign_key_exists? 'notes', 'contacts' + remove_foreign_key 'notes', 'users' if foreign_key_exists? 'notes', 'users' + remove_foreign_key 'team_members', 'teams' if foreign_key_exists? 'team_members', 'teams' + remove_foreign_key 'team_members', 'users' if foreign_key_exists? 'team_members', 'users' + remove_foreign_key 'teams', 'accounts' if foreign_key_exists? 'teams', 'accounts' + remove_foreign_key 'contact_inboxes', 'contacts' if foreign_key_exists? 'contact_inboxes', 'contacts' + remove_foreign_key 'contact_inboxes', 'inboxes' if foreign_key_exists? 'contact_inboxes', 'inboxes' + + remove_foreign_key 'articles', 'articles', column: 'associated_article_id' if foreign_key_exists? 'articles', 'articles', + column: 'associated_article_id' + remove_foreign_key 'articles', 'users', column: 'author_id' if foreign_key_exists? 'articles', 'users', column: 'author_id' + + remove_foreign_key 'categories', 'categories', column: 'parent_category_id' if foreign_key_exists? 'categories', 'categories', + column: 'parent_category_id' + remove_foreign_key 'categories', 'categories', column: 'associated_category_id' if foreign_key_exists? 'categories', 'categories', + column: 'associated_category_id' + + remove_foreign_key 'dashboard_apps', 'accounts' if foreign_key_exists? 'dashboard_apps', 'accounts' + remove_foreign_key 'dashboard_apps', 'users' if foreign_key_exists? 'dashboard_apps', 'users' + + remove_foreign_key 'macros', 'users', column: 'created_by_id' if foreign_key_exists? 'macros', 'users', column: 'created_by_id' + remove_foreign_key 'macros', 'users', column: 'updated_by_id' if foreign_key_exists? 'macros', 'users', column: 'updated_by_id' + end +end diff --git a/db/schema.rb b/db/schema.rb index 17271fa65..2920c3411 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2022_08_02_133722) do +ActiveRecord::Schema.define(version: 2022_08_09_104508) do # These are extensions that must be enabled in order to support this database enable_extension "pg_stat_statements" @@ -862,40 +862,8 @@ ActiveRecord::Schema.define(version: 2022_08_02_133722) do t.index ["inbox_id"], name: "index_working_hours_on_inbox_id" end - add_foreign_key "account_users", "accounts", on_delete: :cascade - add_foreign_key "account_users", "users", on_delete: :cascade add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id" add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id" - add_foreign_key "agent_bots", "accounts", on_delete: :cascade - add_foreign_key "articles", "articles", column: "associated_article_id" - add_foreign_key "articles", "users", column: "author_id" - add_foreign_key "campaigns", "accounts", on_delete: :cascade - add_foreign_key "campaigns", "inboxes", on_delete: :cascade - add_foreign_key "categories", "categories", column: "associated_category_id" - add_foreign_key "categories", "categories", column: "parent_category_id" - add_foreign_key "contact_inboxes", "contacts", on_delete: :cascade - add_foreign_key "contact_inboxes", "inboxes", on_delete: :cascade - add_foreign_key "conversations", "campaigns", on_delete: :cascade - add_foreign_key "conversations", "contact_inboxes", on_delete: :cascade - add_foreign_key "conversations", "teams", on_delete: :cascade - add_foreign_key "csat_survey_responses", "accounts", on_delete: :cascade - add_foreign_key "csat_survey_responses", "contacts", on_delete: :cascade - add_foreign_key "csat_survey_responses", "conversations", on_delete: :cascade - add_foreign_key "csat_survey_responses", "messages", on_delete: :cascade - add_foreign_key "csat_survey_responses", "users", column: "assigned_agent_id", on_delete: :cascade - add_foreign_key "dashboard_apps", "accounts" - add_foreign_key "dashboard_apps", "users" - add_foreign_key "data_imports", "accounts", on_delete: :cascade - add_foreign_key "macros", "users", column: "created_by_id" - add_foreign_key "macros", "users", column: "updated_by_id" - add_foreign_key "mentions", "conversations", on_delete: :cascade - add_foreign_key "mentions", "users", on_delete: :cascade - add_foreign_key "notes", "accounts", on_delete: :cascade - add_foreign_key "notes", "contacts", on_delete: :cascade - add_foreign_key "notes", "users", on_delete: :cascade - add_foreign_key "team_members", "teams", on_delete: :cascade - add_foreign_key "team_members", "users", on_delete: :cascade - add_foreign_key "teams", "accounts", on_delete: :cascade create_trigger("accounts_after_insert_row_tr", :generated => true, :compatibility => 1). on("accounts"). after(:insert). diff --git a/spec/models/notification_spec.rb b/spec/models/notification_spec.rb index 4c5a01e94..e3584d182 100644 --- a/spec/models/notification_spec.rb +++ b/spec/models/notification_spec.rb @@ -3,6 +3,8 @@ require 'rails_helper' RSpec.describe Notification do + include ActiveJob::TestHelper + context 'with associations' do it { is_expected.to belong_to(:account) } it { is_expected.to belong_to(:user) } @@ -97,4 +99,17 @@ RSpec.describe Notification do }) end end + + context 'when primary actory is deleted' do + let!(:conversation) { create(:conversation) } + + it 'clears notifications' do + notification = create(:notification, notification_type: 'conversation_creation', primary_actor: conversation) + perform_enqueued_jobs do + conversation.inbox.destroy! + end + + expect { notification.reload }.to raise_error(ActiveRecord::RecordNotFound) + end + end end