Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
0df50a45
Commit
0df50a45
authored
Jul 02, 2021
by
Heinrich Lee Yu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix loading of gems and classes
These fixes are required for us to switch to the Zeitwerk autoloader
parent
8fc42807
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
174 additions
and
166 deletions
+174
-166
lib/gitlab/auth/u2f_webauthn_converter.rb
lib/gitlab/auth/u2f_webauthn_converter.rb
+2
-0
lib/gitlab/background_migration/migrate_u2f_webauthn.rb
lib/gitlab/background_migration/migrate_u2f_webauthn.rb
+0
-1
lib/gitlab/database/batch_count.rb
lib/gitlab/database/batch_count.rb
+0
-154
lib/gitlab/database/batch_counter.rb
lib/gitlab/database/batch_counter.rb
+159
-0
lib/gitlab/database/load_balancing/srv_resolver.rb
lib/gitlab/database/load_balancing/srv_resolver.rb
+2
-0
lib/gitlab/database/postgresql_adapter/force_disconnectable_mixin.rb
...database/postgresql_adapter/force_disconnectable_mixin.rb
+1
-1
spec/lib/gitlab/background_migration/migrate_u2f_webauthn_spec.rb
.../gitlab/background_migration/migrate_u2f_webauthn_spec.rb
+2
-0
spec/lib/gitlab/database/migration_helpers_spec.rb
spec/lib/gitlab/database/migration_helpers_spec.rb
+8
-10
No files found.
lib/gitlab/auth/u2f_webauthn_converter.rb
View file @
0df50a45
# frozen_string_literal: true
# frozen_string_literal: true
require
'webauthn/u2f_migrator'
module
Gitlab
module
Gitlab
module
Auth
module
Auth
class
U2fWebauthnConverter
class
U2fWebauthnConverter
...
...
lib/gitlab/background_migration/migrate_u2f_webauthn.rb
View file @
0df50a45
# frozen_string_literal: true
# frozen_string_literal: true
# rubocop:disable Style/Documentation
# rubocop:disable Style/Documentation
require
"webauthn/u2f_migrator"
module
Gitlab
module
Gitlab
module
BackgroundMigration
module
BackgroundMigration
...
...
lib/gitlab/database/batch_count.rb
View file @
0df50a45
...
@@ -41,159 +41,5 @@ module Gitlab
...
@@ -41,159 +41,5 @@ module Gitlab
include
BatchCount
include
BatchCount
end
end
end
end
class
BatchCounter
FALLBACK
=
-
1
MIN_REQUIRED_BATCH_SIZE
=
1_250
DEFAULT_SUM_BATCH_SIZE
=
1_000
MAX_ALLOWED_LOOPS
=
10_000
SLEEP_TIME_IN_SECONDS
=
0.01
# 10 msec sleep
ALLOWED_MODES
=
[
:itself
,
:distinct
].
freeze
FALLBACK_FINISH
=
0
OFFSET_BY_ONE
=
1
# Each query should take < 500ms https://gitlab.com/gitlab-org/gitlab/-/merge_requests/22705
DEFAULT_DISTINCT_BATCH_SIZE
=
10_000
DEFAULT_BATCH_SIZE
=
100_000
def
initialize
(
relation
,
column:
nil
,
operation: :count
,
operation_args:
nil
)
@relation
=
relation
@column
=
column
||
relation
.
primary_key
@operation
=
operation
@operation_args
=
operation_args
end
def
unwanted_configuration?
(
finish
,
batch_size
,
start
)
(
@operation
==
:count
&&
batch_size
<=
MIN_REQUIRED_BATCH_SIZE
)
||
(
@operation
==
:sum
&&
batch_size
<
DEFAULT_SUM_BATCH_SIZE
)
||
(
finish
-
start
)
/
batch_size
>=
MAX_ALLOWED_LOOPS
||
start
>=
finish
end
def
count
(
batch_size:
nil
,
mode: :itself
,
start:
nil
,
finish:
nil
)
raise
'BatchCount can not be run inside a transaction'
if
ActiveRecord
::
Base
.
connection
.
transaction_open?
check_mode!
(
mode
)
# non-distinct have better performance
batch_size
||=
batch_size_for_mode_and_operation
(
mode
,
@operation
)
start
=
actual_start
(
start
)
finish
=
actual_finish
(
finish
)
raise
"Batch counting expects positive values only for
#{
@column
}
"
if
start
<
0
||
finish
<
0
return
FALLBACK
if
unwanted_configuration?
(
finish
,
batch_size
,
start
)
results
=
nil
batch_start
=
start
while
batch_start
<
finish
begin
batch_end
=
[
batch_start
+
batch_size
,
finish
].
min
batch_relation
=
build_relation_batch
(
batch_start
,
batch_end
,
mode
)
op_args
=
@operation_args
if
@operation
==
:count
&&
@operation_args
.
blank?
&&
use_loose_index_scan_for_distinct_values?
(
mode
)
op_args
=
[
Gitlab
::
Database
::
LooseIndexScanDistinctCount
::
COLUMN_ALIAS
]
end
results
=
merge_results
(
results
,
batch_relation
.
send
(
@operation
,
*
op_args
))
# rubocop:disable GitlabSecurity/PublicSend
batch_start
=
batch_end
rescue
ActiveRecord
::
QueryCanceled
=>
error
# retry with a safe batch size & warmer cache
if
batch_size
>=
2
*
MIN_REQUIRED_BATCH_SIZE
batch_size
/=
2
else
log_canceled_batch_fetch
(
batch_start
,
mode
,
batch_relation
.
to_sql
,
error
)
return
FALLBACK
end
rescue
Gitlab
::
Database
::
LooseIndexScanDistinctCount
::
ColumnConfigurationError
=>
error
Gitlab
::
AppJsonLogger
.
error
(
event:
'batch_count'
,
relation:
@relation
.
table_name
,
operation:
@operation
,
operation_args:
@operation_args
,
mode:
mode
,
message:
"LooseIndexScanDistinctCount column error:
#{
error
.
message
}
"
)
return
FALLBACK
end
sleep
(
SLEEP_TIME_IN_SECONDS
)
end
results
end
def
merge_results
(
results
,
object
)
return
object
unless
results
if
object
.
is_a?
(
Hash
)
results
.
merge!
(
object
)
{
|
_
,
a
,
b
|
a
+
b
}
else
results
+
object
end
end
private
def
build_relation_batch
(
start
,
finish
,
mode
)
if
use_loose_index_scan_for_distinct_values?
(
mode
)
Gitlab
::
Database
::
LooseIndexScanDistinctCount
.
new
(
@relation
,
@column
).
build_query
(
from:
start
,
to:
finish
)
else
@relation
.
select
(
@column
).
public_send
(
mode
).
where
(
between_condition
(
start
,
finish
))
# rubocop:disable GitlabSecurity/PublicSend
end
end
def
batch_size_for_mode_and_operation
(
mode
,
operation
)
return
DEFAULT_SUM_BATCH_SIZE
if
operation
==
:sum
mode
==
:distinct
?
DEFAULT_DISTINCT_BATCH_SIZE
:
DEFAULT_BATCH_SIZE
end
def
between_condition
(
start
,
finish
)
return
@column
.
between
(
start
...
finish
)
if
@column
.
is_a?
(
Arel
::
Attributes
::
Attribute
)
{
@column
=>
start
...
finish
}
end
def
actual_start
(
start
)
start
||
@relation
.
unscope
(
:group
,
:having
).
minimum
(
@column
)
||
0
end
def
actual_finish
(
finish
)
(
finish
||
@relation
.
unscope
(
:group
,
:having
).
maximum
(
@column
)
||
FALLBACK_FINISH
)
+
OFFSET_BY_ONE
end
def
check_mode!
(
mode
)
raise
"The mode
#{
mode
.
inspect
}
is not supported"
unless
ALLOWED_MODES
.
include?
(
mode
)
raise
'Use distinct count for optimized distinct counting'
if
@relation
.
limit
(
1
).
distinct_value
.
present?
&&
mode
!=
:distinct
raise
'Use distinct count only with non id fields'
if
@column
==
:id
&&
mode
==
:distinct
end
def
log_canceled_batch_fetch
(
batch_start
,
mode
,
query
,
error
)
Gitlab
::
AppJsonLogger
.
error
(
event:
'batch_count'
,
relation:
@relation
.
table_name
,
operation:
@operation
,
operation_args:
@operation_args
,
start:
batch_start
,
mode:
mode
,
query:
query
,
message:
"Query has been canceled with message:
#{
error
.
message
}
"
)
end
def
use_loose_index_scan_for_distinct_values?
(
mode
)
Feature
.
enabled?
(
:loose_index_scan_for_distinct_values
)
&&
not_group_by_query?
&&
mode
==
:distinct
end
def
not_group_by_query?
!
@relation
.
is_a?
(
ActiveRecord
::
Relation
)
||
@relation
.
group_values
.
blank?
end
end
end
end
end
end
lib/gitlab/database/batch_counter.rb
0 → 100644
View file @
0df50a45
# frozen_string_literal: true
module
Gitlab
module
Database
class
BatchCounter
FALLBACK
=
-
1
MIN_REQUIRED_BATCH_SIZE
=
1_250
DEFAULT_SUM_BATCH_SIZE
=
1_000
MAX_ALLOWED_LOOPS
=
10_000
SLEEP_TIME_IN_SECONDS
=
0.01
# 10 msec sleep
ALLOWED_MODES
=
[
:itself
,
:distinct
].
freeze
FALLBACK_FINISH
=
0
OFFSET_BY_ONE
=
1
# Each query should take < 500ms https://gitlab.com/gitlab-org/gitlab/-/merge_requests/22705
DEFAULT_DISTINCT_BATCH_SIZE
=
10_000
DEFAULT_BATCH_SIZE
=
100_000
def
initialize
(
relation
,
column:
nil
,
operation: :count
,
operation_args:
nil
)
@relation
=
relation
@column
=
column
||
relation
.
primary_key
@operation
=
operation
@operation_args
=
operation_args
end
def
unwanted_configuration?
(
finish
,
batch_size
,
start
)
(
@operation
==
:count
&&
batch_size
<=
MIN_REQUIRED_BATCH_SIZE
)
||
(
@operation
==
:sum
&&
batch_size
<
DEFAULT_SUM_BATCH_SIZE
)
||
(
finish
-
start
)
/
batch_size
>=
MAX_ALLOWED_LOOPS
||
start
>=
finish
end
def
count
(
batch_size:
nil
,
mode: :itself
,
start:
nil
,
finish:
nil
)
raise
'BatchCount can not be run inside a transaction'
if
ActiveRecord
::
Base
.
connection
.
transaction_open?
check_mode!
(
mode
)
# non-distinct have better performance
batch_size
||=
batch_size_for_mode_and_operation
(
mode
,
@operation
)
start
=
actual_start
(
start
)
finish
=
actual_finish
(
finish
)
raise
"Batch counting expects positive values only for
#{
@column
}
"
if
start
<
0
||
finish
<
0
return
FALLBACK
if
unwanted_configuration?
(
finish
,
batch_size
,
start
)
results
=
nil
batch_start
=
start
while
batch_start
<
finish
begin
batch_end
=
[
batch_start
+
batch_size
,
finish
].
min
batch_relation
=
build_relation_batch
(
batch_start
,
batch_end
,
mode
)
op_args
=
@operation_args
if
@operation
==
:count
&&
@operation_args
.
blank?
&&
use_loose_index_scan_for_distinct_values?
(
mode
)
op_args
=
[
Gitlab
::
Database
::
LooseIndexScanDistinctCount
::
COLUMN_ALIAS
]
end
results
=
merge_results
(
results
,
batch_relation
.
send
(
@operation
,
*
op_args
))
# rubocop:disable GitlabSecurity/PublicSend
batch_start
=
batch_end
rescue
ActiveRecord
::
QueryCanceled
=>
error
# retry with a safe batch size & warmer cache
if
batch_size
>=
2
*
MIN_REQUIRED_BATCH_SIZE
batch_size
/=
2
else
log_canceled_batch_fetch
(
batch_start
,
mode
,
batch_relation
.
to_sql
,
error
)
return
FALLBACK
end
rescue
Gitlab
::
Database
::
LooseIndexScanDistinctCount
::
ColumnConfigurationError
=>
error
Gitlab
::
AppJsonLogger
.
error
(
event:
'batch_count'
,
relation:
@relation
.
table_name
,
operation:
@operation
,
operation_args:
@operation_args
,
mode:
mode
,
message:
"LooseIndexScanDistinctCount column error:
#{
error
.
message
}
"
)
return
FALLBACK
end
sleep
(
SLEEP_TIME_IN_SECONDS
)
end
results
end
def
merge_results
(
results
,
object
)
return
object
unless
results
if
object
.
is_a?
(
Hash
)
results
.
merge!
(
object
)
{
|
_
,
a
,
b
|
a
+
b
}
else
results
+
object
end
end
private
def
build_relation_batch
(
start
,
finish
,
mode
)
if
use_loose_index_scan_for_distinct_values?
(
mode
)
Gitlab
::
Database
::
LooseIndexScanDistinctCount
.
new
(
@relation
,
@column
).
build_query
(
from:
start
,
to:
finish
)
else
@relation
.
select
(
@column
).
public_send
(
mode
).
where
(
between_condition
(
start
,
finish
))
# rubocop:disable GitlabSecurity/PublicSend
end
end
def
batch_size_for_mode_and_operation
(
mode
,
operation
)
return
DEFAULT_SUM_BATCH_SIZE
if
operation
==
:sum
mode
==
:distinct
?
DEFAULT_DISTINCT_BATCH_SIZE
:
DEFAULT_BATCH_SIZE
end
def
between_condition
(
start
,
finish
)
return
@column
.
between
(
start
...
finish
)
if
@column
.
is_a?
(
Arel
::
Attributes
::
Attribute
)
{
@column
=>
start
...
finish
}
end
def
actual_start
(
start
)
start
||
@relation
.
unscope
(
:group
,
:having
).
minimum
(
@column
)
||
0
end
def
actual_finish
(
finish
)
(
finish
||
@relation
.
unscope
(
:group
,
:having
).
maximum
(
@column
)
||
FALLBACK_FINISH
)
+
OFFSET_BY_ONE
end
def
check_mode!
(
mode
)
raise
"The mode
#{
mode
.
inspect
}
is not supported"
unless
ALLOWED_MODES
.
include?
(
mode
)
raise
'Use distinct count for optimized distinct counting'
if
@relation
.
limit
(
1
).
distinct_value
.
present?
&&
mode
!=
:distinct
raise
'Use distinct count only with non id fields'
if
@column
==
:id
&&
mode
==
:distinct
end
def
log_canceled_batch_fetch
(
batch_start
,
mode
,
query
,
error
)
Gitlab
::
AppJsonLogger
.
error
(
event:
'batch_count'
,
relation:
@relation
.
table_name
,
operation:
@operation
,
operation_args:
@operation_args
,
start:
batch_start
,
mode:
mode
,
query:
query
,
message:
"Query has been canceled with message:
#{
error
.
message
}
"
)
end
def
use_loose_index_scan_for_distinct_values?
(
mode
)
Feature
.
enabled?
(
:loose_index_scan_for_distinct_values
)
&&
not_group_by_query?
&&
mode
==
:distinct
end
def
not_group_by_query?
!
@relation
.
is_a?
(
ActiveRecord
::
Relation
)
||
@relation
.
group_values
.
blank?
end
end
end
end
lib/gitlab/database/load_balancing/srv_resolver.rb
View file @
0df50a45
# frozen_string_literal: true
# frozen_string_literal: true
require
'net/dns'
module
Gitlab
module
Gitlab
module
Database
module
Database
module
LoadBalancing
module
LoadBalancing
...
...
lib/gitlab/database/postgresql_adapter/force_disconnectable_mixin.rb
View file @
0df50a45
...
@@ -22,7 +22,7 @@ module Gitlab
...
@@ -22,7 +22,7 @@ module Gitlab
end
end
def
force_disconnect_timer
def
force_disconnect_timer
@force_disconnect_timer
||=
ConnectionTimer
.
starting_now
@force_disconnect_timer
||=
::
Gitlab
::
Database
::
ConnectionTimer
.
starting_now
end
end
end
end
end
end
...
...
spec/lib/gitlab/background_migration/migrate_u2f_webauthn_spec.rb
View file @
0df50a45
...
@@ -2,6 +2,8 @@
...
@@ -2,6 +2,8 @@
require
'spec_helper'
require
'spec_helper'
require
'webauthn/u2f_migrator'
RSpec
.
describe
Gitlab
::
BackgroundMigration
::
MigrateU2fWebauthn
,
:migration
,
schema:
20200925125321
do
RSpec
.
describe
Gitlab
::
BackgroundMigration
::
MigrateU2fWebauthn
,
:migration
,
schema:
20200925125321
do
let
(
:users
)
{
table
(
:users
)
}
let
(
:users
)
{
table
(
:users
)
}
...
...
spec/lib/gitlab/database/migration_helpers_spec.rb
View file @
0df50a45
...
@@ -2184,16 +2184,14 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
...
@@ -2184,16 +2184,14 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
describe
'#backfill_iids'
do
describe
'#backfill_iids'
do
include
MigrationsHelpers
include
MigrationsHelpers
before
do
let
(
:issue_class
)
do
stub_const
(
'Issue'
,
Class
.
new
(
ActiveRecord
::
Base
))
Class
.
new
(
ActiveRecord
::
Base
)
do
Issue
.
class_eval
do
include
AtomicInternalId
include
AtomicInternalId
self
.
table_name
=
'issues'
self
.
table_name
=
'issues'
self
.
inheritance_column
=
:_type_disabled
self
.
inheritance_column
=
:_type_disabled
belongs_to
:project
,
class_name:
"::Project"
belongs_to
:project
,
class_name:
"::Project"
,
inverse_of:
nil
has_internal_id
:iid
,
has_internal_id
:iid
,
scope: :project
,
scope: :project
,
...
@@ -2216,7 +2214,7 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
...
@@ -2216,7 +2214,7 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
model
.
backfill_iids
(
'issues'
)
model
.
backfill_iids
(
'issues'
)
issue
=
Issue
.
create!
(
project_id:
project
.
id
)
issue
=
issue_class
.
create!
(
project_id:
project
.
id
)
expect
(
issue
.
iid
).
to
eq
(
1
)
expect
(
issue
.
iid
).
to
eq
(
1
)
end
end
...
@@ -2227,7 +2225,7 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
...
@@ -2227,7 +2225,7 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
model
.
backfill_iids
(
'issues'
)
model
.
backfill_iids
(
'issues'
)
issue_b
=
Issue
.
create!
(
project_id:
project
.
id
)
issue_b
=
issue_class
.
create!
(
project_id:
project
.
id
)
expect
(
issue_a
.
reload
.
iid
).
to
eq
(
1
)
expect
(
issue_a
.
reload
.
iid
).
to
eq
(
1
)
expect
(
issue_b
.
iid
).
to
eq
(
2
)
expect
(
issue_b
.
iid
).
to
eq
(
2
)
...
@@ -2242,8 +2240,8 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
...
@@ -2242,8 +2240,8 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
model
.
backfill_iids
(
'issues'
)
model
.
backfill_iids
(
'issues'
)
issue_a
=
Issue
.
create!
(
project_id:
project_a
.
id
)
issue_a
=
issue_class
.
create!
(
project_id:
project_a
.
id
)
issue_b
=
Issue
.
create!
(
project_id:
project_b
.
id
)
issue_b
=
issue_class
.
create!
(
project_id:
project_b
.
id
)
expect
(
issue_a
.
iid
).
to
eq
(
2
)
expect
(
issue_a
.
iid
).
to
eq
(
2
)
expect
(
issue_b
.
iid
).
to
eq
(
3
)
expect
(
issue_b
.
iid
).
to
eq
(
3
)
...
@@ -2257,7 +2255,7 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
...
@@ -2257,7 +2255,7 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
model
.
backfill_iids
(
'issues'
)
model
.
backfill_iids
(
'issues'
)
issue_b
=
Issue
.
create!
(
project_id:
project_b
.
id
)
issue_b
=
issue_class
.
create!
(
project_id:
project_b
.
id
)
expect
(
issue_a
.
reload
.
iid
).
to
eq
(
1
)
expect
(
issue_a
.
reload
.
iid
).
to
eq
(
1
)
expect
(
issue_b
.
reload
.
iid
).
to
eq
(
1
)
expect
(
issue_b
.
reload
.
iid
).
to
eq
(
1
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment