aws-sdk-s3 1.192.0 → 1.201.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -358,8 +358,8 @@ module Aws
358
358
  # {Client#complete_multipart_upload},
359
359
  # and {Client#upload_part} can be provided.
360
360
  #
361
- # @option options [Integer] :thread_count (10) The number of parallel
362
- # multipart uploads
361
+ # @option options [Integer] :thread_count (10) The number of parallel multipart uploads.
362
+ # An additional thread is used internally for task coordination.
363
363
  #
364
364
  # @option options [Boolean] :tempfile (false) Normally read data is stored
365
365
  # in memory when building the parts in order to complete the underlying
@@ -383,29 +383,28 @@ module Aws
383
383
  # @see Client#complete_multipart_upload
384
384
  # @see Client#upload_part
385
385
  def upload_stream(options = {}, &block)
386
- uploading_options = options.dup
386
+ upload_opts = options.merge(bucket: bucket_name, key: key)
387
+ executor = DefaultExecutor.new(max_threads: upload_opts.delete(:thread_count))
387
388
  uploader = MultipartStreamUploader.new(
388
389
  client: client,
389
- thread_count: uploading_options.delete(:thread_count),
390
- tempfile: uploading_options.delete(:tempfile),
391
- part_size: uploading_options.delete(:part_size)
390
+ executor: executor,
391
+ tempfile: upload_opts.delete(:tempfile),
392
+ part_size: upload_opts.delete(:part_size)
392
393
  )
393
394
  Aws::Plugins::UserAgent.metric('RESOURCE_MODEL') do
394
- uploader.upload(
395
- uploading_options.merge(bucket: bucket_name, key: key),
396
- &block
397
- )
395
+ uploader.upload(upload_opts, &block)
398
396
  end
397
+ executor.shutdown
399
398
  true
400
399
  end
400
+ deprecated(:upload_stream, use: 'Aws::S3::TransferManager#upload_stream', version: 'next major version')
401
401
 
402
402
  # Uploads a file from disk to the current object in S3.
403
403
  #
404
404
  # # small files are uploaded in a single API call
405
405
  # obj.upload_file('/path/to/file')
406
406
  #
407
- # Files larger than or equal to `:multipart_threshold` are uploaded
408
- # using the Amazon S3 multipart upload APIs.
407
+ # Files larger than or equal to `:multipart_threshold` are uploaded using the Amazon S3 multipart upload APIs.
409
408
  #
410
409
  # # large files are automatically split into parts
411
410
  # # and the parts are uploaded in parallel
@@ -421,74 +420,65 @@ module Aws
421
420
  # You can provide a callback to monitor progress of the upload:
422
421
  #
423
422
  # # bytes and totals are each an array with 1 entry per part
424
- # progress = Proc.new do |bytes, totals|
425
- # puts bytes.map.with_index { |b, i| "Part #{i+1}: #{b} / #{totals[i]}"}.join(' ') + "Total: #{100.0 * bytes.sum / totals.sum }%" }
423
+ # progress = proc do |bytes, totals|
424
+ # puts bytes.map.with_index { |b, i| "Part #{i+1}: #{b} / #{totals[i]}"}.join(' ') + "Total: #{100.0 * bytes.sum / totals.sum }%"
426
425
  # end
427
426
  # obj.upload_file('/path/to/file', progress_callback: progress)
428
427
  #
429
- # @param [String, Pathname, File, Tempfile] source A file on the local
430
- # file system that will be uploaded as this object. This can either be
431
- # a String or Pathname to the file, an open File object, or an open
432
- # Tempfile object. If you pass an open File or Tempfile object, then
433
- # you are responsible for closing it after the upload completes. When
434
- # using an open Tempfile, rewind it before uploading or else the object
428
+ # @param [String, Pathname, File, Tempfile] source A file on the local file system that will be uploaded as
429
+ # this object. This can either be a String or Pathname to the file, an open File object, or an open
430
+ # Tempfile object. If you pass an open File or Tempfile object, then you are responsible for closing it
431
+ # after the upload completes. When using an open Tempfile, rewind it before uploading or else the object
435
432
  # will be empty.
436
433
  #
437
434
  # @param [Hash] options
