/// <summary> /// Waits for a condition to be satisfied. /// </summary> /// <typeparam name="T"> /// The changeType of object that will be operated on. /// </typeparam> /// <param name="client"> /// The client instance this is extending. /// </param> /// <param name="poll"> /// The function to poll the client for state. /// </param> /// <param name="continuePolling"> /// A function to evaluate the state to see if it matches the condition. /// </param> /// <param name="notifyHandler"> /// A notification handler used to rais events when the status changes. /// </param> /// <param name="interval"> /// A time frame to wait between polls. /// </param> /// <param name="timeout"> /// The amount of time to wait for the condition to be satisfied. /// </param> /// <param name="cancellationToken"> /// A Cancelation Token that can be used to cancel the request. /// </param> /// <returns> /// An awaitable task. /// </returns> public static async Task WaitForCondition <T>(this IHDInsightManagementPocoClient client, Func <Task <T> > poll, Func <T, PollResult> continuePolling, Action <T> notifyHandler, TimeSpan interval, TimeSpan timeout, CancellationToken cancellationToken) { client.ArgumentNotNull("client"); poll.ArgumentNotNull("poll"); continuePolling.ArgumentNotNull("continuePolling"); var start = DateTime.Now; int pollingFailures = 0; const int MaxPollingFailuresCount = 10; T pollingResult = default(T); PollResult result = PollResult.Continue; do { try { pollingResult = await poll(); result = continuePolling(pollingResult); if (notifyHandler.IsNotNull() && pollingResult.IsNotNull()) { notifyHandler(pollingResult); } if (result == PollResult.Unknown || result == PollResult.Null) { pollingFailures++; if (result == PollResult.Null) { client.LogMessage("Poll for cluster returned no cluster. Current error weight (out of 10): " + pollingFailures.ToString(CultureInfo.InvariantCulture), Severity.Informational, Verbosity.Diagnostic); } cancellationToken.WaitForInterval(interval); } else if (result == PollResult.Continue) { pollingFailures = 0; cancellationToken.WaitForInterval(interval); } } catch (Exception ex) { ex = ex.GetFirstException(); var hlex = ex as HttpLayerException; var httpEx = ex as HttpRequestException; var webex = ex as WebException; var timeOut = ex as TimeoutException; var taskCancled = ex as TaskCanceledException; var operationCanceled = ex as OperationCanceledException; if (taskCancled.IsNotNull() && taskCancled.CancellationToken.IsNotNull() && taskCancled.CancellationToken.IsCancellationRequested) { throw; } if (operationCanceled.IsNotNull() && operationCanceled.CancellationToken.IsNotNull() && operationCanceled.CancellationToken.IsCancellationRequested) { throw; } if (hlex.IsNotNull() || httpEx.IsNotNull() || webex.IsNotNull() || taskCancled.IsNotNull() || timeOut.IsNotNull() || operationCanceled.IsNotNull()) { pollingFailures += 5; client.LogMessage("Poll for cluster a manageable exception. Current error weight (out of 10): " + pollingFailures.ToString(CultureInfo.InvariantCulture), Severity.Informational, Verbosity.Diagnostic); client.LogMessage(ex.ToString(), Severity.Informational, Verbosity.Diagnostic); if (pollingFailures >= MaxPollingFailuresCount) { client.LogMessage("Polling error weight exceeded maximum allowed. Aborting operation.", Severity.Error, Verbosity.Normal); throw; } } else { client.LogMessage("Poll for cluster returned an unmanageable exception. Aborting operation.", Severity.Error, Verbosity.Normal); client.LogException(ex); throw; } } }while ((result == PollResult.Continue || result == PollResult.Null || result == PollResult.Unknown) && DateTime.Now - start < timeout && pollingFailures <= MaxPollingFailuresCount); if (pollingFailures > MaxPollingFailuresCount) { client.LogMessage("Polling error weight exceeded maximum allowed. Aborting operation.", Severity.Error, Verbosity.Normal); } if (notifyHandler.IsNotNull() && pollingResult.IsNotNull()) { notifyHandler(pollingResult); } }