azure-storage-common 1.1.0 → 2.0.1

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.
Files changed (60) hide show
  1. checksums.yaml +5 -5
  2. data/lib/azure/core.rb +47 -0
  3. data/lib/azure/core/auth/authorizer.rb +36 -0
  4. data/lib/azure/core/auth/shared_key.rb +125 -0
  5. data/lib/azure/core/auth/shared_key_lite.rb +48 -0
  6. data/lib/azure/core/auth/signer.rb +51 -0
  7. data/lib/azure/core/default.rb +23 -0
  8. data/lib/azure/core/error.rb +21 -0
  9. data/lib/azure/core/filtered_service.rb +45 -0
  10. data/lib/azure/core/http/debug_filter.rb +36 -0
  11. data/lib/azure/core/http/http_error.rb +135 -0
  12. data/lib/azure/core/http/http_filter.rb +53 -0
  13. data/lib/azure/core/http/http_request.rb +194 -0
  14. data/lib/azure/core/http/http_response.rb +102 -0
  15. data/lib/azure/core/http/retry_policy.rb +84 -0
  16. data/lib/azure/core/http/signer_filter.rb +33 -0
  17. data/lib/azure/core/service.rb +46 -0
  18. data/lib/azure/core/signed_service.rb +45 -0
  19. data/lib/azure/core/utility.rb +244 -0
  20. data/lib/azure/core/version.rb +33 -0
  21. data/lib/azure/http_response_helper.rb +38 -0
  22. data/lib/azure/storage/common.rb +26 -26
  23. data/lib/azure/storage/common/autoload.rb +62 -61
  24. data/lib/azure/storage/common/client.rb +162 -162
  25. data/lib/azure/storage/common/client_options.rb +363 -363
  26. data/lib/azure/storage/common/client_options_error.rb +41 -41
  27. data/lib/azure/storage/common/configurable.rb +212 -212
  28. data/lib/azure/storage/common/core.rb +35 -35
  29. data/lib/azure/storage/common/core/auth/anonymous_signer.rb +43 -43
  30. data/lib/azure/storage/common/core/auth/shared_access_signature.rb +30 -30
  31. data/lib/azure/storage/common/core/auth/shared_access_signature_generator.rb +399 -352
  32. data/lib/azure/storage/common/core/auth/shared_access_signature_signer.rb +57 -57
  33. data/lib/azure/storage/common/core/auth/shared_key.rb +60 -60
  34. data/lib/azure/storage/common/core/auth/token_signer.rb +43 -43
  35. data/lib/azure/storage/common/core/autoload.rb +53 -53
  36. data/lib/azure/storage/common/core/error.rb +43 -43
  37. data/lib/azure/storage/common/core/filter/exponential_retry_filter.rb +64 -64
  38. data/lib/azure/storage/common/core/filter/linear_retry_filter.rb +55 -55
  39. data/lib/azure/storage/common/core/filter/retry_filter.rb +300 -300
  40. data/lib/azure/storage/common/core/http_client.rb +79 -69
  41. data/lib/azure/storage/common/core/sr.rb +85 -85
  42. data/lib/azure/storage/common/core/token_credential.rb +64 -64
  43. data/lib/azure/storage/common/core/utility.rb +255 -255
  44. data/lib/azure/storage/common/default.rb +868 -868
  45. data/lib/azure/storage/common/service/access_policy.rb +37 -37
  46. data/lib/azure/storage/common/service/cors.rb +38 -38
  47. data/lib/azure/storage/common/service/cors_rule.rb +48 -48
  48. data/lib/azure/storage/common/service/enumeration_results.rb +32 -32
  49. data/lib/azure/storage/common/service/geo_replication.rb +40 -40
  50. data/lib/azure/storage/common/service/logging.rb +47 -47
  51. data/lib/azure/storage/common/service/metrics.rb +45 -45
  52. data/lib/azure/storage/common/service/retention_policy.rb +37 -37
  53. data/lib/azure/storage/common/service/serialization.rb +335 -335
  54. data/lib/azure/storage/common/service/signed_identifier.rb +40 -40
  55. data/lib/azure/storage/common/service/storage_service.rb +322 -322
  56. data/lib/azure/storage/common/service/storage_service_properties.rb +48 -48
  57. data/lib/azure/storage/common/service/storage_service_stats.rb +39 -39
  58. data/lib/azure/storage/common/service/user_delegation_key.rb +50 -0
  59. data/lib/azure/storage/common/version.rb +49 -49
  60. metadata +60 -18