438
- # Additional options for {Client#put_object}
439
- # when file sizes below the multipart threshold. For files larger than
440
- # the multipart threshold, options for {Client#create_multipart_upload},
441
- # {Client#complete_multipart_upload},
442
- # and {Client#upload_part} can be provided.
435
+ # Additional options for {Client#put_object} when file sizes below the multipart threshold.
436
+ # For files larger than the multipart threshold, options for {Client#create_multipart_upload},
437
+ # {Client#complete_multipart_upload}, and {Client#upload_part} can be provided.
443
438
  #
444
- # @option options [Integer] :multipart_threshold (104857600) Files larger
445
- # than or equal to `:multipart_threshold` are uploaded using the S3
446
- # multipart APIs.
447
- # Default threshold is 100MB.
439
+ # @option options [Integer] :multipart_threshold (104857600) Files larger han or equal to
440
+ # `:multipart_threshold` are uploaded using the S3 multipart APIs. Default threshold is 100MB.
448
441
  #
449
- # @option options [Integer] :thread_count (10) The number of parallel
450
- # multipart uploads. This option is not used if the file is smaller than
451
- # `:multipart_threshold`.
442
+ # @option options [Integer] :thread_count (10) The number of parallel multipart uploads.
443
+ # This option is not used if the file is smaller than `:multipart_threshold`.
452
444
  #
453
445
  # @option options [Proc] :progress_callback
454
446
  # A Proc that will be called when each chunk of the upload is sent.
455
447
  # It will be invoked with [bytes_read], [total_sizes]
456
448
  #
457
- # @raise [MultipartUploadError] If an object is being uploaded in
458
- # parts, and the upload can not be completed, then the upload is
459
- # aborted and this error is raised. The raised error has a `#errors`
460
- # method that returns the failures that caused the upload to be
461
- # aborted.
449
+ # @raise [MultipartUploadError] If an object is being uploaded in parts, and the upload can not be completed,
450
+ # then the upload is aborted and this error is raised. The raised error has a `#errors` method that
451
+ # returns the failures that caused the upload to be aborted.
462
452
  #
463
- # @return [Boolean] Returns `true` when the object is uploaded
464
- # without any errors.
453
+ # @return [Boolean] Returns `true` when the object is uploaded without any errors.
465
454
  #
466
455
  # @see Client#put_object
467
456
  # @see Client#create_multipart_upload
468
457
  # @see Client#complete_multipart_upload
469
458
  # @see Client#upload_part
470
459
  def upload_file(source, options = {})
471
- uploading_options = options.dup
460
+ upload_opts = options.merge(bucket: bucket_name, key: key)
461
+ executor = DefaultExecutor.new(max_threads: upload_opts.delete(:thread_count))
472
462
  uploader = FileUploader.new(
473
- multipart_threshold: uploading_options.delete(:multipart_threshold),
474
- client: client
463
+ client: client,
464
+ executor: executor,
465
+ multipart_threshold: upload_opts.delete(:multipart_threshold)
475
466
  )
476
467
  response = Aws::Plugins::UserAgent.metric('RESOURCE_MODEL') do
477
- uploader.upload(
478
- source,
479
- uploading_options.merge(bucket: bucket_name, key: key)
480
- )
468
+ uploader.upload(source, upload_opts)
481
469
  end
482
470
  yield response if block_given?
471
+ executor.shutdown
483
472
  true
484
473
  end
474
+ deprecated(:upload_file, use: 'Aws::S3::TransferManager#upload_file', version: 'next major version')
485
475
 
486
476
  # Downloads a file in S3 to a path on disk.
487
477
  #
488
478
  # # small files (< 5MB) are downloaded in a single API call
489
479
  # obj.download_file('/path/to/file')
490
480
  #
491
- # Files larger than 5MB are downloaded using multipart method
481
+ # Files larger than 5MB are downloaded using multipart method:
492
482
  #
493
483
  # # large files are split into parts
494
484
  # # and the parts are downloaded in parallel
@@ -498,67 +488,68 @@ module Aws
498
488
  #
499
489
  # # bytes and part_sizes are each an array with 1 entry per part
500
490
  # # part_sizes may not be known until the first bytes are retrieved
