public void ReturnsFalseIfNotCorrectExceptionType() { var e = new Exception(); var result = RetryWithExponentialBackoff.IsTransientError(e, null); Assert.False(result); }
/// <summary> /// Retrieve a list of plannerPlan objects owned by a group object. /// </summary> /// <param name="groupId">The ID of the group (team) to retrieve the list of plannerPlan from.</param> /// <returns>If successful, this method returns a 200 OK response code and collection of plannerPlan objects in the response body. In case of errors, see HTTP status codes.</returns> public async Task <PlannerPlan[]> GetPlanners(string groupId) { // C# 8.0 Preview 2 feature. using var cs = this.GetCodeSection(); PlannerPlan[] planners; try { HttpResponseMessage httpResponseMessage = null; var retry = new RetryWithExponentialBackoff <HttpResponseMessage>(); await retry.RunAsync( async() => { httpResponseMessage = await HttpClient.GetAsync(O365Settings.MsGraphBetaEndpoint + $"/groups/{groupId}/planner/plans/"); return(httpResponseMessage); }); if (!httpResponseMessage.IsSuccessStatusCode) { var ex = new HttpRequestException(Constants.EXCEPTION_HTTPREQUEST + $" Status Code: {httpResponseMessage.StatusCode}."); cs.Exception(ex); throw ex; } var httpResultString = httpResponseMessage.Content.ReadAsStringAsync().Result; var root = JsonConvert.DeserializeObject <RootElem <PlannerPlan> >(httpResultString); planners = root.Values; } catch (Exception ex) { cs.Exception(ex); throw; } return(planners); }
public void ReturnsFalseIfResponseStatusBelow500OrWhitelisted(Exception e, HttpStatusCode status) { var response = new HttpResponseMessage(status); var result = RetryWithExponentialBackoff.IsTransientError(e, response); Assert.False(result); }
public void ReturnsTrueIfResponseStatusAbove500(Exception e, HttpStatusCode status) { var response = new HttpResponseMessage(status); var result = RetryWithExponentialBackoff.IsTransientError(e, response); Assert.True(result); }
/// <summary> /// Send event card /// </summary> /// <param name="eventMessages">List of EventMessage</param> /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns> private async Task SendEventCard(List <EventMessage> eventMessages) { var tasks = Task.Run(() => { Parallel.ForEach(eventMessages, new ParallelOptions { MaxDegreeOfParallelism = MaxParallelism }, async(eventMessage) => { var activity = eventMessage.Activity; HeroCard card = null; switch (eventMessage.MessageType) { case MessageType.Event: card = CelebrationCard.GetEventCard(activity); break; case MessageType.Preview: card = CelebrationCard.GetPreviewCard(activity); break; } var task = this.connectorServiceHelper.SendPersonalMessageAsync(string.Empty, new List <Attachment> { card.ToAttachment() }, activity.ConversationId); RetryWithExponentialBackoff retryBackOff = new RetryWithExponentialBackoff(); await retryBackOff.RunAsync(task, eventMessage, this.SuccessCallback, this.FailureCallback); }); }); await tasks; }
/// <summary> /// Use this API to create a new plannerTask. /// </summary> /// <param name="planId">The plannerplan's ID to create a new plannerTask into.</param> /// <param name="bucket"></param> /// <param name="sTask"></param> /// <returns>If successful, this method returns 201 Created response code and plannerTask object in the response body. In case of errors, see HTTP status codes.</returns> private async Task <PlannerTask> CreateTask(string planId, PlannerBucket bucket, PlannerTask sTask) { // C# 8.0 Preview 2 feature. using var cs = this.GetCodeSection(); if (string.IsNullOrWhiteSpace(planId) || bucket == null || sTask == null) { cs.Warning(Constants.MESSAGE_WARNING_NULLARGUMENTS); return(null); } dynamic body = new ExpandoObject(); body.planId = planId; body.bucketId = bucket.Id; body.title = sTask.Title; body.startDateTime = sTask.StartDateTime; body.dueDateTime = sTask.DueDateTime; var bodyContent = JsonConvert.SerializeObject(body); cs.Debug($"\nBody content:\n-Title: {body.title}\n-Plan Id: {body.planId}"); PlannerTask newTask; try { HttpResponseMessage httpResponseMessage = null; var retry = new RetryWithExponentialBackoff <HttpResponseMessage>(); await retry.RunAsync( async() => { httpResponseMessage = await HttpClient.PostAsync( new Uri(O365Settings.MsGraphBetaEndpoint + $"/planner/tasks"), new StringContent(bodyContent, Encoding.UTF8, "application/json")); return(httpResponseMessage); }); if (!httpResponseMessage.IsSuccessStatusCode) { var ex = new HttpRequestException(Constants.EXCEPTION_HTTPREQUEST + $" Status Code: {httpResponseMessage.StatusCode}."); cs.Exception(ex); throw ex; } var httpResultString = httpResponseMessage.Content.ReadAsStringAsync().Result; newTask = JsonConvert.DeserializeObject <PlannerTask>(httpResultString); } catch (Exception ex) { cs.Exception(ex); throw; } return(newTask); }
/// <summary> /// Update the properties of plannerplandetails object. /// </summary> /// <param name="planId"></param> /// <param name="eTag"></param> /// <param name="categoryDescriptions"></param> /// <param name="sharedWith"></param> /// <returns>If successful, this method returns a 200 OK response code and updated plannerPlanDetails object in the response body. In case of errors, see HTTP status codes.</returns> public async Task UpdatePlannerDetails(string planId, string eTag, object categoryDescriptions, object sharedWith) { // C# 8.0 Preview 2 feature. using var cs = this.GetCodeSection(); if (string.IsNullOrWhiteSpace(planId) || string.IsNullOrWhiteSpace(eTag) || categoryDescriptions == null || sharedWith == null) { cs.Warning(Constants.MESSAGE_WARNING_NULLARGUMENTS); return; } dynamic body = new ExpandoObject(); body.categoryDescriptions = categoryDescriptions; body.sharedWith = sharedWith; var bodyContent = JsonConvert.SerializeObject(body); cs.Debug($"Body content:\n-Plan Id: {planId}\n-Category Description: {body.categoryDescriptions}\n-Shared With: {body.sharedWith}"); try { HttpResponseMessage httpResponseMessage = null; var retry = new RetryWithExponentialBackoff <HttpResponseMessage>(); await retry.RunAsync( async() => { httpResponseMessage = await HttpClient.SendTeamsAsync ( HttpVerb.PATCH, new Uri(O365Settings.MsGraphBetaEndpoint + $"/planner/plans/{planId}/details"), eTag, new StringContent(bodyContent, Encoding.UTF8, "application/json") ); return(httpResponseMessage); }); if (!httpResponseMessage.IsSuccessStatusCode) { var ex = new HttpRequestException(Constants.EXCEPTION_HTTPREQUEST + $" Status Code: {httpResponseMessage.StatusCode}."); cs.Exception(ex); throw ex; } } catch (Exception ex) { cs.Exception(ex); throw; } }
/// <summary> /// Create a copy of a team. This operation also creates a copy of the corresponding group. /// </summary> /// <param name="request"></param> /// <returns>If successful, this method will return a 202 Accepted response code with a Location: header pointing to the operation resource. /// When the operation is complete, the operation resource will tell you the id of the created team.</returns> public async Task <bool> CloneTeam(InCloneTeamMessage request) { // C# 8.0 Preview 2 feature. using var cs = this.GetCodeSection(); bool created = false; if (request == null) { cs.Warning(Constants.MESSAGE_WARNING_NULLARGUMENTS); return(created); } var bodyContent = JsonConvert.SerializeObject(request); try { HttpResponseMessage httpResponseMessage = null; var retry = new RetryWithExponentialBackoff <HttpResponseMessage>(); await retry.RunAsync( async() => { httpResponseMessage = await HttpClient.PostAsync(O365Settings.MsGraphBetaEndpoint + $"/teams/{request.TeamId}/clone", new StringContent(bodyContent, Encoding.UTF8, "application/json")); return(httpResponseMessage); }); if (!httpResponseMessage.IsSuccessStatusCode) { var ex = new HttpRequestException(Constants.EXCEPTION_HTTPREQUEST + $" Status Code: {httpResponseMessage.StatusCode}."); cs.Exception(ex); throw ex; } created = true; } catch (Exception ex) { cs.Exception(ex); throw; } return(created); }
/// <summary> /// Use this API to create a new plannerPlan. /// </summary> /// <param name="groupId">The group's ID (team) to create the plannerPlan into.</param> /// <returns>If successful, this method returns 201 Created response code and plannerPlan object in the response body. In case of errors, see HTTP status codes.</returns> public async Task CreatePlannerPlan(string groupId) { // C# 8.0 Preview 2 feature. using var cs = this.GetCodeSection(); if (string.IsNullOrWhiteSpace(groupId)) { cs.Warning(Constants.MESSAGE_WARNING_NULLARGUMENTS); return; } var plannerPlan = new PlannerPlan() { Id = groupId }; var plannerPlanContent = JsonConvert.SerializeObject(plannerPlan); try { HttpResponseMessage httpResponseMessage = null; var retry = new RetryWithExponentialBackoff <HttpResponseMessage>(); await retry.RunAsync( async() => { httpResponseMessage = await HttpClient.PostAsync(O365Settings.MsGraphBetaEndpoint + "/planner/plans", new StringContent(plannerPlanContent, Encoding.UTF8, "application/json")); return(httpResponseMessage); }); if (!httpResponseMessage.IsSuccessStatusCode) { var ex = new HttpRequestException(Constants.EXCEPTION_HTTPREQUEST + $" Status Code: {httpResponseMessage.StatusCode}."); cs.Exception(ex); throw ex; } } catch (Exception ex) { cs.Exception(ex); throw; } }
/// <summary> /// Retrieve the properties and relationships of a channel. /// </summary> /// <param name="teamId"></param> /// <returns>If successful, this method returns a 200 OK response code and a channel object in the response body.</returns> public async Task <Channel[]> GetChannels(string teamId) { // C# 8.0 Preview 2 feature. using var cs = this.GetCodeSection(); if (string.IsNullOrWhiteSpace(teamId)) { cs.Warning(Constants.MESSAGE_WARNING_NULLARGUMENTS); return(null); } Channel[] channels = null; try { HttpResponseMessage httpResponseMessage = null; var retry = new RetryWithExponentialBackoff <HttpResponseMessage>(); await retry.RunAsync( async() => { httpResponseMessage = await HttpClient.GetAsync(O365Settings.MsGraphBetaEndpoint + "teams/" + teamId + "/channels"); return(httpResponseMessage); }); if (!httpResponseMessage.IsSuccessStatusCode) { var ex = new HttpRequestException(Constants.EXCEPTION_HTTPREQUEST + $" Status Code: {httpResponseMessage.StatusCode}."); cs.Exception(ex); throw ex; } var httpResultString = httpResponseMessage.Content.ReadAsStringAsync().Result; var root = JsonConvert.DeserializeObject <RootElem <Channel> >(httpResultString); channels = root.Values; } catch (Exception ex) { cs.Exception(ex); throw; } return(channels); }
/// <summary> /// Retrieve the properties and relationships of plannerplandetails object. /// </summary> /// <param name="planId">The plan's ID to get the properties and relationships from.</param> /// <returns>If successful, this method returns a 200 OK response code and plannerPlanDetails object in the response body. In case of errors, see HTTP status codes.</returns> public async Task <PlannerPlanDetails> GetPlannerDetails(string planId) { // C# 8.0 Preview 2 feature. using var cs = this.GetCodeSection(); if (string.IsNullOrWhiteSpace(planId)) { cs.Warning(Constants.MESSAGE_WARNING_NULLARGUMENTS); return(null); } PlannerPlanDetails details; try { HttpResponseMessage httpResponseMessage = null; var retry = new RetryWithExponentialBackoff <HttpResponseMessage>(); await retry.RunAsync( async() => { httpResponseMessage = await HttpClient.GetAsync(O365Settings.MsGraphBetaEndpoint + $"/planner/plans/{planId}/details"); return(httpResponseMessage); }); if (!httpResponseMessage.IsSuccessStatusCode) { var ex = new HttpRequestException(Constants.EXCEPTION_HTTPREQUEST + $" Status Code: {httpResponseMessage.StatusCode}."); cs.Exception(ex); throw ex; } var httpResultString = httpResponseMessage.Content.ReadAsStringAsync().Result; details = JsonConvert.DeserializeObject <PlannerPlanDetails>(httpResultString); } catch (Exception ex) { cs.Exception(ex); throw; } return(details); }
/// <summary> /// Delete a plannerBucket. /// </summary> /// <param name="bucketId">The plannerBucket's ID to delete.</param> /// <param name="eTag">eTag of the plannerBucket resource.</param> /// <returns>If successful, this method returns 204 No Content response code. It does not return anything in the response body. In case of errors, see HTTP status codes.</returns> public async Task DeleteBucket(string bucketId, string eTag) { // C# 8.0 Preview 2 feature. using var cs = this.GetCodeSection(); if (string.IsNullOrWhiteSpace(bucketId) || string.IsNullOrWhiteSpace(eTag)) { cs.Warning(Constants.MESSAGE_WARNING_NULLARGUMENTS); return; } try { HttpResponseMessage httpResponseMessage = null; var retry = new RetryWithExponentialBackoff <HttpResponseMessage>(); await retry.RunAsync( async() => { httpResponseMessage = await HttpClient.SendTeamsAsync( HttpVerb.DELETE, new Uri(O365Settings.MsGraphBetaEndpoint + $"/planner/buckets/{bucketId}"), eTag, null); return(httpResponseMessage); }); if (!httpResponseMessage.IsSuccessStatusCode) { var ex = new HttpRequestException(Constants.EXCEPTION_HTTPREQUEST + $" Status Code: {httpResponseMessage.StatusCode}."); cs.Exception(ex); throw ex; } } catch (Exception ex) { cs.Exception(ex); throw ex; } }
internal static TResponse DecorateWithRetry <TResponse>(Func <TResponse> apiCall) { var retry = new RetryWithExponentialBackoff(); return(retry.Run(apiCall)); }
public void ReturnsTrueIfResponseNull(Exception e) { var result = RetryWithExponentialBackoff.IsTransientError(e, null); Assert.True(result); }
/// <summary> /// Update the properties of plannertaskdetails object. /// </summary> /// <param name="taskId"></param> /// <param name="eTag"></param> /// <param name="checklist"></param> /// <param name="description"></param> /// <param name="previewType"></param> /// <param name="references"></param> /// <returns>If successful, this method returns a 200 OK response code and updated plannerTaskDetails object in the response body. In case of errors, see HTTP status codes.</returns> public async Task UpdateTaskDetails(string taskId, string eTag, Dictionary <string, Checklist> checklist = null, string description = null, string previewType = null, object references = null) { // C# 8.0 Preview 2 feature. using var cs = this.GetCodeSection(); if (string.IsNullOrWhiteSpace(taskId) || string.IsNullOrWhiteSpace(eTag)) { cs.Warning(Constants.MESSAGE_WARNING_NULLARGUMENTS); return; } dynamic body = new ExpandoObject(); if (checklist?.Count > 0) { var newChecklist = new Dictionary <string, object>(); foreach (string k in checklist.Keys) { var ch = new Dictionary <string, string> { { "@odata.type", "#microsoft.graph.plannerChecklistItem" }, { "title", checklist[k].Title }, { "isChecked", checklist[k].IsChecked.ToString() } }; newChecklist.Add(Guid.NewGuid().ToString(), ch); } body.checklist = newChecklist; } body.description = description; body.previewType = previewType; body.references = references; // TODO: use JsonConverter. var bodyContent = JsonConvert.SerializeObject(body); try { HttpResponseMessage httpResponseMessage = null; var retry = new RetryWithExponentialBackoff <HttpResponseMessage>(); await retry.RunAsync( async() => { httpResponseMessage = await HttpClient.SendTeamsAsync( HttpVerb.PATCH, new Uri(O365Settings.MsGraphBetaEndpoint + $"/planner/tasks/{taskId}/details"), eTag, new StringContent(bodyContent, Encoding.UTF8, "application/json")); return(httpResponseMessage); }); if (!httpResponseMessage.IsSuccessStatusCode) { var ex = new HttpRequestException(Constants.EXCEPTION_HTTPREQUEST + $" Status Code: {httpResponseMessage.StatusCode}."); cs.Exception(ex); throw ex; } } catch (Exception ex) { cs.Exception(ex); throw; } }