Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
李少辉-开发者
gitlab-foss
提交
729de4f1
G
gitlab-foss
项目概览
李少辉-开发者
/
gitlab-foss
通知
15
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
gitlab-foss
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
未验证
提交
729de4f1
编写于
7月 23, 2018
作者:
A
Andreas Brandl
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add migration to cleanup internal_ids.
See
https://gitlab.com/gitlab-org/gitlab-ce/issues/49446
.
上级
fb98496f
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
171 addition
and
0 deletion
+171
-0
changelogs/unreleased/ab-49446-internal-ids-inconsistency.yml
...gelogs/unreleased/ab-49446-internal-ids-inconsistency.yml
+5
-0
db/post_migrate/20180723130817_delete_inconsistent_internal_id_records.rb
...20180723130817_delete_inconsistent_internal_id_records.rb
+47
-0
spec/migrations/delete_inconsistent_internal_id_records_spec.rb
...igrations/delete_inconsistent_internal_id_records_spec.rb
+119
-0
未找到文件。
changelogs/unreleased/ab-49446-internal-ids-inconsistency.yml
0 → 100644
浏览文件 @
729de4f1
---
title
:
Add migration to cleanup internal_ids inconsistency.
merge_request
:
20926
author
:
type
:
fixed
db/post_migrate/20180723130817_delete_inconsistent_internal_id_records.rb
0 → 100644
浏览文件 @
729de4f1
# frozen_string_literal: true
class
DeleteInconsistentInternalIdRecords
<
ActiveRecord
::
Migration
include
Gitlab
::
Database
::
MigrationHelpers
DOWNTIME
=
false
disable_ddl_transaction!
# This migration cleans up any inconsistent records in internal_ids.
#
# That is, it deletes records that track a `last_value` that is
# smaller than the maximum internal id (usually `iid`) found in
# the corresponding model records.
def
up
disable_statement_timeout
do
delete_internal_id_records
(
'issues'
,
'project_id'
)
delete_internal_id_records
(
'merge_requests'
,
'project_id'
,
'target_project_id'
)
delete_internal_id_records
(
'deployments'
,
'project_id'
)
delete_internal_id_records
(
'milestones'
,
'project_id'
)
delete_internal_id_records
(
'milestones'
,
'namespace_id'
,
'group_id'
)
delete_internal_id_records
(
'ci_pipelines'
,
'project_id'
)
end
end
class
InternalId
<
ActiveRecord
::
Base
self
.
table_name
=
'internal_ids'
enum
usage:
{
issues:
0
,
merge_requests:
1
,
deployments:
2
,
milestones:
3
,
epics:
4
,
ci_pipelines:
5
}
end
private
def
delete_internal_id_records
(
base_table
,
scope_column_name
,
base_scope_column_name
=
scope_column_name
)
sql
=
<<~
SQL
SELECT id FROM ( -- workaround for MySQL
SELECT internal_ids.id FROM (
SELECT
#{
base_scope_column_name
}
AS
#{
scope_column_name
}
, max(iid) as maximum_iid from
#{
base_table
}
GROUP BY
#{
scope_column_name
}
) maxima JOIN internal_ids USING (
#{
scope_column_name
}
)
WHERE internal_ids.usage=
#{
InternalId
.
usages
.
fetch
(
base_table
)
}
AND maxima.maximum_iid > internal_ids.last_value
) internal_ids
SQL
InternalId
.
where
(
"id IN (
#{
sql
}
)"
).
tap
do
|
ids
|
# rubocop:disable GitlabSecurity/SqlInjection
say
"Deleting internal_id records for
#{
base_table
}
:
#{
ids
.
pluck
(
:project_id
,
:last_value
)
}
"
unless
ids
.
empty?
end
.
delete_all
end
end
spec/migrations/delete_inconsistent_internal_id_records_spec.rb
0 → 100644
浏览文件 @
729de4f1
# frozen_string_literal: true
# rubocop:disable RSpec/FactoriesInMigrationSpecs
require
'spec_helper'
require
Rails
.
root
.
join
(
'db'
,
'post_migrate'
,
'20180723130817_delete_inconsistent_internal_id_records.rb'
)
describe
DeleteInconsistentInternalIdRecords
,
:migration
do
let!
(
:project1
)
{
create
(
:project
)
}
let!
(
:project2
)
{
create
(
:project
)
}
let!
(
:project3
)
{
create
(
:project
)
}
let
(
:internal_id_query
)
{
->
(
project
)
{
InternalId
.
where
(
usage:
InternalId
.
usages
[
scope
.
to_s
.
tableize
],
project:
project
)
}
}
let
(
:create_models
)
do
3
.
times
{
create
(
scope
,
project:
project1
)
}
3
.
times
{
create
(
scope
,
project:
project2
)
}
3
.
times
{
create
(
scope
,
project:
project3
)
}
end
shared_examples_for
'deleting inconsistent internal_id records'
do
before
do
create_models
internal_id_query
.
call
(
project1
).
first
.
tap
do
|
iid
|
iid
.
last_value
=
iid
.
last_value
-
2
# This is an inconsistent record
iid
.
save!
end
internal_id_query
.
call
(
project3
).
first
.
tap
do
|
iid
|
iid
.
last_value
=
iid
.
last_value
+
2
# This is a consistent record
iid
.
save!
end
end
it
"deletes inconsistent issues"
do
expect
{
migrate!
}.
to
change
{
internal_id_query
.
call
(
project1
).
size
}.
from
(
1
).
to
(
0
)
end
it
"retains consistent issues"
do
expect
{
migrate!
}.
not_to
change
{
internal_id_query
.
call
(
project2
).
size
}
end
it
"retains consistent records, especially those with a greater last_value"
do
expect
{
migrate!
}.
not_to
change
{
internal_id_query
.
call
(
project3
).
size
}
end
end
context
'for issues'
do
let
(
:scope
)
{
:issue
}
it_behaves_like
'deleting inconsistent internal_id records'
end
context
'for merge_requests'
do
let
(
:scope
)
{
:merge_request
}
let
(
:create_models
)
do
3
.
times
{
|
i
|
create
(
scope
,
target_project:
project1
,
source_project:
project1
,
source_branch:
i
.
to_s
)
}
3
.
times
{
|
i
|
create
(
scope
,
target_project:
project2
,
source_project:
project2
,
source_branch:
i
.
to_s
)
}
3
.
times
{
|
i
|
create
(
scope
,
target_project:
project3
,
source_project:
project3
,
source_branch:
i
.
to_s
)
}
end
it_behaves_like
'deleting inconsistent internal_id records'
end
context
'for deployments'
do
let
(
:scope
)
{
:deployment
}
it_behaves_like
'deleting inconsistent internal_id records'
end
context
'for milestones (by project)'
do
let
(
:scope
)
{
:milestone
}
it_behaves_like
'deleting inconsistent internal_id records'
end
context
'for ci_pipelines'
do
let
(
:scope
)
{
:ci_pipeline
}
it_behaves_like
'deleting inconsistent internal_id records'
end
context
'for milestones (by group)'
do
# milestones (by group) is a little different than all of the other models
let!
(
:group1
)
{
create
(
:group
)
}
let!
(
:group2
)
{
create
(
:group
)
}
let!
(
:group3
)
{
create
(
:group
)
}
let
(
:internal_id_query
)
{
->
(
group
)
{
InternalId
.
where
(
usage:
InternalId
.
usages
[
'milestones'
],
namespace:
group
)
}
}
before
do
3
.
times
{
create
(
:milestone
,
group:
group1
)
}
3
.
times
{
create
(
:milestone
,
group:
group2
)
}
3
.
times
{
create
(
:milestone
,
group:
group3
)
}
internal_id_query
.
call
(
group1
).
first
.
tap
do
|
iid
|
iid
.
last_value
=
iid
.
last_value
-
2
# This is an inconsistent record
iid
.
save!
end
internal_id_query
.
call
(
group3
).
first
.
tap
do
|
iid
|
iid
.
last_value
=
iid
.
last_value
+
2
# This is a consistent record
iid
.
save!
end
end
it
"deletes inconsistent issues"
do
expect
{
migrate!
}.
to
change
{
internal_id_query
.
call
(
group1
).
size
}.
from
(
1
).
to
(
0
)
end
it
"retains consistent issues"
do
expect
{
migrate!
}.
not_to
change
{
internal_id_query
.
call
(
group2
).
size
}
end
it
"retains consistent records, especially those with a greater last_value"
do
expect
{
migrate!
}.
not_to
change
{
internal_id_query
.
call
(
group3
).
size
}
end
end
end
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录