501
- # progress = Proc.new do |bytes, part_sizes, file_size|
502
- # puts bytes.map.with_index { |b, i| "Part #{i+1}: #{b} / #{part_sizes[i]}"}.join(' ') + "Total: #{100.0 * bytes.sum / file_size}%" }
491
+ # progress = proc do |bytes, part_sizes, file_size|
492
+ # puts bytes.map.with_index { |b, i| "Part #{i + 1}: #{b} / #{part_sizes[i]}" }.join(' ') + "Total: #{100.0 * bytes.sum / file_size}%"
503
493
  # end
504
494
  # obj.download_file('/path/to/file', progress_callback: progress)
505
495
  #
506
- # @param [String] destination Where to download the file to.
496
+ # @param [String, Pathname, File, Tempfile] destination
497
+ # Where to download the file to. This can either be a String or Pathname to the file, an open File object,
498
+ # or an open Tempfile object. If you pass an open File or Tempfile object, then you are responsible for
499
+ # closing it after the download completes. Download behavior varies by destination type:
500
+ #
501
+ # * **String/Pathname paths**: Downloads to a temporary file first, then atomically moves to the final
502
+ # destination. This prevents corruption of any existing file if the download fails.
503
+ # * **File/Tempfile objects**: Downloads directly to the file object without using temporary files.
504
+ # You are responsible for managing the file object's state and closing it after the download completes.
505
+ # If the download fails, the file object may contain partial data.
507
506
  #
508
507
  # @param [Hash] options
509
- # Additional options for {Client#get_object} and #{Client#head_object}
510
- # may be provided.
508
+ # Additional options for {Client#get_object} and #{Client#head_object} may be provided.
511
509
  #
512
- # @option options [String] mode `auto`, `single_request`, `get_range`
513
- # `single_request` mode forces only 1 GET request is made in download,
514
- # `get_range` mode allows `chunk_size` parameter to configured in
515
- # customizing each range size in multipart_download,
516
- # By default, `auto` mode is enabled, which performs multipart_download
510
+ # @option options [String] :mode ("auto") `"auto"`, `"single_request"` or `"get_range"`
517
511
  #
518
- # @option options [Integer] chunk_size required in get_range mode.
512
+ # * `auto` mode is enabled by default, which performs `multipart_download`
513
+ # * `"single_request`" mode forces only 1 GET request is made in download
514
+ # * `"get_range"` mode requires `:chunk_size` parameter to configured in customizing each range size
519
515
  #
520
- # @option options [Integer] thread_count (10) Customize threads used in
521
- # the multipart download.
516
+ # @option options [Integer] :chunk_size required in `"get_range"` mode.
522
517
  #
523
- # @option options [String] version_id The object version id used to
524
- # retrieve the object. For more about object versioning, see:
525
- # https://docs.aws.amazon.com/AmazonS3/latest/dev/ObjectVersioning.html
518
+ # @option options [Integer] :thread_count (10) Customize threads used in the multipart download.
526
519
  #
527
- # @option options [String] checksum_mode (ENABLED) When `ENABLED` and
528
- # the object has a stored checksum, it will be used to validate the
529
- # download and will raise an `Aws::Errors::ChecksumError` if
530
- # checksum validation fails. You may provide a `on_checksum_validated`
531
- # callback if you need to verify that validation occurred and which
532
- # algorithm was used. To disable checksum validation, set
533
- # `checksum_mode` to "DISABLED".
520
+ # @option options [String] :checksum_mode ("ENABLED")
521
+ # When `"ENABLED"` and the object has a stored checksum, it will be used to validate the download and will
522
+ # raise an `Aws::Errors::ChecksumError` if checksum validation fails. You may provide a `on_checksum_validated`
523
+ # callback if you need to verify that validation occurred and which algorithm was used.
524
+ # To disable checksum validation, set `checksum_mode` to `"DISABLED"`.
534
525
  #
535
- # @option options [Callable] on_checksum_validated Called each time a
536
- # request's checksum is validated with the checksum algorithm and the
537
- # response. For multipart downloads, this will be called for each
538
- # part that is downloaded and validated.
526
+ # @option options [Callable] :on_checksum_validated
527
+ # Called each time a request's checksum is validated with the checksum algorithm and the
528
+ # response. For multipart downloads, this will be called for each part that is downloaded and validated.
539
529
  #
540
530
  # @option options [Proc] :progress_callback
