public async Task OnMessageDispatchedAsync(OutputResult outputResult) { // If dispatch failed, update the history table with target -1 if (!outputResult.Delivered) { var historyTable = await GetHistoryTableAsync(outputResult.EngagementAccount); var historyEntity = new MessageHistoryTableEntity(outputResult.EngagementAccount, outputResult.MessageId.ToString()); if (historyEntity == null) { EmailProviderEventSource.Current.Warning(EmailProviderEventSource.EmptyTrackingId, this, nameof(this.OnMessageDispatchedAsync), OperationStates.Dropped, $"Does not find record for messageId={outputResult.MessageId}"); return; } historyEntity.Targets = -1; await MessageHistoryTableEntity.InsertOrMergeAsync(historyTable, historyEntity); } // If succeed, update the in-progress table else { // Insert in-progress table var inProgressEntity = new ReportInProgressTableEntity(outputResult.EngagementAccount, outputResult.MessageId, outputResult.DeliveryResponse.CustomMessageId); await ReportInProgressTableEntity.InsertOrMergeAsync(reportInProgressTable, inProgressEntity); } }
public async Task OnMessageSentAsync(InputMessage message, EmailMessageInfoExtension extension) { // Create record in history table var historyTable = await GetHistoryTableAsync(message.MessageInfo.EngagementAccount); if (historyTable == null) { // Create the table in case any issue in account initialize historyTable = await GetHistoryTableAsync(message.MessageInfo.EngagementAccount, true); } var history = new MessageHistoryTableEntity(message, extension); await MessageHistoryTableEntity.InsertOrMergeAsync(historyTable, history); // Create record in audit table var audit = new MessageAuditTableEntity(history); await MessageAuditTableEntity.InsertOrMergeAsync(auditTable, audit); }
public async Task <bool> OnReportUpdatedAsync(string engagementAccount, Report report) { try { // Get record in in-progress table var inProgressEntity = await ReportInProgressTableEntity.GetAsync(reportInProgressTable, engagementAccount, report.MessageIdentifer.MessageId); if (inProgressEntity == null) { // Record should be already in history table var historyTable = await GetHistoryTableAsync(engagementAccount); var historyEntity = await MessageHistoryTableEntity.GetAsync(historyTable, engagementAccount, report.MessageIdentifer.MessageId); if (historyEntity == null) { EmailProviderEventSource.Current.Warning(EmailProviderEventSource.EmptyTrackingId, this, nameof(this.OnReportUpdatedAsync), OperationStates.Dropped, $"Does not find record for messageId={report.MessageIdentifer.MessageId}"); return(false); } // TODO: if after 24h we get new number of target shall we charge? historyEntity.Targets = report.TotalTarget; historyEntity.Delivered = report.TotalDelivered; historyEntity.Opened = report.TotalOpened; historyEntity.Clicked = report.TotalClicked; historyEntity.LastUpdateTime = DateTime.UtcNow; await MessageHistoryTableEntity.InsertOrMergeAsync(historyTable, historyEntity); return(true); } var lastTarget = inProgressEntity.Targets; // Update the record in in-progress table inProgressEntity.Targets = report.TotalTarget; inProgressEntity.Delivered = report.TotalDelivered; inProgressEntity.Opened = report.TotalOpened; inProgressEntity.Clicked = report.TotalClicked; inProgressEntity.LastUpdateTime = DateTime.UtcNow; var updated = await ReportInProgressTableEntity.TryUpdateAsync(reportInProgressTable, inProgressEntity); // New target sent, do the charge (only if update succeed) if (updated && lastTarget < report.TotalTarget) { try { var delta = report.TotalTarget - lastTarget; // Get account detail var account = await this.store.GetAccountAsync(engagementAccount); metricManager.LogDeliverSuccess(delta, engagementAccount, account?.SubscriptionId ?? string.Empty); var usage = new ResourceUsageRecord(); usage.EngagementAccount = engagementAccount; usage.UsageType = ResourceUsageType.EmailMessage; usage.Quantity = delta; await this.billingAgent.StoreBillingUsageAsync(new List <ResourceUsageRecord> { usage }, CancellationToken.None); EmailProviderEventSource.Current.Info(EmailProviderEventSource.EmptyTrackingId, this, nameof(this.OnReportUpdatedAsync), OperationStates.Succeeded, $"Usage pushed to billing service account={engagementAccount} quantity={usage.Quantity}"); } catch (Exception ex) { // We should monitor for billing failure EmailProviderEventSource.Current.CriticalException(EmailProviderEventSource.EmptyTrackingId, this, nameof(this.OnReportUpdatedAsync), OperationStates.Failed, $"Failed at pushing to billing service account={engagementAccount}", ex); } } // If the record in in-progress for 24h, treat it as completed and move it to history table if (inProgressEntity.Timestamp.AddHours(Constants.ReportInProgressIntervalByHours) < DateTime.UtcNow) { // Record should be already in history table var historyTable = await GetHistoryTableAsync(engagementAccount); var historyEntity = new MessageHistoryTableEntity(inProgressEntity); await MessageHistoryTableEntity.InsertOrMergeAsync(historyTable, historyEntity); await ReportInProgressTableEntity.DeleteAsync(reportInProgressTable, inProgressEntity); } return(true); } catch (Exception ex) { EmailProviderEventSource.Current.ErrorException(EmailProviderEventSource.EmptyTrackingId, this, nameof(this.OnReportUpdatedAsync), OperationStates.Failed, string.Empty, ex); return(false); } }