aws-sdk-s3 1.199.1 → 1.202.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +19 -0
- data/VERSION +1 -1
- data/lib/aws-sdk-s3/bucket_versioning.rb +33 -0
- data/lib/aws-sdk-s3/client.rb +644 -155
- data/lib/aws-sdk-s3/client_api.rb +2 -0
- data/lib/aws-sdk-s3/customizations/object.rb +23 -19
- data/lib/aws-sdk-s3/customizations.rb +1 -0
- data/lib/aws-sdk-s3/default_executor.rb +103 -0
- data/lib/aws-sdk-s3/endpoint_parameters.rb +17 -17
- data/lib/aws-sdk-s3/file_downloader.rb +175 -112
- data/lib/aws-sdk-s3/file_uploader.rb +6 -8
- data/lib/aws-sdk-s3/multipart_file_uploader.rb +79 -63
- data/lib/aws-sdk-s3/multipart_stream_uploader.rb +41 -44
- data/lib/aws-sdk-s3/object.rb +52 -23
- data/lib/aws-sdk-s3/object_summary.rb +38 -9
- data/lib/aws-sdk-s3/object_version.rb +7 -9
- data/lib/aws-sdk-s3/plugins/endpoints.rb +1 -1
- data/lib/aws-sdk-s3/transfer_manager.rb +77 -25
- data/lib/aws-sdk-s3/types.rb +198 -142
- data/lib/aws-sdk-s3.rb +1 -1
- data/sig/client.rbs +2 -0
- data/sig/object.rbs +2 -0
- data/sig/object_summary.rbs +2 -0
- data/sig/types.rbs +2 -0
- metadata +4 -3
|
@@ -2,27 +2,74 @@
|
|
|
2
2
|
|
|
3
3
|
module Aws
|
|
4
4
|
module S3
|
|
5
|
-
# A high-level S3 transfer utility that provides enhanced upload and download
|
|
6
|
-
#
|
|
7
|
-
# handling of large files. The following features are supported:
|
|
5
|
+
# A high-level S3 transfer utility that provides enhanced upload and download capabilities with automatic
|
|
6
|
+
# multipart handling, progress tracking, and handling of large files. The following features are supported:
|
|
8
7
|
#
|
|
9
8
|
# * upload a file with multipart upload
|
|
10
9
|
# * upload a stream with multipart upload
|
|
11
10
|
# * download a S3 object with multipart download
|
|
12
11
|
# * track transfer progress by using progress listener
|
|
13
12
|
#
|
|
13
|
+
# ## Executor Management
|
|
14
|
+
# TransferManager uses executors to handle concurrent operations during multipart transfers. You can control
|
|
15
|
+
# concurrency behavior by providing a custom executor or relying on the default executor management.
|
|
16
|
+
#
|
|
17
|
+
# ### Default Behavior
|
|
18
|
+
# When no `:executor` is provided, TransferManager creates a new DefaultExecutor for each individual
|
|
19
|
+
# operation (`download_file`, `upload_file`, etc.) and automatically shuts it down when that operation completes.
|
|
20
|
+
# Each operation gets its own isolated thread pool with the specified `:thread_count` (default 10 threads).
|
|
21
|
+
#
|
|
22
|
+
# ### Custom Executor
|
|
23
|
+
# You can provide your own executor (e.g., `Concurrent::ThreadPoolExecutor`) for fine-grained control over thread
|
|
24
|
+
# pools and resource management. When using a custom executor, you are responsible for shutting it down
|
|
25
|
+
# when finished. The executor may be reused across multiple TransferManager operations.
|
|
26
|
+
#
|
|
27
|
+
# Custom executors must implement the same interface as DefaultExecutor.
|
|
28
|
+
#
|
|
29
|
+
# **Required methods:**
|
|
30
|
+
#
|
|
31
|
+
# * `post(*args, &block)` - Execute a task with given arguments and block
|
|
32
|
+
# * `kill` - Immediately terminate all running tasks
|
|
33
|
+
#
|
|
34
|
+
# **Optional methods:**
|
|
35
|
+
#
|
|
36
|
+
# * `shutdown(timeout = nil)` - Gracefully shutdown the executor with optional timeout
|
|
37
|
+
#
|
|
38
|
+
# @example Using default executor (automatic creation and shutdown)
|
|
39
|
+
# tm = TransferManager.new # No executor provided
|
|
40
|
+
# # DefaultExecutor created, used, and shutdown automatically
|
|
41
|
+
# tm.download_file('/path/to/file', bucket: 'bucket', key: 'key')
|
|
42
|
+
#
|
|
43
|
+
# @example Using custom executor (manual shutdown required)
|
|
44
|
+
# require 'concurrent-ruby'
|
|
45
|
+
#
|
|
46
|
+
# executor = Concurrent::ThreadPoolExecutor.new(max_threads: 5)
|
|
47
|
+
# tm = TransferManager.new(executor: executor)
|
|
48
|
+
# tm.download_file('/path/to/file1', bucket: 'bucket', key: 'key1')
|
|
49
|
+
# executor.shutdown # You must shutdown custom executors
|
|
50
|
+
#
|
|
14
51
|
class TransferManager
|
|
52
|
+
|
|
15
53
|
# @param [Hash] options
|
|
16
54
|
# @option options [S3::Client] :client (S3::Client.new)
|
|
17
55
|
# The S3 client to use for {TransferManager} operations. If not provided, a new default client
|
|
18
56
|
# will be created automatically.
|
|
57
|
+
# @option options [Object] :executor
|
|
58
|
+
# The executor to use for multipart operations. Must implement the same interface as {DefaultExecutor}.
|
|
59
|
+
# If not provided, a new {DefaultExecutor} will be created automatically for each operation and
|
|
60
|
+
# shutdown after completion. When provided a custom executor, it will be reused across operations, and
|
|
61
|
+
# you are responsible for shutting it down when finished.
|
|
19
62
|
def initialize(options = {})
|
|
20
|
-
@client = options
|
|
63
|
+
@client = options[:client] || Client.new
|
|
64
|
+
@executor = options[:executor]
|
|
21
65
|
end
|
|
22
66
|
|
|
23
67
|
# @return [S3::Client]
|
|
24
68
|
attr_reader :client
|
|
25
69
|
|
|
70
|
+
# @return [Object]
|
|
71
|
+
attr_reader :executor
|
|
72
|
+
|
|
26
73
|
# Downloads a file in S3 to a path on disk.
|
|
27
74
|
#
|
|
28
75
|
# # small files (< 5MB) are downloaded in a single API call
|
|
@@ -74,10 +121,7 @@ module Aws
|
|
|
74
121
|
# @option options [Integer] :chunk_size required in `"get_range"` mode.
|
|
75
122
|
#
|
|
76
123
|
# @option options [Integer] :thread_count (10) Customize threads used in the multipart download.
|
|
77
|
-
#
|
|
78
|
-
# @option options [String] :version_id The object version id used to retrieve the object.
|
|
79
|
-
#
|
|
80
|
-
# @see https://docs.aws.amazon.com/AmazonS3/latest/dev/ObjectVersioning.html ObjectVersioning
|
|
124
|
+
# Only used when no custom executor is provided (creates {DefaultExecutor} with given thread count).
|
|
81
125
|
#
|
|
82
126
|
# @option options [String] :checksum_mode ("ENABLED")
|
|
83
127
|
# When `"ENABLED"` and the object has a stored checksum, it will be used to validate the download and will
|
|
@@ -102,8 +146,11 @@ module Aws
|
|
|
102
146
|
# @see Client#get_object
|
|
103
147
|
# @see Client#head_object
|
|
104
148
|
def download_file(destination, bucket:, key:, **options)
|
|
105
|
-
|
|
106
|
-
|
|
149
|
+
download_opts = options.merge(bucket: bucket, key: key)
|
|
150
|
+
executor = @executor || DefaultExecutor.new(max_threads: download_opts.delete(:thread_count))
|
|
151
|
+
downloader = FileDownloader.new(client: @client, executor: executor)
|
|
152
|
+
downloader.download(destination, download_opts)
|
|
153
|
+
executor.shutdown unless @executor
|
|
107
154
|
true
|
|
108
155
|
end
|
|
109
156
|
|
|
@@ -139,7 +186,7 @@ module Aws
|
|
|
139
186
|
# A file on the local file system that will be uploaded. This can either be a `String` or `Pathname` to the
|
|
140
187
|
# file, an open `File` object, or an open `Tempfile` object. If you pass an open `File` or `Tempfile` object,
|
|
141
188
|
# then you are responsible for closing it after the upload completes. When using an open Tempfile, rewind it
|
|
142
|
-
# before
|
|
189
|
+
# before uploading or else the object will be empty.
|
|
143
190
|
#
|
|
144
191
|
# @param [String] bucket
|
|
145
192
|
# The name of the S3 bucket to upload to.
|
|
@@ -156,15 +203,14 @@ module Aws
|
|
|
156
203
|
# Files larger han or equal to `:multipart_threshold` are uploaded using the S3 multipart upload APIs.
|
|
157
204
|
# Default threshold is `100MB`.
|
|
158
205
|
#
|
|
159
|
-
# @option options [Integer] :thread_count (10)
|
|
160
|
-
#
|
|
161
|
-
# `:multipart_threshold`.
|
|
206
|
+
# @option options [Integer] :thread_count (10) Customize threads used in the multipart upload.
|
|
207
|
+
# Only used when no custom executor is provided (creates {DefaultExecutor} with the given thread count).
|
|
162
208
|
#
|
|
163
209
|
# @option options [Proc] :progress_callback (nil)
|
|
164
210
|
# A Proc that will be called when each chunk of the upload is sent.
|
|
165
211
|
# It will be invoked with `[bytes_read]` and `[total_sizes]`.
|
|
166
212
|
#
|
|
167
|
-
# @raise [MultipartUploadError] If
|
|
213
|
+
# @raise [MultipartUploadError] If a file is being uploaded in parts, and the upload can not be completed,
|
|
168
214
|
# then the upload is aborted and this error is raised. The raised error has a `#errors` method that
|
|
169
215
|
# returns the failures that caused the upload to be aborted.
|
|
170
216
|
#
|
|
@@ -175,13 +221,16 @@ module Aws
|
|
|
175
221
|
# @see Client#complete_multipart_upload
|
|
176
222
|
# @see Client#upload_part
|
|
177
223
|
def upload_file(source, bucket:, key:, **options)
|
|
178
|
-
|
|
224
|
+
upload_opts = options.merge(bucket: bucket, key: key)
|
|
225
|
+
executor = @executor || DefaultExecutor.new(max_threads: upload_opts.delete(:thread_count))
|
|
179
226
|
uploader = FileUploader.new(
|
|
180
|
-
multipart_threshold:
|
|
181
|
-
client: @client
|
|
227
|
+
multipart_threshold: upload_opts.delete(:multipart_threshold),
|
|
228
|
+
client: @client,
|
|
229
|
+
executor: executor
|
|
182
230
|
)
|
|
183
|
-
response = uploader.upload(source,
|
|
231
|
+
response = uploader.upload(source, upload_opts)
|
|
184
232
|
yield response if block_given?
|
|
233
|
+
executor.shutdown unless @executor
|
|
185
234
|
true
|
|
186
235
|
end
|
|
187
236
|
|
|
@@ -217,7 +266,8 @@ module Aws
|
|
|
217
266
|
# {Client#upload_part} can be provided.
|
|
218
267
|
#
|
|
219
268
|
# @option options [Integer] :thread_count (10)
|
|
220
|
-
# The number of parallel multipart uploads.
|
|
269
|
+
# The number of parallel multipart uploads. Only used when no custom executor is provided (creates
|
|
270
|
+
# {DefaultExecutor} with the given thread count). An additional thread is used internally for task coordination.
|
|
221
271
|
#
|
|
222
272
|
# @option options [Boolean] :tempfile (false)
|
|
223
273
|
# Normally read data is stored in memory when building the parts in order to complete the underlying
|
|
@@ -237,14 +287,16 @@ module Aws
|
|
|
237
287
|
# @see Client#complete_multipart_upload
|
|
238
288
|
# @see Client#upload_part
|
|
239
289
|
def upload_stream(bucket:, key:, **options, &block)
|
|
240
|
-
|
|
290
|
+
upload_opts = options.merge(bucket: bucket, key: key)
|
|
291
|
+
executor = @executor || DefaultExecutor.new(max_threads: upload_opts.delete(:thread_count))
|
|
241
292
|
uploader = MultipartStreamUploader.new(
|
|
242
293
|
client: @client,
|
|
243
|
-
|
|
244
|
-
tempfile:
|
|
245
|
-
part_size:
|
|
294
|
+
executor: executor,
|
|
295
|
+
tempfile: upload_opts.delete(:tempfile),
|
|
296
|
+
part_size: upload_opts.delete(:part_size)
|
|
246
297
|
)
|
|
247
|
-
uploader.upload(
|
|
298
|
+
uploader.upload(upload_opts, &block)
|
|
299
|
+
executor.shutdown unless @executor
|
|
248
300
|
true
|
|
249
301
|
end
|
|
250
302
|
end
|