541
- # A Proc that will be called when each chunk of the download is received.
542
- # It will be invoked with [bytes_read], [part_sizes], file_size.
543
- # When the object is downloaded as parts (rather than by ranges), the
544
- # part_sizes will not be known ahead of time and will be nil in the
545
- # callback until the first bytes in the part are received.
531
+ # A Proc that will be called when each chunk of the download is received. It will be invoked with
532
+ # `bytes_read`, `part_sizes`, `file_size`. When the object is downloaded as parts (rather than by ranges),
533
+ # the `part_sizes` will not be known ahead of time and will be `nil` in the callback until the first bytes
534
+ # in the part are received.
535
+ #
536
+ # @raise [MultipartDownloadError] Raised when an object validation fails outside of service errors.
546
537
  #
547
- # @return [Boolean] Returns `true` when the file is downloaded without
548
- # any errors.
538
+ # @return [Boolean] Returns `true` when the file is downloaded without any errors.
549
539
  #
550
540
  # @see Client#get_object
551
541
  # @see Client#head_object
552
542
  def download_file(destination, options = {})
553
- downloader = FileDownloader.new(client: client)
543
+ download_opts = options.merge(bucket: bucket_name, key: key)
544
+ executor = DefaultExecutor.new(max_threads: download_opts.delete([:thread_count]))
545
+ downloader = FileDownloader.new(client: client, executor: executor)
554
546
  Aws::Plugins::UserAgent.metric('RESOURCE_MODEL') do
555
- downloader.download(
556
- destination,
557
- options.merge(bucket: bucket_name, key: key)
558
- )
547
+ downloader.download(destination, download_opts)
559
548
  end
549
+ executor.shutdown
560
550
  true
561
551
  end
552
+ deprecated(:download_file, use: 'Aws::S3::TransferManager#download_file', version: 'next major version')
562
553
 
563
554
  class Collection < Aws::Resources::Collection
564
555
  alias_method :delete, :batch_delete!
@@ -7,9 +7,11 @@ module Aws
7
7
  autoload :Encryption, 'aws-sdk-s3/encryption'
8
8
  autoload :EncryptionV2, 'aws-sdk-s3/encryption_v2'
9
9
  autoload :FilePart, 'aws-sdk-s3/file_part'
10
+ autoload :DefaultExecutor, 'aws-sdk-s3/default_executor'
10
11
  autoload :FileUploader, 'aws-sdk-s3/file_uploader'
11
12
  autoload :FileDownloader, 'aws-sdk-s3/file_downloader'
12
13
  autoload :LegacySigner, 'aws-sdk-s3/legacy_signer'
14
+ autoload :MultipartDownloadError, 'aws-sdk-s3/multipart_download_error'
13
15
  autoload :MultipartFileUploader, 'aws-sdk-s3/multipart_file_uploader'
14
16
  autoload :MultipartStreamUploader, 'aws-sdk-s3/multipart_stream_uploader'
15
17
  autoload :MultipartUploadError, 'aws-sdk-s3/multipart_upload_error'
@@ -17,13 +19,13 @@ module Aws
17
19
  autoload :ObjectMultipartCopier, 'aws-sdk-s3/object_multipart_copier'
18
20
  autoload :PresignedPost, 'aws-sdk-s3/presigned_post'
19
21
  autoload :Presigner, 'aws-sdk-s3/presigner'
22
+ autoload :TransferManager, 'aws-sdk-s3/transfer_manager'
20
23
 
21
24
  # s3 express session auth
22
25
  autoload :ExpressCredentials, 'aws-sdk-s3/express_credentials'
23
26
  autoload :ExpressCredentialsProvider, 'aws-sdk-s3/express_credentials_provider'
24
27
 
25
28
  # s3 access grants auth
26
-
27
29
  autoload :AccessGrantsCredentials, 'aws-sdk-s3/access_grants_credentials'
28
30
  autoload :AccessGrantsCredentialsProvider, 'aws-sdk-s3/access_grants_credentials_provider'
29
31
  end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Aws
