public IntegrationEventSubscriptionAttempt GetLastAttempt(IntegrationEventSubscriptionAttempt subscriptionAttempt) { var result = repo.Find(0, 1).Items? .Where(a => a.EventLogID == subscriptionAttempt.EventLogID && a.IntegrationEventSubscriptionID == subscriptionAttempt.IntegrationEventSubscriptionID)? .OrderByDescending(a => a.AttemptCounter) .FirstOrDefault(); return(result); }
public async Task SendWebhook(IntegrationEventSubscription eventSubscription, WebhookPayload payload, IntegrationEventSubscriptionAttempt subscriptionAttempt, bool isSystemEvent, string payloadJSON) { var attemptCount = _attemptManager.SaveAndGetAttemptCount(subscriptionAttempt, eventSubscription.Max_RetryCount); payload.AttemptCount = attemptCount; if (isSystemEvent == true)//event is system event use system generated payload { payloadJSON = JsonConvert.SerializeObject(payload); } bool isSuccessful; try { isSuccessful = await SendWebhookAsync(payloadJSON, eventSubscription.HTTP_URL, eventSubscription); } catch (Exception exception) //an internal error occurred { throw exception; } if (!isSuccessful) { if (attemptCount > (eventSubscription.Max_RetryCount ?? 1)) { var previousAttempt = _attemptManager.GetLastAttempt(subscriptionAttempt); previousAttempt.Status = "FailedFatally"; _attemptRepository.Update(previousAttempt); } else { throw new Exception($"Webhook sending attempt failed."); } } else { var previousAttempt = _attemptManager.GetLastAttempt(subscriptionAttempt); previousAttempt.Status = "Completed"; _attemptRepository.Update(previousAttempt); } return; }
public async Task SendWebhook(IntegrationEventSubscription eventSubscription, WebhookPayload payload, IntegrationEventSubscriptionAttempt subscriptionAttempt) { var attemptCount = _attemptManager.SaveAndGetAttemptCount(subscriptionAttempt, eventSubscription.Max_RetryCount); payload.AttemptCount = attemptCount; bool isSuccessful; try { isSuccessful = await SendWebhookAsync(payload, eventSubscription.HTTP_URL, eventSubscription); } catch (Exception exception) //an internal error occurred { throw exception; } if (!isSuccessful) { if (attemptCount > eventSubscription.Max_RetryCount) { var previousAttempt = _attemptManager.GetLastAttempt(subscriptionAttempt); previousAttempt.Status = "FailedFatally"; _attemptRepository.Update(previousAttempt); } else { throw new Exception($"Webhook sending attempt failed."); } } else { var previousAttempt = _attemptManager.GetLastAttempt(subscriptionAttempt); previousAttempt.Status = "Completed"; _attemptRepository.Update(previousAttempt); } return; }
public int?SaveAndGetAttemptCount(IntegrationEventSubscriptionAttempt currentAttempt, int?maxRetryCount) { int?attemptCount = 0; var previousAttempt = GetLastAttempt(currentAttempt); //if no attempt exists, then this is the first attempt if (previousAttempt == null) { attemptCount = 1; } else { previousAttempt.Status = "Failed"; attemptCount = previousAttempt.AttemptCounter; attemptCount++; repo.Update(previousAttempt); } currentAttempt.AttemptCounter = attemptCount; currentAttempt.CreatedOn = DateTime.UtcNow; currentAttempt.Id = Guid.NewGuid(); repo.Add(currentAttempt); return(attemptCount); }
/// <summary> /// Publishes IntegrationEvents to all subscriptions /// </summary> /// <param name="integrationEventName"> Unique name for IntegrationEvent</param> /// <param name="entityId">Optional parameter that specifies the entity which was affected</param> /// <param name="entityName">Optional parameter that specifies the name of the affected entity</param> /// <returns></returns> public async Task PublishAsync(string integrationEventName, string entityId = "", string entityName = "") { //get all subscriptions for the event var eventSubscriptions = _eventSubscriptionRepository.Find(0, 1).Items?. Where(s => s.IntegrationEventName == integrationEventName || s.EntityID == Guid.Parse(entityId)); if (eventSubscriptions == null) { return; } //get current integration event var integrationEvent = _eventRepository.Find(0, 1).Items?.Where(e => e.Name == integrationEventName).FirstOrDefault(); if (integrationEvent == null) { return; } WebhookPayload payload = CreatePayload(integrationEvent, entityId, entityName); //log integration event IntegrationEventLog eventLog = new IntegrationEventLog() { IntegrationEventName = integrationEventName, OccuredOnUTC = DateTime.UtcNow, EntityType = integrationEvent.EntityType, EntityID = Guid.Parse(entityId), PayloadJSON = JsonConvert.SerializeObject(payload), CreatedOn = DateTime.UtcNow, Message = "", Status = "", SHA256Hash = "" }; eventLog = _eventLogRepository.Add(eventLog); //get subscriptions that must receive webhook foreach (var eventSubscription in eventSubscriptions) { //handle subscriptions that should not get notified if (!((eventSubscription.IntegrationEventName == integrationEventName || eventSubscription.IntegrationEventName == null) && (eventSubscription.EntityID == new Guid(entityId) || eventSubscription.EntityID == null))) { continue; //do not create an attempt in this case } //create new IntegrationEventSubscriptionAttempt IntegrationEventSubscriptionAttempt subscriptionAttempt = new IntegrationEventSubscriptionAttempt() { EventLogID = eventLog.Id, IntegrationEventName = eventSubscription.IntegrationEventName, IntegrationEventSubscriptionID = eventSubscription.Id, Status = "InProgress", AttemptCounter = 0, CreatedOn = DateTime.UtcNow, }; switch (eventSubscription.TransportType) { case TransportType.HTTPS: //create a background job to send the webhook _backgroundJobClient.Enqueue <WebhookSender>(x => x.SendWebhook(eventSubscription, payload, subscriptionAttempt)); break; case TransportType.Queue: QueueItem queueItem = new QueueItem { Name = eventSubscription.Name, IsLocked = false, QueueId = eventSubscription.QUEUE_QueueID ?? Guid.Empty, Type = "Json", JsonType = "IntegrationEvent", DataJson = JsonConvert.SerializeObject(payload), State = "New", RetryCount = eventSubscription.Max_RetryCount ?? 1, Source = eventSubscription.IntegrationEventName, Event = integrationEvent.Description, CreatedOn = DateTime.UtcNow, }; _queueItemRepository.Add(queueItem); subscriptionAttempt.AttemptCounter = 1; _attemptRepository.Add(subscriptionAttempt); break; case TransportType.SignalR: await _hub.Clients.All.SendAsync(integrationEventName, JsonConvert.SerializeObject(payload)).ConfigureAwait(false); subscriptionAttempt.AttemptCounter = 1; _attemptRepository.Add(subscriptionAttempt); break; } } return; }