BigW Consortium Gitlab
Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
G
gitlab-ce
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Forest Godfrey
gitlab-ce
Commits
908aacdd
Commit
908aacdd
authored
Nov 23, 2017
by
Michael Kozono
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Filter existing uploads with one query
parent
7549d17f
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
58 additions
and
82 deletions
+58
-82
populate_untracked_uploads.rb
...gitlab/background_migration/populate_untracked_uploads.rb
+32
-28
populate_untracked_uploads_spec.rb
...b/background_migration/populate_untracked_uploads_spec.rb
+26
-54
No files found.
lib/gitlab/background_migration/populate_untracked_uploads.rb
View file @
908aacdd
...
@@ -50,31 +50,19 @@ module Gitlab
...
@@ -50,31 +50,19 @@ module Gitlab
}
}
].
freeze
].
freeze
def
ensure_tracked!
def
to_h
add_to_uploads_if_needed
{
path:
upload_path
,
delete
end
def
add_to_uploads_if_needed
# Even though we are checking relative paths, path is enough to
# uniquely identify uploads. There is no ambiguity between
# FileUploader paths and other Uploader paths because we use the /-/
# separator kind of like an escape character. Project full_path will
# never conflict with an upload path starting with "uploads/-/".
Upload
.
where
(
path:
upload_path
).
first_or_create!
(
uploader:
uploader
,
uploader:
uploader
,
model_type:
model_type
,
model_type:
model_type
,
model_id:
model_id
,
model_id:
model_id
,
size:
file_size
size:
file_size
)
}
end
end
def
upload_path
def
upload_path
# UntrackedFile#path is absolute, but Upload#path depends on uploader
# UntrackedFile#path is absolute, but Upload#path depends on uploader
if
uploader
==
'FileUploader'
@upload_path
||=
if
uploader
==
'FileUploader'
# Path relative to project directory in uploads
# Path relative to project directory in uploads
matchd
=
path_relative_to_upload_dir
.
match
(
FILE_UPLOADER_PATH_PATTERN
)
matchd
=
path_relative_to_upload_dir
.
match
(
FILE_UPLOADER_PATH_PATTERN
)
matchd
[
0
].
sub
(
%r{
\A
/}
,
''
)
# remove leading slash
matchd
[
0
].
sub
(
%r{
\A
/}
,
''
)
# remove leading slash
...
@@ -187,17 +175,8 @@ module Gitlab
...
@@ -187,17 +175,8 @@ module Gitlab
return
unless
migrate?
return
unless
migrate?
files
=
UntrackedFile
.
where
(
id:
start_id
..
end_id
)
files
=
UntrackedFile
.
where
(
id:
start_id
..
end_id
)
files
.
each
do
|
untracked_file
|
insert_uploads_if_needed
(
files
)
begin
files
.
delete_all
untracked_file
.
ensure_tracked!
rescue
StandardError
=>
e
Rails
.
logger
.
warn
"Failed to add untracked file to uploads:
#{
e
.
message
}
"
# The untracked rows will remain in the DB. We will be able to see
# which ones failed to become tracked, and then we can decide what
# to do.
end
end
drop_temp_table_if_finished
drop_temp_table_if_finished
end
end
...
@@ -208,6 +187,31 @@ module Gitlab
...
@@ -208,6 +187,31 @@ module Gitlab
UntrackedFile
.
table_exists?
&&
Upload
.
table_exists?
UntrackedFile
.
table_exists?
&&
Upload
.
table_exists?
end
end
def
insert_uploads_if_needed
(
files
)
filtered_files
=
filter_existing_uploads
(
files
)
filtered_files
=
filter_deleted_models
(
filtered_files
)
insert
(
filtered_files
)
end
def
filter_existing_uploads
(
files
)
paths
=
files
.
map
(
&
:upload_path
)
existing_paths
=
Upload
.
where
(
path:
paths
).
pluck
(
:path
).
to_set
files
.
reject
do
|
file
|
existing_paths
.
include?
(
file
.
upload_path
)
end
end
def
filter_deleted_models
(
files
)
files
# TODO
end
def
insert
(
files
)
files
.
each
do
|
file
|
Upload
.
create!
(
file
.
to_h
)
end
end
def
drop_temp_table_if_finished
def
drop_temp_table_if_finished
UntrackedFile
.
connection
.
drop_table
(
:untracked_files_for_uploads
)
if
UntrackedFile
.
all
.
empty?
UntrackedFile
.
connection
.
drop_table
(
:untracked_files_for_uploads
)
if
UntrackedFile
.
all
.
empty?
end
end
...
...
spec/lib/gitlab/background_migration/populate_untracked_uploads_spec.rb
View file @
908aacdd
...
@@ -126,50 +126,11 @@ describe Gitlab::BackgroundMigration::PopulateUntrackedUploads, :migration, :sid
...
@@ -126,50 +126,11 @@ describe Gitlab::BackgroundMigration::PopulateUntrackedUploads, :migration, :sid
end
.
not_to
change
{
uploads
.
count
}.
from
(
0
)
end
.
not_to
change
{
uploads
.
count
}.
from
(
0
)
end
end
end
end
end
describe
Gitlab
::
BackgroundMigration
::
PopulateUntrackedUploads
::
UntrackedFile
do
include
TrackUntrackedUploadsHelpers
let
(
:upload_class
)
{
Gitlab
::
BackgroundMigration
::
PopulateUntrackedUploads
::
Upload
}
before
(
:all
)
do
ensure_temporary_tracking_table_exists
end
after
(
:all
)
do
drop_temp_table_if_exists
end
describe
'#ensure_tracked!'
do
let!
(
:user1
)
{
create
(
:user
,
:with_avatar
)
}
let!
(
:untracked_file
)
{
described_class
.
create!
(
path:
user1
.
uploads
.
first
.
path
)
}
context
'when the file is already in the uploads table'
do
it
'does not add an upload'
do
expect
do
untracked_file
.
ensure_tracked!
end
.
not_to
change
{
upload_class
.
count
}.
from
(
1
)
end
end
context
'when the file is not already in the uploads table'
do
before
do
user1
.
uploads
.
delete_all
end
it
'adds an upload'
do
describe
'upload outcomes for each path pattern'
do
expect
do
shared_examples_for
'non_markdown_file'
do
untracked_file
.
ensure_tracked!
end
.
to
change
{
upload_class
.
count
}.
from
(
0
).
to
(
1
)
end
end
end
describe
'#add_to_uploads_if_needed'
do
shared_examples_for
'add_to_uploads_non_markdown_files'
do
let!
(
:expected_upload_attrs
)
{
model
.
uploads
.
first
.
attributes
.
slice
(
'path'
,
'uploader'
,
'size'
,
'checksum'
)
}
let!
(
:expected_upload_attrs
)
{
model
.
uploads
.
first
.
attributes
.
slice
(
'path'
,
'uploader'
,
'size'
,
'checksum'
)
}
let!
(
:untracked_file
)
{
described_clas
s
.
create!
(
path:
expected_upload_attrs
[
'path'
])
}
let!
(
:untracked_file
)
{
untracked_files_for_upload
s
.
create!
(
path:
expected_upload_attrs
[
'path'
])
}
before
do
before
do
model
.
uploads
.
delete_all
model
.
uploads
.
delete_all
...
@@ -177,7 +138,7 @@ describe Gitlab::BackgroundMigration::PopulateUntrackedUploads::UntrackedFile do
...
@@ -177,7 +138,7 @@ describe Gitlab::BackgroundMigration::PopulateUntrackedUploads::UntrackedFile do
it
'creates an Upload record'
do
it
'creates an Upload record'
do
expect
do
expect
do
untracked_file
.
add_to_uploads_if_needed
subject
.
perform
(
1
,
1000
)
end
.
to
change
{
model
.
reload
.
uploads
.
count
}.
from
(
0
).
to
(
1
)
end
.
to
change
{
model
.
reload
.
uploads
.
count
}.
from
(
0
).
to
(
1
)
expect
(
model
.
uploads
.
first
.
attributes
).
to
include
(
expected_upload_attrs
)
expect
(
model
.
uploads
.
first
.
attributes
).
to
include
(
expected_upload_attrs
)
...
@@ -187,13 +148,13 @@ describe Gitlab::BackgroundMigration::PopulateUntrackedUploads::UntrackedFile do
...
@@ -187,13 +148,13 @@ describe Gitlab::BackgroundMigration::PopulateUntrackedUploads::UntrackedFile do
context
'for an appearance logo file path'
do
context
'for an appearance logo file path'
do
let
(
:model
)
{
create
(
:appearance
,
logo:
uploaded_file
)
}
let
(
:model
)
{
create
(
:appearance
,
logo:
uploaded_file
)
}
it_behaves_like
'
add_to_uploads_non_markdown_files
'
it_behaves_like
'
non_markdown_file
'
end
end
context
'for an appearance header_logo file path'
do
context
'for an appearance header_logo file path'
do
let
(
:model
)
{
create
(
:appearance
,
header_logo:
uploaded_file
)
}
let
(
:model
)
{
create
(
:appearance
,
header_logo:
uploaded_file
)
}
it_behaves_like
'
add_to_uploads_non_markdown_files
'
it_behaves_like
'
non_markdown_file
'
end
end
context
'for a pre-Markdown Note attachment file path'
do
context
'for a pre-Markdown Note attachment file path'
do
...
@@ -203,39 +164,36 @@ describe Gitlab::BackgroundMigration::PopulateUntrackedUploads::UntrackedFile do
...
@@ -203,39 +164,36 @@ describe Gitlab::BackgroundMigration::PopulateUntrackedUploads::UntrackedFile do
let
(
:model
)
{
create
(
:note
,
:with_attachment
)
}
let
(
:model
)
{
create
(
:note
,
:with_attachment
)
}
it_behaves_like
'
add_to_uploads_non_markdown_files
'
it_behaves_like
'
non_markdown_file
'
end
end
context
'for a user avatar file path'
do
context
'for a user avatar file path'
do
let
(
:model
)
{
create
(
:user
,
:with_avatar
)
}
let
(
:model
)
{
create
(
:user
,
:with_avatar
)
}
it_behaves_like
'
add_to_uploads_non_markdown_files
'
it_behaves_like
'
non_markdown_file
'
end
end
context
'for a group avatar file path'
do
context
'for a group avatar file path'
do
let
(
:model
)
{
create
(
:group
,
:with_avatar
)
}
let
(
:model
)
{
create
(
:group
,
:with_avatar
)
}
it_behaves_like
'
add_to_uploads_non_markdown_files
'
it_behaves_like
'
non_markdown_file
'
end
end
context
'for a project avatar file path'
do
context
'for a project avatar file path'
do
let
(
:model
)
{
create
(
:project
,
:with_avatar
)
}
let
(
:model
)
{
create
(
:project
,
:with_avatar
)
}
it_behaves_like
'
add_to_uploads_non_markdown_files
'
it_behaves_like
'
non_markdown_file
'
end
end
context
'for a project Markdown attachment (notes, issues, MR descriptions) file path'
do
context
'for a project Markdown attachment (notes, issues, MR descriptions) file path'
do
let
(
:model
)
{
create
(
:project
)
}
let
(
:model
)
{
create
(
:project
)
}
# UntrackedFile.path is different than Upload.path
let
(
:untracked_file
)
{
create_untracked_file
(
"/
#{
model
.
full_path
}
/
#{
model
.
uploads
.
first
.
path
}
"
)
}
before
do
before
do
# Upload the file
# Upload the file
UploadService
.
new
(
model
,
uploaded_file
,
FileUploader
).
execute
UploadService
.
new
(
model
,
uploaded_file
,
FileUploader
).
execute
# Create the untracked_files_for_uploads record
# Create the untracked_files_for_uploads record
untracked_file
untracked_file
s_for_uploads
.
create!
(
path:
"
#{
Gitlab
::
BackgroundMigration
::
PrepareUntrackedUploads
::
RELATIVE_UPLOAD_DIR
}
/
#{
model
.
full_path
}
/
#{
model
.
uploads
.
first
.
path
}
"
)
# Save the expected upload attributes
# Save the expected upload attributes
@expected_upload_attrs
=
model
.
reload
.
uploads
.
first
.
attributes
.
slice
(
'path'
,
'uploader'
,
'size'
,
'checksum'
)
@expected_upload_attrs
=
model
.
reload
.
uploads
.
first
.
attributes
.
slice
(
'path'
,
'uploader'
,
'size'
,
'checksum'
)
...
@@ -246,13 +204,27 @@ describe Gitlab::BackgroundMigration::PopulateUntrackedUploads::UntrackedFile do
...
@@ -246,13 +204,27 @@ describe Gitlab::BackgroundMigration::PopulateUntrackedUploads::UntrackedFile do
it
'creates an Upload record'
do
it
'creates an Upload record'
do
expect
do
expect
do
untracked_file
.
add_to_uploads_if_needed
subject
.
perform
(
1
,
1000
)
end
.
to
change
{
model
.
reload
.
uploads
.
count
}.
from
(
0
).
to
(
1
)
end
.
to
change
{
model
.
reload
.
uploads
.
count
}.
from
(
0
).
to
(
1
)
expect
(
model
.
uploads
.
first
.
attributes
).
to
include
(
@expected_upload_attrs
)
expect
(
model
.
uploads
.
first
.
attributes
).
to
include
(
@expected_upload_attrs
)
end
end
end
end
end
end
end
describe
Gitlab
::
BackgroundMigration
::
PopulateUntrackedUploads
::
UntrackedFile
do
include
TrackUntrackedUploadsHelpers
let
(
:upload_class
)
{
Gitlab
::
BackgroundMigration
::
PopulateUntrackedUploads
::
Upload
}
before
(
:all
)
do
ensure_temporary_tracking_table_exists
end
after
(
:all
)
do
drop_temp_table_if_exists
end
describe
'#upload_path'
do
describe
'#upload_path'
do
def
assert_upload_path
(
file_path
,
expected_upload_path
)
def
assert_upload_path
(
file_path
,
expected_upload_path
)
...
...
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