4
+ module S3
5
+ # @api private
6
+ class DefaultExecutor
7
+ DEFAULT_MAX_THREADS = 10
8
+ RUNNING = :running
9
+ SHUTTING_DOWN = :shutting_down
10
+ SHUTDOWN = :shutdown
11
+
12
+ def initialize(options = {})
13
+ @max_threads = options[:max_threads] || DEFAULT_MAX_THREADS
14
+ @state = RUNNING
15
+ @queue = Queue.new
16
+ @pool = []
17
+ @mutex = Mutex.new
18
+ end
19
+
20
+ # Submits a task for execution.
21
+ # @param [Object] args Variable number of arguments to pass to the block
22
+ # @param [Proc] block The block to be executed
23
+ # @return [Boolean] Returns true if the task was submitted successfully
24
+ def post(*args, &block)
25
+ @mutex.synchronize do
26
+ raise 'Executor has been shutdown and is no longer accepting tasks' unless @state == RUNNING
27
+
28
+ @queue << [args, block]
29
+ ensure_worker_available
30
+ end
31
+ true
32
+ end
33
+
34
+ # Immediately terminates all worker threads and clears pending tasks.
35
+ # This is a forceful shutdown that doesn't wait for running tasks to complete.
36
+ #
37
+ # @return [Boolean] true when termination is complete
38
+ def kill
39
+ @mutex.synchronize do
40
+ @state = SHUTDOWN
41
+ @pool.each(&:kill)
42
+ @pool.clear
43
+ @queue.clear
44
+ end
45
+ true
46
+ end
47
+
48
+ # Gracefully shuts down the executor, optionally with a timeout.
49
+ # Stops accepting new tasks and waits for running tasks to complete.
50
+ #
51
+ # @param timeout [Numeric, nil] Maximum time in seconds to wait for shutdown.
52
+ # If nil, waits indefinitely. If timeout expires, remaining threads are killed.
53
+ # @return [Boolean] true when shutdown is complete
54
+ def shutdown(timeout = nil)
55
+ @mutex.synchronize do
56
+ return true if @state == SHUTDOWN
57
+
58
+ @state = SHUTTING_DOWN
59
+ @pool.size.times { @queue << :shutdown }
60
+ end
61
+
62
+ if timeout
63
+ deadline = Time.now + timeout
64
+ @pool.each do |thread|
65
+ remaining = deadline - Time.now
66
+ break if remaining <= 0
67
+
68
+ thread.join([remaining, 0].max)
69
+ end
70
+ @pool.select(&:alive?).each(&:kill)
71
+ else
72
+ @pool.each(&:join)
73
+ end
74
+
75
+ @mutex.synchronize do
76
+ @pool.clear
77
+ @state = SHUTDOWN
78
+ end
79
+ true
80
+ end
81
+
82
+ private
83
+
84
+ def ensure_worker_available
85
+ return unless @state == RUNNING
86
+
87
+ @pool.select!(&:alive?)
88
+ @pool << spawn_worker if @pool.size < @max_threads
89
+ end
90
+
91
+ def spawn_worker
92
+ Thread.new do
93
+ while (job = @queue.shift)
94
+ break if job == :shutdown
95
+
96
+ args, block = job
97
+ block.call(*args)
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -63,6 +63,18 @@ module Aws::S3
63
63
  end
64
64
  end
65
65
 
66
+ class CreateBucketMetadataConfiguration
67
+ def self.build(context)
68
+ Aws::S3::EndpointParameters.create(
69
+ context.config,
70
+ bucket: context.params[:bucket],
71
+ use_dual_stack: context[:use_dualstack_endpoint],
72
+ accelerate: context[:use_accelerate_endpoint],
73
+ use_s3_express_control_endpoint: true,
74
+ )
75
+ end
76
+ end
77
+
66
78
  class CreateBucketMetadataTableConfiguration
67
79
  def self.build(context)
