public async Task DistributeScheduledAsync(UserEventMessage userEvent, bool isLastAttempt) { await userNotificationsStore.TrackAttemptAsync(userEvent); try { var user = await userStore.GetCachedAsync(userEvent.AppId, userEvent.UserId); if (user == null) { throw new DomainException(Texts.Notification_NoApp); } var app = await appStore.GetCachedAsync(userEvent.AppId, default); if (app == null) { throw new DomainException(Texts.Notification_NoUser); } var(notification, targets) = await CreateUserNotificationAsync(userEvent, user, app); try { await userNotificationsStore.InsertAsync(notification); } catch (UniqueConstraintException) { throw new DomainException(Texts.Notification_AlreadyProcessed); } foreach (var channel in targets) { if (notification.Settings.TryGetValue(channel.Name, out var preference)) { await channel.SendAsync(notification, preference, user, app, false); } } } catch (Exception ex) { if (isLastAttempt) { await userNotificationsStore.TrackFailedAsync(userEvent); } if (ex is DomainException domainException) { await logStore.LogAsync(userEvent.AppId, domainException.Message); } else { throw; } } }
public async Task DistributeScheduledAsync(UserEventMessage userEvent, bool isLastAttempt) { var links = userEvent.Links(); var parentContext = Activity.Current?.Context ?? default; using (var activity = Telemetry.Activities.StartActivity("DistributeUserEventScheduled", ActivityKind.Internal, parentContext, links: links)) { await userNotificationsStore.TrackAttemptAsync(userEvent); try { var user = await userStore.GetCachedAsync(userEvent.AppId, userEvent.UserId); if (user == null) { throw new DomainException(Texts.Notification_NoApp); } var app = await appStore.GetCachedAsync(userEvent.AppId); if (app == null) { throw new DomainException(Texts.Notification_NoUser); } var options = new SendOptions { App = app, User = user }; var notification = await CreateUserNotificationAsync(userEvent, options); notification.NotificationActivity = activity?.Context ?? default; try { await userNotificationsStore.InsertAsync(notification); } catch (UniqueConstraintException) { throw new DomainException(Texts.Notification_AlreadyProcessed); } foreach (var channel in channels) { if (notification.Channels.TryGetValue(channel.Name, out var notificationChannel)) { foreach (var configuration in notificationChannel.Status.Keys) { await channel.SendAsync(notification, notificationChannel.Setting, configuration, options, default); } } } log.LogInformation("Processed user event for app {appId} with ID {id} to topic {topic}.", userEvent.AppId, userEvent.EventId, userEvent.Topic); } catch (Exception ex) { if (isLastAttempt) { await userNotificationsStore.TrackFailedAsync(userEvent); } if (ex is DomainException domainException) { await logStore.LogAsync(userEvent.AppId, domainException.Message); } else { log.LogError(ex, "Failed to process user event for app {appId} with ID {id} to topic {topic}.", userEvent.AppId, userEvent.EventId, userEvent.Topic); throw; } } } }