@@ -1,64 +1,64 @@
1
- # frozen_string_literal: true
2
-
3
- #-------------------------------------------------------------------------
4
- # # Copyright (c) Microsoft and contributors. All rights reserved.
5
- #
6
- # The MIT License(MIT)
7
-
8
- # Permission is hereby granted, free of charge, to any person obtaining a copy
9
- # of this software and associated documentation files(the "Software"), to deal
10
- # in the Software without restriction, including without limitation the rights
11
- # to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
12
- # copies of the Software, and to permit persons to whom the Software is
13
- # furnished to do so, subject to the following conditions :
14
-
15
- # The above copyright notice and this permission notice shall be included in
16
- # all copies or substantial portions of the Software.
17
-
18
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
21
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
- # THE SOFTWARE.
25
- #--------------------------------------------------------------------------
26
- require "azure/core"
27
- require "azure/core/http/retry_policy"
28
-
29
- module Azure::Storage::Common::Core::Filter
30
- class ExponentialRetryPolicyFilter < RetryPolicyFilter
31
- def initialize(retry_count = nil, min_retry_interval = nil, max_retry_interval = nil)
32
- @retry_count = retry_count || ExponentialRetryPolicyFilter::DEFAULT_RETRY_COUNT
33
- @min_retry_interval = min_retry_interval || ExponentialRetryPolicyFilter::DEFAULT_MIN_RETRY_INTERVAL
34
- @max_retry_interval = max_retry_interval || ExponentialRetryPolicyFilter::DEFAULT_MAX_RETRY_INTERVAL
35
-
36
- super @retry_count, @min_retry_interval
37
- end
38
-
39
- attr_reader :min_retry_interval,
40
- :max_retry_interval
41
-
42
- DEFAULT_RETRY_COUNT = 3
43
- DEFAULT_MIN_RETRY_INTERVAL = 10
44
- DEFAULT_MAX_RETRY_INTERVAL = 90
45
-
46
- # Overrides the base class implementation of call to determine
47
- # how the HTTP request should continue retrying
48
- #
49
- # retry_data - Hash. Stores stateful retry data
50
- #
51
- # The retry_data is a Hash which can be used to store
52
- # stateful data about the request execution context (such as an
53
- # incrementing counter, timestamp, etc). The retry_data object
54
- # will be the same instance throughout the lifetime of the request
55
- def apply_retry_policy(retry_data)
56
- # Adjust retry count
57
- retry_data[:count] = retry_data[:count] === nil ? 1 : retry_data[:count] + 1
58
-
59
- # Adjust retry interval
60
- increment_delta = (@max_retry_interval - @min_retry_interval).fdiv(2**(@retry_count - 1)) * (2**(retry_data[:count] - 1));
61
- retry_data[:interval] = retry_data[:interval] === nil ? @min_retry_interval : [@min_retry_interval + increment_delta, @max_retry_interval].min;
62
- end
63
- end
64
- end
1
+ # frozen_string_literal: true
2
+
3
+ #-------------------------------------------------------------------------
4
+ # # Copyright (c) Microsoft and contributors. All rights reserved.
5
+ #
6
+ # The MIT License(MIT)
7
+
8
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ # of this software and associated documentation files(the "Software"), to deal
10
+ # in the Software without restriction, including without limitation the rights
11
+ # to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
12
+ # copies of the Software, and to permit persons to whom the Software is
13
+ # furnished to do so, subject to the following conditions :
14
+
15
+ # The above copyright notice and this permission notice shall be included in
16
+ # all copies or substantial portions of the Software.
17
+
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
21
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ # THE SOFTWARE.
25
+ #--------------------------------------------------------------------------
26
+ require "azure/core"
27
+ require "azure/core/http/retry_policy"
28
+
29
+ module Azure::Storage::Common::Core::Filter
30
+ class ExponentialRetryPolicyFilter < RetryPolicyFilter
31
+ def initialize(retry_count = nil, min_retry_interval = nil, max_retry_interval = nil)
32
+ @retry_count = retry_count || ExponentialRetryPolicyFilter::DEFAULT_RETRY_COUNT
33
+ @min_retry_interval = min_retry_interval || ExponentialRetryPolicyFilter::DEFAULT_MIN_RETRY_INTERVAL
34
+ @max_retry_interval = max_retry_interval || ExponentialRetryPolicyFilter::DEFAULT_MAX_RETRY_INTERVAL
35
+
36
+ super @retry_count, @min_retry_interval
37
+ end
38
+
39
+ attr_reader :min_retry_interval,
40
+ :max_retry_interval
41
+
42
+ DEFAULT_RETRY_COUNT = 3
43
+ DEFAULT_MIN_RETRY_INTERVAL = 10
44
+ DEFAULT_MAX_RETRY_INTERVAL = 90
45
+
46
+ # Overrides the base class implementation of call to determine
47
+ # how the HTTP request should continue retrying
48
+ #
49
+ # retry_data - Hash. Stores stateful retry data
50
+ #
51
+ # The retry_data is a Hash which can be used to store
52
+ # stateful data about the request execution context (such as an
53
+ # incrementing counter, timestamp, etc). The retry_data object
54
+ # will be the same instance throughout the lifetime of the request
55
+ def apply_retry_policy(retry_data)
56
+ # Adjust retry count
57
+ retry_data[:count] = retry_data[:count] === nil ? 1 : retry_data[:count] + 1
58
+
59
+ # Adjust retry interval
60
+ increment_delta = (@max_retry_interval - @min_retry_interval).fdiv(2**(@retry_count - 1)) * (2**(retry_data[:count] - 1));
61
+ retry_data[:interval] = retry_data[:interval] === nil ? @min_retry_interval : [@min_retry_interval + increment_delta, @max_retry_interval].min;
62
+ end
63
+ end
64
+ end
@@ -1,55 +1,55 @@
1
- # frozen_string_literal: true
2
-
3
- #-------------------------------------------------------------------------
4
- # # Copyright (c) Microsoft and contributors. All rights reserved.
5
- #
6
- # The MIT License(MIT)
7
-
8
- # Permission is hereby granted, free of charge, to any person obtaining a copy
9
- # of this software and associated documentation files(the "Software"), to deal
10
- # in the Software without restriction, including without limitation the rights
11
- # to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
12
- # copies of the Software, and to permit persons to whom the Software is
13
- # furnished to do so, subject to the following conditions :
14
-
15
- # The above copyright notice and this permission notice shall be included in
16
- # all copies or substantial portions of the Software.
17
-
18
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
21
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
- # THE SOFTWARE.
25
- #--------------------------------------------------------------------------
26
- require "azure/core"
27
- require "azure/core/http/retry_policy"
28
-
29
- module Azure::Storage::Common::Core::Filter
30
- class LinearRetryPolicyFilter < RetryPolicyFilter
31
- def initialize(retry_count = nil, retry_interval = nil)
32
- @retry_count = retry_count || LinearRetryPolicyFilter::DEFAULT_RETRY_COUNT
33
- @retry_interval = retry_interval || LinearRetryPolicyFilter::DEFAULT_RETRY_INTERVAL
34
-
35
- super @retry_count, @retry_interval
36
- end
37
-
38
- DEFAULT_RETRY_COUNT = 3
39
- DEFAULT_RETRY_INTERVAL = 30
40
-
41
- # Overrides the base class implementation of call to determine
42
- # how the HTTP request should continue retrying
43
- #
44
- # retry_data - Hash. Stores stateful retry data
45
- #
46
- # The retry_data is a Hash which can be used to store
47
- # stateful data about the request execution context (such as an
48
- # incrementing counter, timestamp, etc). The retry_data object
49
- # will be the same instance throughout the lifetime of the request
50
- def apply_retry_policy(retry_data)
51
- retry_data[:count] = retry_data[:count] == nil ? 1 : retry_data[:count] + 1
52
- retry_data[:interval] = @retry_interval
53
- end
54
- end
55
- end
1
+ # frozen_string_literal: true
2
+
3
+ #-------------------------------------------------------------------------
4
+ # # Copyright (c) Microsoft and contributors. All rights reserved.
5
+ #
6
+ # The MIT License(MIT)
7
+
8
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ # of this software and associated documentation files(the "Software"), to deal
10
+ # in the Software without restriction, including without limitation the rights
11
+ # to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
12
+ # copies of the Software, and to permit persons to whom the Software is
13
+ # furnished to do so, subject to the following conditions :
14
+
15
+ # The above copyright notice and this permission notice shall be included in
16
+ # all copies or substantial portions of the Software.
17
+
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
21
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ # THE SOFTWARE.
25
+ #--------------------------------------------------------------------------
26
+ require "azure/core"
27
+ require "azure/core/http/retry_policy"
28
+
29
+ module Azure::Storage::Common::Core::Filter
30
+ class LinearRetryPolicyFilter < RetryPolicyFilter
31
+ def initialize(retry_count = nil, retry_interval = nil)
32
+ @retry_count = retry_count || LinearRetryPolicyFilter::DEFAULT_RETRY_COUNT
33
+ @retry_interval = retry_interval || LinearRetryPolicyFilter::DEFAULT_RETRY_INTERVAL
34
+
35
+ super @retry_count, @retry_interval
36
+ end
37
+
38
+ DEFAULT_RETRY_COUNT = 3
39
+ DEFAULT_RETRY_INTERVAL = 30
40
+
41
+ # Overrides the base class implementation of call to determine
42
+ # how the HTTP request should continue retrying
43
+ #
44
+ # retry_data - Hash. Stores stateful retry data
45
+ #
46
+ # The retry_data is a Hash which can be used to store
47
+ # stateful data about the request execution context (such as an
48
+ # incrementing counter, timestamp, etc). The retry_data object
49
+ # will be the same instance throughout the lifetime of the request
50
+ def apply_retry_policy(retry_data)
51
+ retry_data[:count] = retry_data[:count] == nil ? 1 : retry_data[:count] + 1
52
+ retry_data[:interval] = @retry_interval
53
+ end
54
+ end
55
+ end
@@ -1,300 +1,300 @@
1
- # frozen_string_literal: true
2
-
3
- #-------------------------------------------------------------------------
4
- # # Copyright (c) Microsoft and contributors. All rights reserved.
5
- #
6
- # The MIT License(MIT)
7
-
8
- # Permission is hereby granted, free of charge, to any person obtaining a copy
9
- # of this software and associated documentation files(the "Software"), to deal
10
- # in the Software without restriction, including without limitation the rights
11
- # to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
12
- # copies of the Software, and to permit persons to whom the Software is
13
- # furnished to do so, subject to the following conditions :
14
-
15
- # The above copyright notice and this permission notice shall be included in
16
- # all copies or substantial portions of the Software.
17
-
18
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
- # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
- # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
21
- # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
- # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
- # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
- # THE SOFTWARE.
25
- #--------------------------------------------------------------------------
26
- require "azure/core"
27
- require "azure/core/http/retry_policy"
28
-
29
- module Azure::Storage::Common::Core::Filter
30
- class RetryPolicyFilter < Azure::Core::Http::RetryPolicy
31
- def initialize(retry_count = nil, retry_interval = nil)
32
- @retry_count = retry_count
33
- @retry_interval = retry_interval
34
- @request_options = {}
35
-
36
- super &:should_retry?
37
- end
38
-
39
- attr_reader :retry_count,
40
- :retry_interval
41
-
42
- # Overrides the base class implementation of call to determine
43
- # whether to retry the operation
44
- #
45
- # response - HttpResponse. The response from the active request
46
- # retry_data - Hash. Stores stateful retry data
47
- def should_retry?(response, retry_data)
48
- # Fill necessary information
49
- init_retry_data retry_data
50
-
51
- # Applies the logic when there is subclass overrides it
52
- apply_retry_policy retry_data
53
-
54
- # Checks the result and count limit
55
- if retry_data[:retryable].nil?
56
- retry_data[:retryable] = true
57
- else
58
- retry_data[:retryable] &&= retry_data[:count] <= @retry_count
59
- end
60
- return false unless retry_data[:retryable]
61
-
62
- # Checks whether there is a local error
63
- # Cannot retry immediately when it returns true, as it need check other errors
64
- should_retry_on_local_error? retry_data
65
- return false unless should_retry_on_error? response, retry_data
66
-
67
- # Determined that it needs to retry.
68
- adjust_retry_request retry_data
69
-
70
- wait_for_retry
71
-
72
- retry_data[:retryable]
73
- end
74
-
75
- # Apply the retry policy to determine how the HTTP request should continue retrying
76
- #
77
- # retry_data - Hash. Stores stateful retry data
78
- #
79
- # The retry_data is a Hash which can be used to store
80
- # stateful data about the request execution context (such as an
81
- # incrementing counter, timestamp, etc). The retry_data object
82
- # will be the same instance throughout the lifetime of the request
83
- #
84
- # Alternatively, a subclass could override this method.
85
- def apply_retry_policy(retry_data)
86
- end
87
-
88
- # Determines if the HTTP request should continue retrying
89
- #
90
- # retry_data - Hash. Stores stateful retry data
91
- #
92
- # The retry_data is a Hash which can be used to store
93
- # stateful data about the request execution context (such as an
94
- # incrementing counter, timestamp, etc). The retry_data object
95
- # will be the same instance throughout the lifetime of the request.
96
- def should_retry_on_local_error?(retry_data)
97
- unless retry_data[:error]
98
- retry_data[:retryable] = true;
99
- return true
100
- end
101
-
102
- error_message = retry_data[:error].inspect
103
-
104
- if error_message.include?("SocketError: Hostname not known")
105
- # Retry on local DNS resolving
106
- # When uses resolv-replace.rb to replace the libc resolver
107
- # Reference:
108
- # https://makandracards.com/ninjaconcept/30815-fixing-socketerror-getaddrinfo-name-or-service-not-known-with-ruby-s-resolv-replace-rb
109
- # http://www.subelsky.com/2014/05/fixing-socketerror-getaddrinfo-name-or.html
110
- retry_data[:retryable] = true;
111
- elsif error_message.include?("getaddrinfo: Name or service not known")
112
- # When uses the default resolver
113
- retry_data[:retryable] = true;
114
- elsif error_message.downcase.include?("timeout")
115
- retry_data[:retryable] = true;
116
- elsif error_message.include?("Errno::ECONNRESET")
117
- retry_data[:retryable] = true;
118
- elsif error_message.include?("Errno::EACCES")
119
- retry_data[:retryable] = false;
120
- elsif error_message.include?("NOSUPPORT")
121
- retry_data[:retryable] = false;
122
- end
123
-
124
- retry_data[:retryable]
125
- end
126
-
127
- # Determines if the HTTP request should continue retrying
128
- #
129
- # response - Azure::Core::Http::HttpResponse. The response from the active request
130
- # retry_data - Hash. Stores stateful retry data
131
- #
132
- # The retry_data is a Hash which can be used to store
133
- # stateful data about the request execution context (such as an
134
- # incrementing counter, timestamp, etc). The retry_data object
135
- # will be the same instance throughout the lifetime of the request.
136
- def should_retry_on_error?(response, retry_data)
137
- response = response || retry_data[:error].http_response if retry_data[:error] && retry_data[:error].respond_to?("http_response")
138
- unless response
139
- retry_data[:retryable] = false unless retry_data[:error]
140
- return retry_data[:retryable]
141
- end
142
-
143
- check_location(response, retry_data)
144
-
145
- check_status_code(retry_data)
146
-
147
- retry_data[:retryable]
148
- end
149
-
150
- # Adjust the retry parameter and wait for retry
151
- def wait_for_retry
152
- sleep @retry_interval if @retry_interval > 0
153
- end
154
-
155
- # Adjust the retry request
156
- #
157
- # retry_data - Hash. Stores stateful retry data
158
- def adjust_retry_request(retry_data)
159
- # Adjust the location first
160
- next_location = @request_options[:target_location].nil? ? get_next_location(retry_data) : @request_options[:target_location]
161
- retry_data[:current_location] = next_location
162
-
163
- retry_data[:uri] =
164
- if next_location == Azure::Storage::Common::StorageLocation::PRIMARY
165
- @request_options[:primary_uri]
166
- else
167
- @request_options[:secondary_uri]
168
- end
169
-
170
- # Now is the time to calculate the exact retry interval. ShouldRetry call above already
171
- # returned back how long two requests to the same location should be apart from each other.
172
- # However, for the reasons explained above, the time spent between the last attempt to
173
- # the target location and current time must be subtracted from the total retry interval
174
- # that ShouldRetry returned.
175
- lastAttemptTime =
176
- if retry_data[:current_location] == Azure::Storage::Common::StorageLocation::PRIMARY
177
- retry_data[:last_primary_attempt]
178
- else
179
- retry_data[:last_secondary_attempt]
180
- end
181
-
182
- @retry_interval =
183
- if lastAttemptTime.nil?
184
- 0
185
- else
186
- since_last_attempt = Time.now - lastAttemptTime
187
- remainder = retry_data[:interval] - since_last_attempt
188
- remainder > 0 ? remainder : 0
189
- end
190
- end
191
-
192
- # Initialize the retry data
193
- #
194
- # retry_data - Hash. Stores stateful retry data
195
- def init_retry_data(retry_data)
196
- @request_options = retry_data[:request_options] unless retry_data[:request_options].nil?
197
-
198
- if retry_data[:current_location].nil?
199
- retry_data[:current_location] = Azure::Storage::Common::Service::StorageService.get_location(@request_options[:location_mode], @request_options[:request_location_mode])
200
- end
201
-
202
- if retry_data[:current_location] == Azure::Storage::Common::StorageLocation::PRIMARY
203
- retry_data[:last_primary_attempt] = Time.now
204
- else
205
- retry_data[:last_secondary_attempt] = Time.now
206
- end
207
- end
208
-
209
- # Check the location
210
- #
211
- # retry_data - Hash. Stores stateful retry data
212
- def check_location(response, retry_data)
213
- # If a request sent to the secondary location fails with 404 (Not Found), it is possible
214
- # that the resource replication is not finished yet. So, in case of 404 only in the secondary
215
- # location, the failure should still be retryable.
216
- retry_data[:secondary_not_found] =
217
- ((retry_data[:current_location] === Azure::Storage::Common::StorageLocation::SECONDARY) &&
218
- response.status_code === 404);
219
-
220
- if retry_data[:secondary_not_found]
221
- retry_data[:status_code] = 500
222
- else
223
- if (response.status_code)
224
- retry_data[:status_code] = response.status_code
225
- else
226
- retry_data[:status_code] = nil
227
- end
228
- end
229
- end
230
-
231
- # Check the status code
232
- #
233
- # retry_data - Hash. Stores stateful retry data
234
- def check_status_code(retry_data)
235
- if (retry_data[:status_code] < 400)
236
- retry_data[:retryable] = false;
237
- # Non-timeout Cases
238
- elsif (retry_data[:status_code] != 408)
239
- # Always no retry on "not implemented" and "version not supported"
240
- if (retry_data[:status_code] == 501 || retry_data[:status_code] == 505)
241
- retry_data[:retryable] = false;
242
- end
243
-
244
- # When absorb_conditional_errors_on_retry is set (for append blob)
245
- if (@request_options[:absorb_conditional_errors_on_retry])
246
- if (retry_data[:status_code] == 412)
247
- # When appending block with precondition failure and their was a server error before, we ignore the error.
248
- if (retry_data[:last_server_error])
249
- retry_data[:error] = nil;
250
- retry_data[:retryable] = true;
251
- else
252
- retry_data[:retryable] = false;
253
- end
254
- elsif (retry_data[:retryable] && retry_data[:status_code] >= 500 && retry_data[:status_code] < 600)
255
- # Retry on the server error
256
- retry_data[:retryable] = true;
257
- retry_data[:last_server_error] = true;
258
- end
259
- elsif (retry_data[:status_code] < 500)
260
- # No retry on the client error
261
- retry_data[:retryable] = false;
262
- end
263
- end
264
- end
265
-
266
- # Get retry request destination
267
- #
268
- # retry_data - Hash. Stores stateful retry data
269
- def get_next_location(retry_data)
270
- # In case of 404 when trying the secondary location, instead of retrying on the
271
- # secondary, further requests should be sent only to the primary location, as it most
272
- # probably has a higher chance of succeeding there.
273
- if retry_data[:secondary_not_found] && @request_options[:location_mode] != Azure::Storage::Common::LocationMode::SECONDARY_ONLY
274
- @request_options[:location_mode] = Azure::Storage::Common::LocationMode::PRIMARY_ONLY;
275
- return Azure::Storage::Common::StorageLocation::PRIMARY
276
- end
277
-
278
- case @request_options[:location_mode]
279
- when Azure::Storage::Common::LocationMode::PRIMARY_ONLY
280
- Azure::Storage::Common::StorageLocation::PRIMARY
281
- when Azure::Storage::Common::LocationMode::SECONDARY_ONLY
282
- Azure::Storage::Common::StorageLocation::SECONDARY
283
- else
284
- # request_location_mode cannot be SECONDARY_ONLY because it will be blocked at the first time
285
- if @request_options[:request_location_mode] == Azure::Storage::Common::RequestLocationMode::PRIMARY_ONLY
286
- Azure::Storage::Common::StorageLocation::PRIMARY
287
- elsif @request_options[:request_location_mode] == Azure::Storage::Common::RequestLocationMode::SECONDARY_ONLY
288
- Azure::Storage::Common::StorageLocation::SECONDARY
289
- else
290
- if retry_data[:current_location] === Azure::Storage::Common::StorageLocation::PRIMARY
291
- Azure::Storage::Common::StorageLocation::SECONDARY
292
- else
293
- Azure::Storage::Common::StorageLocation::PRIMARY
294
- end
295
- end
296
- end
297
- end
298
-
299
- end
300
- end
1
+ # frozen_string_literal: true
2
+
3
+ #-------------------------------------------------------------------------
4
+ # # Copyright (c) Microsoft and contributors. All rights reserved.
5
+ #
6
+ # The MIT License(MIT)
7
+
8
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ # of this software and associated documentation files(the "Software"), to deal
10
+ # in the Software without restriction, including without limitation the rights
11
+ # to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
12
+ # copies of the Software, and to permit persons to whom the Software is
13
+ # furnished to do so, subject to the following conditions :
14
+
15
+ # The above copyright notice and this permission notice shall be included in
16
+ # all copies or substantial portions of the Software.
17
+
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
21
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24
+ # THE SOFTWARE.
25
+ #--------------------------------------------------------------------------
26
+ require "azure/core"
27
+ require "azure/core/http/retry_policy"
28
+
29
+ module Azure::Storage::Common::Core::Filter
30
+ class RetryPolicyFilter < Azure::Core::Http::RetryPolicy
31
+ def initialize(retry_count = nil, retry_interval = nil)
32
+ @retry_count = retry_count
33
+ @retry_interval = retry_interval
34
+ @request_options = {}
35
+
36
+ super &:should_retry?
37
+ end
38
+
39
+ attr_reader :retry_count,
40
+ :retry_interval
41
+
42
+ # Overrides the base class implementation of call to determine
43
+ # whether to retry the operation
44
+ #
45
+ # response - HttpResponse. The response from the active request
46
+ # retry_data - Hash. Stores stateful retry data
47
+ def should_retry?(response, retry_data)
48
+ # Fill necessary information
49
+ init_retry_data retry_data
50
+
51
+ # Applies the logic when there is subclass overrides it
52
+ apply_retry_policy retry_data
53
+
54
+ # Checks the result and count limit
55
+ if retry_data[:retryable].nil?
56
+ retry_data[:retryable] = true
57
+ else
58
+ retry_data[:retryable] &&= retry_data[:count] <= @retry_count
59
+ end
60
+ return false unless retry_data[:retryable]
61
+
62
+ # Checks whether there is a local error
63
+ # Cannot retry immediately when it returns true, as it need check other errors
64
+ should_retry_on_local_error? retry_data
65
+ return false unless should_retry_on_error? response, retry_data
66
+
67
+ # Determined that it needs to retry.
68
+ adjust_retry_request retry_data
69
+
70
+ wait_for_retry
71
+
72
+ retry_data[:retryable]
73
+ end
74
+
75
+ # Apply the retry policy to determine how the HTTP request should continue retrying
76
+ #
77
+ # retry_data - Hash. Stores stateful retry data
78
+ #
79
+ # The retry_data is a Hash which can be used to store
80
+ # stateful data about the request execution context (such as an
81
+ # incrementing counter, timestamp, etc). The retry_data object
82
+ # will be the same instance throughout the lifetime of the request
83
+ #
84
+ # Alternatively, a subclass could override this method.
85
+ def apply_retry_policy(retry_data)
86
+ end
87
+
88
+ # Determines if the HTTP request should continue retrying
89
+ #
90
+ # retry_data - Hash. Stores stateful retry data
91
+ #
92
+ # The retry_data is a Hash which can be used to store
93
+ # stateful data about the request execution context (such as an
94
+ # incrementing counter, timestamp, etc). The retry_data object
95
+ # will be the same instance throughout the lifetime of the request.
96
+ def should_retry_on_local_error?(retry_data)
97
+ unless retry_data[:error]
98
+ retry_data[:retryable] = true;
99
+ return true
100
+ end
101
+
102
+ error_message = retry_data[:error].inspect
103
+
104
+ if error_message.include?("SocketError: Hostname not known")
105
+ # Retry on local DNS resolving
106
+ # When uses resolv-replace.rb to replace the libc resolver
107
+ # Reference:
108
+ # https://makandracards.com/ninjaconcept/30815-fixing-socketerror-getaddrinfo-name-or-service-not-known-with-ruby-s-resolv-replace-rb
109
+ # http://www.subelsky.com/2014/05/fixing-socketerror-getaddrinfo-name-or.html
110
+ retry_data[:retryable] = true;
111
+ elsif error_message.include?("getaddrinfo: Name or service not known")
112
+ # When uses the default resolver
113
+ retry_data[:retryable] = true;
114
+ elsif error_message.downcase.include?("timeout")
115
+ retry_data[:retryable] = true;
116
+ elsif error_message.include?("Errno::ECONNRESET")
117
+ retry_data[:retryable] = true;
118
+ elsif error_message.include?("Errno::EACCES")
119
+ retry_data[:retryable] = false;
120
+ elsif error_message.include?("NOSUPPORT")
121
+ retry_data[:retryable] = false;
122
+ end
123
+
124
+ retry_data[:retryable]
125
+ end
126
+
127
+ # Determines if the HTTP request should continue retrying
128
+ #
129
+ # response - Azure::Core::Http::HttpResponse. The response from the active request
130
+ # retry_data - Hash. Stores stateful retry data
131
+ #
132
+ # The retry_data is a Hash which can be used to store
133
+ # stateful data about the request execution context (such as an
134
+ # incrementing counter, timestamp, etc). The retry_data object
135
+ # will be the same instance throughout the lifetime of the request.
136
+ def should_retry_on_error?(response, retry_data)
137
+ response = response || retry_data[:error].http_response if retry_data[:error] && retry_data[:error].respond_to?("http_response")
138
+ unless response
139
+ retry_data[:retryable] = false unless retry_data[:error]
140
+ return retry_data[:retryable]
141
+ end
142
+
143
+ check_location(response, retry_data)
144
+
145
+ check_status_code(retry_data)
146
+
147
+ retry_data[:retryable]
148
+ end
149
+
150
+ # Adjust the retry parameter and wait for retry
151
+ def wait_for_retry
152
+ sleep @retry_interval if @retry_interval > 0
153
+ end
154
+
155
+ # Adjust the retry request
156
+ #
157
+ # retry_data - Hash. Stores stateful retry data
158
+ def adjust_retry_request(retry_data)
159
+ # Adjust the location first
160
+ next_location = @request_options[:target_location].nil? ? get_next_location(retry_data) : @request_options[:target_location]
161
+ retry_data[:current_location] = next_location
162
+
163
+ retry_data[:uri] =
164
+ if next_location == Azure::Storage::Common::StorageLocation::PRIMARY
165
+ @request_options[:primary_uri]
166
+ else
167
+ @request_options[:secondary_uri]
168
+ end
169
+
170
+ # Now is the time to calculate the exact retry interval. ShouldRetry call above already
171
+ # returned back how long two requests to the same location should be apart from each other.
172
+ # However, for the reasons explained above, the time spent between the last attempt to
173
+ # the target location and current time must be subtracted from the total retry interval
174
+ # that ShouldRetry returned.
175
+ lastAttemptTime =
176
+ if retry_data[:current_location] == Azure::Storage::Common::StorageLocation::PRIMARY
177
+ retry_data[:last_primary_attempt]
178
+ else
179
+ retry_data[:last_secondary_attempt]
180
+ end
181
+
182
+ @retry_interval =
183
+ if lastAttemptTime.nil?
184
+ 0
185
+ else
186
+ since_last_attempt = Time.now - lastAttemptTime
187
+ remainder = retry_data[:interval] - since_last_attempt
188
+ remainder > 0 ? remainder : 0
189
+ end
190
+ end
191
+
192
+ # Initialize the retry data
193
+ #
194
+ # retry_data - Hash. Stores stateful retry data
195
+ def init_retry_data(retry_data)
196
+ @request_options = retry_data[:request_options] unless retry_data[:request_options].nil?
197
+
198
+ if retry_data[:current_location].nil?
199
+ retry_data[:current_location] = Azure::Storage::Common::Service::StorageService.get_location(@request_options[:location_mode], @request_options[:request_location_mode])
200
+ end
201
+
202
+ if retry_data[:current_location] == Azure::Storage::Common::StorageLocation::PRIMARY
203
+ retry_data[:last_primary_attempt] = Time.now
204
+ else
205
+ retry_data[:last_secondary_attempt] = Time.now
206
+ end
207
+ end
208
+
209
+ # Check the location
210
+ #
211
+ # retry_data - Hash. Stores stateful retry data
212
+ def check_location(response, retry_data)
213
+ # If a request sent to the secondary location fails with 404 (Not Found), it is possible
214
+ # that the resource replication is not finished yet. So, in case of 404 only in the secondary
215
+ # location, the failure should still be retryable.
216
+ retry_data[:secondary_not_found] =
217
+ ((retry_data[:current_location] === Azure::Storage::Common::StorageLocation::SECONDARY) &&
218
+ response.status_code === 404);
219
+
220
+ if retry_data[:secondary_not_found]
221
+ retry_data[:status_code] = 500
222
+ else
223
+ if (response.status_code)
224
+ retry_data[:status_code] = response.status_code
225
+ else
226
+ retry_data[:status_code] = nil
227
+ end
228
+ end
229
+ end
230
+
231
+ # Check the status code
232
+ #
233
+ # retry_data - Hash. Stores stateful retry data
234
+ def check_status_code(retry_data)
235
+ if (retry_data[:status_code] < 400)
236
+ retry_data[:retryable] = false;
237
+ # Non-timeout Cases
238
+ elsif (retry_data[:status_code] != 408)
239
+ # Always no retry on "not implemented" and "version not supported"
240
+ if (retry_data[:status_code] == 501 || retry_data[:status_code] == 505)
241
+ retry_data[:retryable] = false;
242
+ end
243
+
244
+ # When absorb_conditional_errors_on_retry is set (for append blob)
245
+ if (@request_options[:absorb_conditional_errors_on_retry])
246
+ if (retry_data[:status_code] == 412)
247
+ # When appending block with precondition failure and their was a server error before, we ignore the error.
248
+ if (retry_data[:last_server_error])
249
+ retry_data[:error] = nil;
250
+ retry_data[:retryable] = true;
251
+ else
252
+ retry_data[:retryable] = false;
253
+ end
254
+ elsif (retry_data[:retryable] && retry_data[:status_code] >= 500 && retry_data[:status_code] < 600)
255
+ # Retry on the server error
256
+ retry_data[:retryable] = true;
257
+ retry_data[:last_server_error] = true;
258
+ end
259
+ elsif (retry_data[:status_code] < 500)
260
+ # No retry on the client error
261
+ retry_data[:retryable] = false;
262
+ end
263
+ end
264
+ end
265
+
266
+ # Get retry request destination
267
+ #
268
+ # retry_data - Hash. Stores stateful retry data
269
+ def get_next_location(retry_data)
270
+ # In case of 404 when trying the secondary location, instead of retrying on the
271
+ # secondary, further requests should be sent only to the primary location, as it most
272
+ # probably has a higher chance of succeeding there.
273
+ if retry_data[:secondary_not_found] && @request_options[:location_mode] != Azure::Storage::Common::LocationMode::SECONDARY_ONLY
274
+ @request_options[:location_mode] = Azure::Storage::Common::LocationMode::PRIMARY_ONLY;
275
+ return Azure::Storage::Common::StorageLocation::PRIMARY
276
+ end
277
+
278
+ case @request_options[:location_mode]
279
+ when Azure::Storage::Common::LocationMode::PRIMARY_ONLY
280
+ Azure::Storage::Common::StorageLocation::PRIMARY
281
+ when Azure::Storage::Common::LocationMode::SECONDARY_ONLY
282
+ Azure::Storage::Common::StorageLocation::SECONDARY
283
+ else
284
+ # request_location_mode cannot be SECONDARY_ONLY because it will be blocked at the first time
285
+ if @request_options[:request_location_mode] == Azure::Storage::Common::RequestLocationMode::PRIMARY_ONLY
286
+ Azure::Storage::Common::StorageLocation::PRIMARY
287
+ elsif @request_options[:request_location_mode] == Azure::Storage::Common::RequestLocationMode::SECONDARY_ONLY
288
+ Azure::Storage::Common::StorageLocation::SECONDARY
289
+ else
290
+ if retry_data[:current_location] === Azure::Storage::Common::StorageLocation::PRIMARY
291
+ Azure::Storage::Common::StorageLocation::SECONDARY
292
+ else
293
+ Azure::Storage::Common::StorageLocation::PRIMARY
294
+ end
295
+ end
296
+ end
297
+ end
298
+
299
+ end
300
+ end