68
80
  Aws::S3::EndpointParameters.create(
@@ -183,6 +195,18 @@ module Aws::S3
183
195
  end
184
196
  end
185
197
 
198
+ class DeleteBucketMetadataConfiguration
199
+ def self.build(context)
200
+ Aws::S3::EndpointParameters.create(
201
+ context.config,
202
+ bucket: context.params[:bucket],
203
+ use_dual_stack: context[:use_dualstack_endpoint],
204
+ accelerate: context[:use_accelerate_endpoint],
205
+ use_s3_express_control_endpoint: true,
206
+ )
207
+ end
208
+ end
209
+
186
210
  class DeleteBucketMetadataTableConfiguration
187
211
  def self.build(context)
188
212
  Aws::S3::EndpointParameters.create(
@@ -445,6 +469,18 @@ module Aws::S3
445
469
  end
446
470
  end
447
471
 
472
+ class GetBucketMetadataConfiguration
473
+ def self.build(context)
474
+ Aws::S3::EndpointParameters.create(
475
+ context.config,
476
+ bucket: context.params[:bucket],
477
+ use_dual_stack: context[:use_dualstack_endpoint],
478
+ accelerate: context[:use_accelerate_endpoint],
479
+ use_s3_express_control_endpoint: true,
480
+ )
481
+ end
482
+ end
483
+
448
484
  class GetBucketMetadataTableConfiguration
449
485
  def self.build(context)
450
486
  Aws::S3::EndpointParameters.create(
@@ -1196,6 +1232,30 @@ module Aws::S3
1196
1232
  end
1197
1233
  end
1198
1234
 
1235
+ class UpdateBucketMetadataInventoryTableConfiguration
1236
+ def self.build(context)
1237
+ Aws::S3::EndpointParameters.create(
1238
+ context.config,
1239
+ bucket: context.params[:bucket],
1240
+ use_dual_stack: context[:use_dualstack_endpoint],
1241
+ accelerate: context[:use_accelerate_endpoint],
1242
+ use_s3_express_control_endpoint: true,
1243
+ )
1244
+ end
1245
+ end
1246
+
1247
+ class UpdateBucketMetadataJournalTableConfiguration
1248
+ def self.build(context)
1249
+ Aws::S3::EndpointParameters.create(
1250
+ context.config,
1251
+ bucket: context.params[:bucket],
1252
+ use_dual_stack: context[:use_dualstack_endpoint],
1253
+ accelerate: context[:use_accelerate_endpoint],
1254
+ use_s3_express_control_endpoint: true,
1255
+ )
1256
+ end
1257
+ end
1258
+
1199
1259
  class UploadPart
1200
1260
  def self.build(context)
1201
1261
  Aws::S3::EndpointParameters.create(
@@ -1242,6 +1302,8 @@ module Aws::S3
1242
1302
  CopyObject.build(context)
1243
1303
  when :create_bucket
1244
1304
  CreateBucket.build(context)
1305
+ when :create_bucket_metadata_configuration
1306
+ CreateBucketMetadataConfiguration.build(context)
1245
1307
  when :create_bucket_metadata_table_configuration
1246
1308
  CreateBucketMetadataTableConfiguration.build(context)
1247
1309
  when :create_multipart_upload
@@ -1262,6 +1324,8 @@ module Aws::S3
1262
1324
  DeleteBucketInventoryConfiguration.build(context)
1263
1325
  when :delete_bucket_lifecycle
1264
1326
  DeleteBucketLifecycle.build(context)
1327
+ when :delete_bucket_metadata_configuration
1328
+ DeleteBucketMetadataConfiguration.build(context)
1265
1329
  when :delete_bucket_metadata_table_configuration
1266
1330
  DeleteBucketMetadataTableConfiguration.build(context)
1267
1331
  when :delete_bucket_metrics_configuration
@@ -1306,6 +1370,8 @@ module Aws::S3
1306
1370
  GetBucketLocation.build(context)
1307
1371
  when :get_bucket_logging
1308
1372
  GetBucketLogging.build(context)
1373
+ when :get_bucket_metadata_configuration
1374
+ GetBucketMetadataConfiguration.build(context)
1309
1375
  when :get_bucket_metadata_table_configuration
1310
1376
  GetBucketMetadataTableConfiguration.build(context)
1311
1377
  when :get_bucket_metrics_configuration
@@ -1434,6 +1500,10 @@ module Aws::S3
1434
1500
  RestoreObject.build(context)
1435
1501
  when :select_object_content
1436
1502
  SelectObjectContent.build(context)
1503
+ when :update_bucket_metadata_inventory_table_configuration
1504
+ UpdateBucketMetadataInventoryTableConfiguration.build(context)
1505
+ when :update_bucket_metadata_journal_table_configuration
1506
+ UpdateBucketMetadataJournalTableConfiguration.build(context)
1437
1507
  when :upload_part
1438
1508
  UploadPart.build(context)
1439
1509
  when :upload_part_copy