summaryrefslogtreecommitdiff
path: root/app/uploaders/object_storage.rb
diff options
context:
space:
mode:
Diffstat (limited to 'app/uploaders/object_storage.rb')
-rw-r--r--app/uploaders/object_storage.rb28
1 files changed, 22 insertions, 6 deletions
diff --git a/app/uploaders/object_storage.rb b/app/uploaders/object_storage.rb
index 4188e0caa8e..e1e103e20f8 100644
--- a/app/uploaders/object_storage.rb
+++ b/app/uploaders/object_storage.rb
@@ -11,6 +11,7 @@ module ObjectStorage
RemoteStoreError = Class.new(StandardError)
UnknownStoreError = Class.new(StandardError)
ObjectStorageUnavailable = Class.new(StandardError)
+ MissingFinalStorePathRootId = Class.new(StandardError)
class ExclusiveLeaseTaken < StandardError
def initialize(lease_key)
@@ -153,21 +154,30 @@ module ObjectStorage
[CarrierWave.generate_cache_id, SecureRandom.hex].join('-')
end
- def generate_final_store_path
+ def generate_final_store_path(root_id:)
hash = Digest::SHA2.hexdigest(SecureRandom.uuid)
# We prefix '@final' to prevent clashes and make the files easily recognizable
# as having been created by this code.
- File.join('@final', hash[0..1], hash[2..3], hash[4..])
+ sub_path = File.join('@final', hash[0..1], hash[2..3], hash[4..])
+
+ # We generate a hashed path of the root ID (e.g. Project ID) to distribute directories instead of
+ # filling up one root directory with a bunch of files.
+ Gitlab::HashedPath.new(sub_path, root_hash: root_id).to_s
end
- def workhorse_authorize(has_length:, maximum_size: nil, use_final_store_path: false)
+ def workhorse_authorize(
+ has_length:,
+ maximum_size: nil,
+ use_final_store_path: false,
+ final_store_path_root_id: nil)
{}.tap do |hash|
if self.direct_upload_to_object_store?
hash[:RemoteObject] = workhorse_remote_upload_options(
has_length: has_length,
maximum_size: maximum_size,
- use_final_store_path: use_final_store_path
+ use_final_store_path: use_final_store_path,
+ final_store_path_root_id: final_store_path_root_id
)
else
hash[:TempPath] = workhorse_local_upload_path
@@ -190,11 +200,17 @@ module ObjectStorage
ObjectStorage::Config.new(object_store_options)
end
- def workhorse_remote_upload_options(has_length:, maximum_size: nil, use_final_store_path: false)
+ def workhorse_remote_upload_options(
+ has_length:,
+ maximum_size: nil,
+ use_final_store_path: false,
+ final_store_path_root_id: nil)
return unless direct_upload_to_object_store?
if use_final_store_path
- id = generate_final_store_path
+ raise MissingFinalStorePathRootId unless final_store_path_root_id.present?
+
+ id = generate_final_store_path(root_id: final_store_path_root_id)
upload_path = with_bucket_prefix(id)
prepare_pending_direct_upload(id)
else