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;
                }
            }
        }
Example #2
0
        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;
                    }
                }
            }
        }