Time.cs
1 namespace Utils 2 { 3 public static class Time 4 { 5 public static void Sleep(TimeSpan span) 6 { 7 Thread.Sleep(span); 8 } 9 10 public static T Wait<T>(Task<T> task) 11 { 12 task.Wait(); 13 return task.Result; 14 } 15 16 public static void Wait(Task task) 17 { 18 task.Wait(); 19 } 20 21 public static string FormatDuration(TimeSpan? d) 22 { 23 if (d == null) return "[NULL]"; 24 return FormatDuration(d.Value); 25 } 26 27 public static string FormatDuration(TimeSpan d) 28 { 29 var result = ""; 30 if (d.Days > 0) result += $"{d.Days} days, "; 31 if (d.Hours > 0) result += $"{d.Hours} hours, "; 32 if (d.Minutes > 0) result += $"{d.Minutes} mins, "; 33 result += $"{d.Seconds} secs"; 34 return result; 35 } 36 37 public static string FormatTimestamp(DateTime d) 38 { 39 return d.ToString("o"); 40 } 41 42 public static TimeSpan ParseTimespan(string span) 43 { 44 span = span.Replace(" ", "").Replace(",", ""); 45 var result = TimeSpan.Zero; 46 var number = ""; 47 foreach (var c in span) 48 { 49 if (char.IsNumber(c)) number += c; 50 else 51 { 52 var value = Convert.ToInt32(number); 53 number = ""; 54 55 if (c == 'd') result += TimeSpan.FromDays(value); 56 else if (c == 'h') result += TimeSpan.FromHours(value); 57 else if (c == 'm') result += TimeSpan.FromMinutes(value); 58 else if (c == 's') result += TimeSpan.FromSeconds(value); 59 else throw new Exception("Unknown time modifier: " + c); 60 } 61 } 62 63 if (!string.IsNullOrEmpty(number)) 64 { 65 var value = Convert.ToInt32(number); 66 result += TimeSpan.FromSeconds(value); 67 } 68 return result; 69 } 70 71 public static void WaitUntil(Func<bool> predicate, string msg) 72 { 73 WaitUntil(predicate, TimeSpan.FromMinutes(1), TimeSpan.FromSeconds(1), msg); 74 } 75 76 public static void WaitUntil(Func<bool> predicate, TimeSpan timeout, TimeSpan retryDelay, string msg) 77 { 78 var start = DateTime.UtcNow; 79 var tries = 1; 80 var state = predicate(); 81 while (!state) 82 { 83 var duration = DateTime.UtcNow - start; 84 if (duration > timeout) 85 { 86 throw new TimeoutException($"Operation timed out after {tries} tries over (total) {FormatDuration(duration)}. '{msg}'"); 87 } 88 89 Sleep(retryDelay); 90 state = predicate(); 91 tries++; 92 } 93 } 94 95 public static void Retry(Action action, string description) 96 { 97 Retry(action, TimeSpan.FromSeconds(30), description); 98 } 99 100 public static T Retry<T>(Func<T> action, string description) 101 { 102 return Retry(action, TimeSpan.FromSeconds(30), description); 103 } 104 105 public static void Retry(Action action, TimeSpan maxTimeout, string description) 106 { 107 Retry(action, maxTimeout, TimeSpan.FromSeconds(5), description); 108 } 109 110 public static T Retry<T>(Func<T> action, TimeSpan maxTimeout, string description) 111 { 112 return Retry(action, maxTimeout, TimeSpan.FromSeconds(5), description); 113 } 114 115 public static void Retry(Action action, TimeSpan maxTimeout, TimeSpan retryTime, string description) 116 { 117 Retry(action, maxTimeout, retryTime, description, f => { }); 118 } 119 120 public static T Retry<T>(Func<T> action, TimeSpan maxTimeout, TimeSpan retryTime, string description) 121 { 122 return Retry(action, maxTimeout, retryTime, description, f => { }); 123 } 124 125 public static void Retry(Action action, TimeSpan maxTimeout, TimeSpan retryTime, string description, Action<Failure> onFail) 126 { 127 var r = new Retry(description, maxTimeout, retryTime, onFail, failFast: true); 128 r.Run(action); 129 } 130 131 public static T Retry<T>(Func<T> action, TimeSpan maxTimeout, TimeSpan retryTime, string description, Action<Failure> onFail) 132 { 133 var r = new Retry(description, maxTimeout, retryTime, onFail, failFast: true); 134 return r.Run(action); 135 } 136 } 137 }