PageRenderTime 51ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/src/ServiceStack.Common/ExecExtensions.cs

http://github.com/ServiceStack/ServiceStack
C# | 142 lines | 125 code | 16 blank | 1 comment | 12 complexity | caedf5f99e90e6489ba7b6a72c4c1cdb MD5 | raw file
Possible License(s): BSD-3-Clause
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Threading;
  4. using ServiceStack.Logging;
  5. namespace ServiceStack
  6. {
  7. public static class ExecExtensions
  8. {
  9. public static void LogError(Type declaringType, string clientMethodName, Exception ex)
  10. {
  11. var log = LogManager.GetLogger(declaringType);
  12. log.Error(string.Format("'{0}' threw an error on {1}: {2}", declaringType.FullName, clientMethodName, ex.Message), ex);
  13. }
  14. public static void ExecAll<T>(this IEnumerable<T> instances, Action<T> action)
  15. {
  16. foreach (var instance in instances)
  17. {
  18. try
  19. {
  20. action(instance);
  21. }
  22. catch (Exception ex)
  23. {
  24. LogError(instance.GetType(), action.GetType().Name, ex);
  25. }
  26. }
  27. }
  28. public static void ExecAllWithFirstOut<T, TReturn>(this IEnumerable<T> instances, Func<T, TReturn> action, ref TReturn firstResult)
  29. {
  30. foreach (var instance in instances)
  31. {
  32. try
  33. {
  34. var result = action(instance);
  35. if (!Equals(firstResult, default(TReturn)))
  36. {
  37. firstResult = result;
  38. }
  39. }
  40. catch (Exception ex)
  41. {
  42. LogError(instance.GetType(), action.GetType().Name, ex);
  43. }
  44. }
  45. }
  46. public static TReturn ExecReturnFirstWithResult<T, TReturn>(this IEnumerable<T> instances, Func<T, TReturn> action)
  47. {
  48. foreach (var instance in instances)
  49. {
  50. try
  51. {
  52. var result = action(instance);
  53. if (!Equals(result, default(TReturn)))
  54. {
  55. return result;
  56. }
  57. }
  58. catch (Exception ex)
  59. {
  60. LogError(instance.GetType(), action.GetType().Name, ex);
  61. }
  62. }
  63. return default(TReturn);
  64. }
  65. public static void RetryUntilTrue(Func<bool> action, TimeSpan? timeOut)
  66. {
  67. var i = 0;
  68. var firstAttempt = DateTime.UtcNow;
  69. while (timeOut == null || DateTime.UtcNow - firstAttempt < timeOut.Value)
  70. {
  71. i++;
  72. if (action())
  73. {
  74. return;
  75. }
  76. SleepBackOffMultiplier(i);
  77. }
  78. throw new TimeoutException(string.Format("Exceeded timeout of {0}", timeOut.Value));
  79. }
  80. public static void RetryOnException(Action action, TimeSpan? timeOut)
  81. {
  82. var i = 0;
  83. Exception lastEx = null;
  84. var firstAttempt = DateTime.UtcNow;
  85. while (timeOut == null || DateTime.UtcNow - firstAttempt < timeOut.Value)
  86. {
  87. i++;
  88. try
  89. {
  90. action();
  91. return;
  92. }
  93. catch (Exception ex)
  94. {
  95. lastEx = ex;
  96. SleepBackOffMultiplier(i);
  97. }
  98. }
  99. throw new TimeoutException(string.Format("Exceeded timeout of {0}", timeOut.Value), lastEx);
  100. }
  101. public static void RetryOnException(Action action, int maxRetries)
  102. {
  103. for (var i = 0; i < maxRetries; i++)
  104. {
  105. try
  106. {
  107. action();
  108. break;
  109. }
  110. catch
  111. {
  112. if (i == maxRetries - 1) throw;
  113. SleepBackOffMultiplier(i);
  114. }
  115. }
  116. }
  117. private static void SleepBackOffMultiplier(int i)
  118. {
  119. //exponential/random retry back-off.
  120. var rand = new Random(Guid.NewGuid().GetHashCode());
  121. var nextTry = rand.Next(
  122. (int)Math.Pow(i, 2), (int)Math.Pow(i + 1, 2) + 1);
  123. Thread.Sleep(nextTry);
  124. }
  125. }
  126. }