You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

79 lines
2.9 KiB

  1. /*
  2. * MinIO .NET Library for Amazon S3 Compatible Cloud Storage, (C) 2020, 2021 MinIO, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. using Minio.DataModel.Result;
  17. using Minio.Exceptions;
  18. using Minio.Handlers;
  19. using Polly;
  20. namespace Minio.Examples.Cases;
  21. internal static class RetryPolicyHelper
  22. {
  23. private const int DefaultRetryCount = 3;
  24. private static readonly TimeSpan defaultRetryInterval = TimeSpan.FromMilliseconds(200);
  25. private static readonly TimeSpan defaultMaxRetryInterval = TimeSpan.FromSeconds(10);
  26. // exponential backoff with jitter, truncated by max retry interval
  27. public static TimeSpan CalcBackoff(int retryAttempt, TimeSpan retryInterval, TimeSpan maxRetryInterval)
  28. {
  29. // 0.8..1.2
  30. var jitter = 0.8 + (new Random(Environment.TickCount).NextDouble() * 0.4);
  31. // (2^retryCount - 1) * jitter
  32. var scaleCoeff = (Math.Pow(2.0, retryAttempt) - 1.0) * jitter;
  33. // Apply scale coefficient
  34. var result = TimeSpan.FromMilliseconds(retryInterval.TotalMilliseconds * scaleCoeff);
  35. // Truncate by max retry interval
  36. return result < maxRetryInterval ? result : maxRetryInterval;
  37. }
  38. public static PolicyBuilder<ResponseResult> CreatePolicyBuilder()
  39. {
  40. return Policy<ResponseResult>
  41. .Handle<ConnectionException>()
  42. .Or<InternalClientException>(ex =>
  43. ex.Message.StartsWith("Unsuccessful response from server", StringComparison.InvariantCulture));
  44. }
  45. public static AsyncPolicy<ResponseResult> GetDefaultRetryPolicy()
  46. {
  47. return GetDefaultRetryPolicy(DefaultRetryCount, defaultRetryInterval, defaultMaxRetryInterval);
  48. }
  49. public static AsyncPolicy<ResponseResult> GetDefaultRetryPolicy(
  50. int retryCount,
  51. TimeSpan retryInterval,
  52. TimeSpan maxRetryInterval)
  53. {
  54. return CreatePolicyBuilder()
  55. .WaitAndRetryAsync(
  56. retryCount,
  57. i => CalcBackoff(i, retryInterval, maxRetryInterval));
  58. }
  59. public static IRetryPolicyHandler AsRetryDelegate(this AsyncPolicy<ResponseResult> policy)
  60. {
  61. return policy is null
  62. ? null
  63. : new RetryPolicyHandler(policy);
  64. }
  65. public static IMinioClient WithRetryPolicy(this IMinioClient client, AsyncPolicy<ResponseResult> policy)
  66. {
  67. return client.WithRetryPolicy(policy.AsRetryDelegate());
  68. }
  69. }