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
9d589b9f
Commit
9d589b9f
authored
Aug 30, 2021
by
GitLab Bot
Browse files
Options
Browse Files
Download
Plain Diff
Automatic merge of gitlab-org/gitlab master
parents
77850f8a
94468c74
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
68 additions
and
201 deletions
+68
-201
app/finders/packages/npm/package_finder.rb
app/finders/packages/npm/package_finder.rb
+4
-10
app/presenters/packages/npm/package_presenter.rb
app/presenters/packages/npm/package_presenter.rb
+9
-46
config/feature_flags/development/npm_presenter_queries_tuning.yml
...eature_flags/development/npm_presenter_queries_tuning.yml
+0
-8
spec/finders/packages/npm/package_finder_spec.rb
spec/finders/packages/npm/package_finder_spec.rb
+0
-54
spec/presenters/packages/npm/package_presenter_spec.rb
spec/presenters/packages/npm/package_presenter_spec.rb
+55
-83
No files found.
app/finders/packages/npm/package_finder.rb
View file @
9d589b9f
...
...
@@ -12,16 +12,10 @@ module Packages
end
def
execute
results
=
base
.
npm
.
with_name
(
@package_name
)
.
installable
.
last_of_each_version
unless
Feature
.
enabled?
(
:npm_presenter_queries_tuning
)
results
=
results
.
preload_files
end
results
base
.
npm
.
with_name
(
@package_name
)
.
installable
.
last_of_each_version
end
private
...
...
app/presenters/packages/npm/package_presenter.rb
View file @
9d589b9f
...
...
@@ -13,34 +13,6 @@ module Packages
end
def
versions
if
queries_tuning?
new_versions
else
legacy_versions
end
end
def
dist_tags
build_package_tags
.
tap
{
|
t
|
t
[
"latest"
]
||=
sorted_versions
.
last
}
end
private
def
legacy_versions
package_versions
=
{}
packages
.
each
do
|
package
|
package_file
=
package
.
package_files
.
last
next
unless
package_file
package_versions
[
package
.
version
]
=
build_package_version
(
package
,
package_file
)
end
package_versions
end
def
new_versions
package_versions
=
{}
packages
.
each_batch
do
|
relation
|
...
...
@@ -58,6 +30,12 @@ module Packages
package_versions
end
def
dist_tags
build_package_tags
.
tap
{
|
t
|
t
[
"latest"
]
||=
sorted_versions
.
last
}
end
private
def
build_package_tags
package_tags
.
to_h
{
|
tag
|
[
tag
.
name
,
tag
.
package
.
version
]
}
end
...
...
@@ -84,20 +62,9 @@ module Packages
def
build_package_dependencies
(
package
)
dependencies
=
Hash
.
new
{
|
h
,
key
|
h
[
key
]
=
{}
}
if
queries_tuning?
package
.
dependency_links
.
each
do
|
dependency_link
|
dependency
=
dependency_link
.
dependency
dependencies
[
dependency_link
.
dependency_type
][
dependency
.
name
]
=
dependency
.
version_pattern
end
else
dependency_links
=
package
.
dependency_links
.
with_dependency_type
(
%i[dependencies devDependencies bundleDependencies peerDependencies]
)
.
includes_dependency
dependency_links
.
find_each
do
|
dependency_link
|
dependency
=
dependency_link
.
dependency
dependencies
[
dependency_link
.
dependency_type
][
dependency
.
name
]
=
dependency
.
version_pattern
end
package
.
dependency_links
.
each
do
|
dependency_link
|
dependency
=
dependency_link
.
dependency
dependencies
[
dependency_link
.
dependency_type
][
dependency
.
name
]
=
dependency
.
version_pattern
end
dependencies
...
...
@@ -112,10 +79,6 @@ module Packages
Packages
::
Tag
.
for_packages
(
packages
)
.
preload_package
end
def
queries_tuning?
Feature
.
enabled?
(
:npm_presenter_queries_tuning
)
end
end
end
end
config/feature_flags/development/npm_presenter_queries_tuning.yml
deleted
100644 → 0
View file @
77850f8a
---
name
:
npm_presenter_queries_tuning
introduced_by_url
:
https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68275
rollout_issue_url
:
https://gitlab.com/gitlab-org/gitlab/-/issues/338603
milestone
:
'
14.2'
type
:
development
group
:
group::package
default_enabled
:
false
spec/finders/packages/npm/package_finder_spec.rb
View file @
9d589b9f
...
...
@@ -68,20 +68,6 @@ RSpec.describe ::Packages::Npm::PackageFinder do
it
{
is_expected
.
to
be_empty
}
end
context
'with npm_presenter_queries_tuning disabled'
do
before
do
stub_feature_flags
(
npm_presenter_queries_tuning:
false
)
end
it_behaves_like
'finding packages by name'
context
'set to nil'
do
let
(
:project
)
{
nil
}
it
{
is_expected
.
to
be_empty
}
end
end
end
context
'with a namespace'
do
...
...
@@ -94,20 +80,6 @@ RSpec.describe ::Packages::Npm::PackageFinder do
it
{
is_expected
.
to
be_empty
}
end
context
'with npm_presenter_queries_tuning disabled'
do
before
do
stub_feature_flags
(
npm_presenter_queries_tuning:
false
)
end
it_behaves_like
'accepting a namespace for'
,
'finding packages by name'
context
'set to nil'
do
let_it_be
(
:namespace
)
{
nil
}
it
{
is_expected
.
to
be_empty
}
end
end
end
end
...
...
@@ -137,24 +109,6 @@ RSpec.describe ::Packages::Npm::PackageFinder do
it_behaves_like
'accepting a namespace for'
,
'finding packages by version'
end
context
'with npm_presenter_queries_tuning disabled'
do
before
do
stub_feature_flags
(
npm_presenter_queries_tuning:
false
)
end
context
'with a project'
do
let
(
:finder
)
{
described_class
.
new
(
package_name
,
project:
project
)
}
it_behaves_like
'finding packages by version'
end
context
'with a namespace'
do
let
(
:finder
)
{
described_class
.
new
(
package_name
,
namespace:
namespace
)
}
it_behaves_like
'accepting a namespace for'
,
'finding packages by version'
end
end
end
describe
'#last'
do
...
...
@@ -194,13 +148,5 @@ RSpec.describe ::Packages::Npm::PackageFinder do
end
it_behaves_like
'handling project or namespace parameter'
context
'with npm_presenter_queries_tuning disabled'
do
before
do
stub_feature_flags
(
npm_presenter_queries_tuning:
false
)
end
it_behaves_like
'handling project or namespace parameter'
end
end
end
spec/presenters/packages/npm/package_presenter_spec.rb
View file @
9d589b9f
...
...
@@ -15,110 +15,86 @@ RSpec.describe ::Packages::Npm::PackagePresenter do
describe
'#versions'
do
subject
{
presenter
.
versions
}
shared_examples
'returning packages versions'
do
|
expect_n_plus_one:
false
|
context
'for packages without dependencies'
do
it
{
is_expected
.
to
be_a
(
Hash
)
}
it
{
expect
(
subject
[
package1
.
version
].
with_indifferent_access
).
to
match_schema
(
'public_api/v4/packages/npm_package_version'
)
}
it
{
expect
(
subject
[
package2
.
version
].
with_indifferent_access
).
to
match_schema
(
'public_api/v4/packages/npm_package_version'
)
}
::
Packages
::
DependencyLink
.
dependency_types
.
keys
.
each
do
|
dependency_type
|
it
{
expect
(
subject
.
dig
(
package1
.
version
,
dependency_type
)).
to
be
nil
}
it
{
expect
(
subject
.
dig
(
package2
.
version
,
dependency_type
)).
to
be
nil
}
end
context
'for packages without dependencies'
do
it
{
is_expected
.
to
be_a
(
Hash
)
}
it
{
expect
(
subject
[
package1
.
version
].
with_indifferent_access
).
to
match_schema
(
'public_api/v4/packages/npm_package_version'
)
}
it
{
expect
(
subject
[
package2
.
version
].
with_indifferent_access
).
to
match_schema
(
'public_api/v4/packages/npm_package_version'
)
}
::
Packages
::
DependencyLink
.
dependency_types
.
keys
.
each
do
|
dependency_type
|
it
{
expect
(
subject
.
dig
(
package1
.
version
,
dependency_type
)).
to
be
nil
}
it
{
expect
(
subject
.
dig
(
package2
.
version
,
dependency_type
)).
to
be
nil
}
end
it
'avoids N+1 database queries'
do
check_n_plus_one
(
:versions
,
expect_it:
expect_n_plus_one
)
do
create_list
(
:npm_package
,
5
,
project:
project
,
name:
package_name
)
end
it
'avoids N+1 database queries'
do
check_n_plus_one
(
:versions
)
do
create_list
(
:npm_package
,
5
,
project:
project
,
name:
package_name
)
end
end
end
context
'for packages with dependencies'
do
::
Packages
::
DependencyLink
.
dependency_types
.
keys
.
each
do
|
dependency_type
|
let_it_be
(
"package_dependency_link_for_
#{
dependency_type
}
"
)
{
create
(
:packages_dependency_link
,
package:
package1
,
dependency_type:
dependency_type
)
}
end
context
'for packages with dependencies'
do
::
Packages
::
DependencyLink
.
dependency_types
.
keys
.
each
do
|
dependency_type
|
let_it_be
(
"package_dependency_link_for_
#{
dependency_type
}
"
)
{
create
(
:packages_dependency_link
,
package:
package1
,
dependency_type:
dependency_type
)
}
end
it
{
is_expected
.
to
be_a
(
Hash
)
}
it
{
expect
(
subject
[
package1
.
version
].
with_indifferent_access
).
to
match_schema
(
'public_api/v4/packages/npm_package_version'
)
}
it
{
expect
(
subject
[
package2
.
version
].
with_indifferent_access
).
to
match_schema
(
'public_api/v4/packages/npm_package_version'
)
}
::
Packages
::
DependencyLink
.
dependency_types
.
keys
.
each
do
|
dependency_type
|
it
{
expect
(
subject
.
dig
(
package1
.
version
,
dependency_type
.
to_s
)).
to
be_any
}
end
it
{
is_expected
.
to
be_a
(
Hash
)
}
it
{
expect
(
subject
[
package1
.
version
].
with_indifferent_access
).
to
match_schema
(
'public_api/v4/packages/npm_package_version'
)
}
it
{
expect
(
subject
[
package2
.
version
].
with_indifferent_access
).
to
match_schema
(
'public_api/v4/packages/npm_package_version'
)
}
::
Packages
::
DependencyLink
.
dependency_types
.
keys
.
each
do
|
dependency_type
|
it
{
expect
(
subject
.
dig
(
package1
.
version
,
dependency_type
.
to_s
)).
to
be_any
}
end
it
'avoids N+1 database queries'
do
check_n_plus_one
(
:versions
,
expect_it:
expect_n_plus_one
)
do
create_list
(
:npm_package
,
5
,
project:
project
,
name:
package_name
).
each
do
|
npm_package
|
::
Packages
::
DependencyLink
.
dependency_types
.
keys
.
each
do
|
dependency_type
|
create
(
:packages_dependency_link
,
package:
npm_package
,
dependency_type:
dependency_type
)
end
it
'avoids N+1 database queries'
do
check_n_plus_one
(
:versions
)
do
create_list
(
:npm_package
,
5
,
project:
project
,
name:
package_name
).
each
do
|
npm_package
|
::
Packages
::
DependencyLink
.
dependency_types
.
keys
.
each
do
|
dependency_type
|
create
(
:packages_dependency_link
,
package:
npm_package
,
dependency_type:
dependency_type
)
end
end
end
end
end
it_behaves_like
'returning packages versions'
context
'with npm_presenter_queries_tuning disabled'
do
before
do
stub_feature_flags
(
npm_presenter_queries_tuning:
false
)
end
it_behaves_like
'returning packages versions'
,
expect_n_plus_one:
true
end
end
describe
'#dist_tags'
do
subject
{
presenter
.
dist_tags
}
shared_examples
'returning packages tags'
do
context
'for packages without tags'
do
it
{
is_expected
.
to
be_a
(
Hash
)
}
it
{
expect
(
subject
[
"latest"
]).
to
eq
(
latest_package
.
version
)
}
context
'for packages without tags'
do
it
{
is_expected
.
to
be_a
(
Hash
)
}
it
{
expect
(
subject
[
"latest"
]).
to
eq
(
latest_package
.
version
)
}
it
'avoids N+1 database queries'
do
check_n_plus_one
(
:dist_tags
)
do
create_list
(
:npm_package
,
5
,
project:
project
,
name:
package_name
)
end
it
'avoids N+1 database queries'
do
check_n_plus_one
(
:dist_tags
)
do
create_list
(
:npm_package
,
5
,
project:
project
,
name:
package_name
)
end
end
end
context
'for packages with tags'
do
let_it_be
(
:package_tag1
)
{
create
(
:packages_tag
,
package:
package1
,
name:
'release_a'
)
}
let_it_be
(
:package_tag2
)
{
create
(
:packages_tag
,
package:
package1
,
name:
'test_release'
)
}
let_it_be
(
:package_tag3
)
{
create
(
:packages_tag
,
package:
package2
,
name:
'release_b'
)
}
let_it_be
(
:package_tag4
)
{
create
(
:packages_tag
,
package:
latest_package
,
name:
'release_c'
)
}
let_it_be
(
:package_tag5
)
{
create
(
:packages_tag
,
package:
latest_package
,
name:
'latest'
)
}
it
{
is_expected
.
to
be_a
(
Hash
)
}
it
{
expect
(
subject
[
package_tag1
.
name
]).
to
eq
(
package1
.
version
)
}
it
{
expect
(
subject
[
package_tag2
.
name
]).
to
eq
(
package1
.
version
)
}
it
{
expect
(
subject
[
package_tag3
.
name
]).
to
eq
(
package2
.
version
)
}
it
{
expect
(
subject
[
package_tag4
.
name
]).
to
eq
(
latest_package
.
version
)
}
it
{
expect
(
subject
[
package_tag5
.
name
]).
to
eq
(
latest_package
.
version
)
}
it
'avoids N+1 database queries'
do
check_n_plus_one
(
:dist_tags
)
do
create_list
(
:npm_package
,
5
,
project:
project
,
name:
package_name
).
each_with_index
do
|
npm_package
,
index
|
create
(
:packages_tag
,
package:
npm_package
,
name:
"tag_
#{
index
}
"
)
end
context
'for packages with tags'
do
let_it_be
(
:package_tag1
)
{
create
(
:packages_tag
,
package:
package1
,
name:
'release_a'
)
}
let_it_be
(
:package_tag2
)
{
create
(
:packages_tag
,
package:
package1
,
name:
'test_release'
)
}
let_it_be
(
:package_tag3
)
{
create
(
:packages_tag
,
package:
package2
,
name:
'release_b'
)
}
let_it_be
(
:package_tag4
)
{
create
(
:packages_tag
,
package:
latest_package
,
name:
'release_c'
)
}
let_it_be
(
:package_tag5
)
{
create
(
:packages_tag
,
package:
latest_package
,
name:
'latest'
)
}
it
{
is_expected
.
to
be_a
(
Hash
)
}
it
{
expect
(
subject
[
package_tag1
.
name
]).
to
eq
(
package1
.
version
)
}
it
{
expect
(
subject
[
package_tag2
.
name
]).
to
eq
(
package1
.
version
)
}
it
{
expect
(
subject
[
package_tag3
.
name
]).
to
eq
(
package2
.
version
)
}
it
{
expect
(
subject
[
package_tag4
.
name
]).
to
eq
(
latest_package
.
version
)
}
it
{
expect
(
subject
[
package_tag5
.
name
]).
to
eq
(
latest_package
.
version
)
}
it
'avoids N+1 database queries'
do
check_n_plus_one
(
:dist_tags
)
do
create_list
(
:npm_package
,
5
,
project:
project
,
name:
package_name
).
each_with_index
do
|
npm_package
,
index
|
create
(
:packages_tag
,
package:
npm_package
,
name:
"tag_
#{
index
}
"
)
end
end
end
end
it_behaves_like
'returning packages tags'
context
'with npm_presenter_queries_tuning disabled'
do
before
do
stub_feature_flags
(
npm_presenter_queries_tuning:
false
)
end
it_behaves_like
'returning packages tags'
end
end
def
check_n_plus_one
(
field
,
expect_it:
false
)
def
check_n_plus_one
(
field
)
pkgs
=
project
.
packages
.
npm
.
with_name
(
package_name
).
last_of_each_version
.
preload_files
control
=
ActiveRecord
::
QueryRecorder
.
new
{
described_class
.
new
(
package_name
,
pkgs
).
public_send
(
field
)
}
...
...
@@ -126,10 +102,6 @@ RSpec.describe ::Packages::Npm::PackagePresenter do
pkgs
=
project
.
packages
.
npm
.
with_name
(
package_name
).
last_of_each_version
.
preload_files
if
expect_it
expect
{
described_class
.
new
(
package_name
,
pkgs
).
public_send
(
field
)
}.
to
exceed_query_limit
(
control
)
else
expect
{
described_class
.
new
(
package_name
,
pkgs
).
public_send
(
field
)
}.
not_to
exceed_query_limit
(
control
)
end
expect
{
described_class
.
new
(
package_name
,
pkgs
).
public_send
(
field
)
}.
not_to
exceed_query_limit
(
control
)
end
end
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