azure-storage-common 1.1.0 → 2.0.1

Sign up to get free protection for your applications and to get access to all the features.
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