Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'db/post_migrate/20180223124427_build_user_interacted_projects_table.rb')
-rw-r--r--db/post_migrate/20180223124427_build_user_interacted_projects_table.rb139
1 files changed, 0 insertions, 139 deletions
diff --git a/db/post_migrate/20180223124427_build_user_interacted_projects_table.rb b/db/post_migrate/20180223124427_build_user_interacted_projects_table.rb
deleted file mode 100644
index 1eb49d60da5..00000000000
--- a/db/post_migrate/20180223124427_build_user_interacted_projects_table.rb
+++ /dev/null
@@ -1,139 +0,0 @@
-require_relative '../migrate/20180223120443_create_user_interacted_projects_table.rb'
-# rubocop:disable AddIndex
-# rubocop:disable AddConcurrentForeignKey
-class BuildUserInteractedProjectsTable < ActiveRecord::Migration[4.2]
- include Gitlab::Database::MigrationHelpers
-
- # Set this constant to true if this migration requires downtime.
- DOWNTIME = false
-
- UNIQUE_INDEX_NAME = 'index_user_interacted_projects_on_project_id_and_user_id'
-
- disable_ddl_transaction!
-
- def up
- PostgresStrategy.new.up
-
- if index_exists_by_name?(:user_interacted_projects, CreateUserInteractedProjectsTable::INDEX_NAME)
- remove_concurrent_index_by_name :user_interacted_projects, CreateUserInteractedProjectsTable::INDEX_NAME
- end
- end
-
- def down
- execute "TRUNCATE user_interacted_projects"
-
- if foreign_key_exists?(:user_interacted_projects, :users)
- remove_foreign_key :user_interacted_projects, :users
- end
-
- if foreign_key_exists?(:user_interacted_projects, :projects)
- remove_foreign_key :user_interacted_projects, :projects
- end
-
- if index_exists_by_name?(:user_interacted_projects, UNIQUE_INDEX_NAME)
- remove_concurrent_index_by_name :user_interacted_projects, UNIQUE_INDEX_NAME
- end
-
- unless index_exists_by_name?(:user_interacted_projects, CreateUserInteractedProjectsTable::INDEX_NAME)
- add_concurrent_index :user_interacted_projects, [:project_id, :user_id], name: CreateUserInteractedProjectsTable::INDEX_NAME
- end
- end
-
- class PostgresStrategy < ActiveRecord::Migration[4.2]
- include Gitlab::Database::MigrationHelpers
-
- BATCH_SIZE = 100_000
- SLEEP_TIME = 5
-
- def up
- with_index(:events, [:author_id, :project_id], name: 'events_user_interactions_temp', where: 'project_id IS NOT NULL') do
- insert_missing_records
-
- # Do this once without lock to speed up the second invocation
- remove_duplicates
- with_table_lock(:user_interacted_projects) do
- remove_duplicates
- create_unique_index
- end
-
- remove_without_project
- with_table_lock(:user_interacted_projects, :projects) do
- remove_without_project
- create_fk :user_interacted_projects, :projects, :project_id
- end
-
- remove_without_user
- with_table_lock(:user_interacted_projects, :users) do
- remove_without_user
- create_fk :user_interacted_projects, :users, :user_id
- end
- end
-
- execute "ANALYZE user_interacted_projects"
- end
-
- private
-
- def insert_missing_records
- iteration = 0
- records = 0
- begin
- Rails.logger.info "Building user_interacted_projects table, batch ##{iteration}" # rubocop:disable Gitlab/RailsLogger
- result = execute <<~SQL
- INSERT INTO user_interacted_projects (user_id, project_id)
- SELECT e.user_id, e.project_id
- FROM (SELECT DISTINCT author_id AS user_id, project_id FROM events WHERE project_id IS NOT NULL) AS e
- LEFT JOIN user_interacted_projects ucp USING (user_id, project_id)
- WHERE ucp.user_id IS NULL
- LIMIT #{BATCH_SIZE}
- SQL
- iteration += 1
- records += result.cmd_tuples
- Rails.logger.info "Building user_interacted_projects table, batch ##{iteration} complete, created #{records} overall" # rubocop:disable Gitlab/RailsLogger
- Kernel.sleep(SLEEP_TIME) if result.cmd_tuples > 0
- end while result.cmd_tuples > 0
- end
-
- def remove_duplicates
- execute <<~SQL
- WITH numbered AS (select ctid, ROW_NUMBER() OVER (PARTITION BY (user_id, project_id)) as row_number, user_id, project_id from user_interacted_projects)
- DELETE FROM user_interacted_projects WHERE ctid IN (SELECT ctid FROM numbered WHERE row_number > 1);
- SQL
- end
-
- def remove_without_project
- execute "DELETE FROM user_interacted_projects WHERE NOT EXISTS (SELECT 1 FROM projects WHERE id = user_interacted_projects.project_id)"
- end
-
- def remove_without_user
- execute "DELETE FROM user_interacted_projects WHERE NOT EXISTS (SELECT 1 FROM users WHERE id = user_interacted_projects.user_id)"
- end
-
- def create_fk(table, target, column)
- return if foreign_key_exists?(table, target, column: column)
-
- add_foreign_key table, target, column: column, on_delete: :cascade
- end
-
- def create_unique_index
- return if index_exists_by_name?(:user_interacted_projects, UNIQUE_INDEX_NAME)
-
- add_index :user_interacted_projects, [:project_id, :user_id], unique: true, name: UNIQUE_INDEX_NAME
- end
-
- # Protect table against concurrent data changes while still allowing reads
- def with_table_lock(*tables)
- ActiveRecord::Base.connection.transaction do
- execute "LOCK TABLE #{tables.join(", ")} IN SHARE MODE"
- yield
- end
- end
-
- def with_index(*args)
- add_concurrent_index(*args) unless index_exists?(*args)
- yield
- ensure
- remove_concurrent_index(*args) if index_exists?(*args)
- end
- end
-end