public async Task WhenIAskTheUserNotificationStoreForNotificationsForTheUserWithId(int itemCount, string userId, string resultName)
        {
            IUserNotificationStore store  = this.serviceProvider.GetRequiredService <IUserNotificationStore>();
            GetNotificationsResult result = await store.GetAsync(userId, null, itemCount).ConfigureAwait(false);

            this.scenarioContext.Set(result, resultName);
        }
        public void ThenTheGetNotificationsResultShouldContainAContinuationToken(string resultName)
        {
            GetNotificationsResult result = this.scenarioContext.Get <GetNotificationsResult>(resultName);

            Assert.IsNotNull(result.ContinuationToken);
            Assert.IsNotEmpty(result.ContinuationToken);
        }
Beispiel #3
0
            public async Task GetNotifications_ProcessAsync(int seqid, TProtocol iprot, TProtocol oprot, CancellationToken cancellationToken)
            {
                var args = new GetNotificationsArgs();
                await args.ReadAsync(iprot, cancellationToken);

                await iprot.ReadMessageEndAsync(cancellationToken);

                var result = new GetNotificationsResult();

                try
                {
                    result.Success = await _iAsync.GetNotificationsAsync(cancellationToken);

                    await oprot.WriteMessageBeginAsync(new TMessage("GetNotifications", TMessageType.Reply, seqid), cancellationToken);

                    await result.WriteAsync(oprot, cancellationToken);
                }
                catch (TTransportException)
                {
                    throw;
                }
                catch (Exception ex)
                {
                    Console.Error.WriteLine("Error occurred in processor:");
                    Console.Error.WriteLine(ex.ToString());
                    var x = new TApplicationException(TApplicationException.ExceptionType.InternalError, " Internal error.");
                    await oprot.WriteMessageBeginAsync(new TMessage("GetNotifications", TMessageType.Exception, seqid), cancellationToken);

                    await x.WriteAsync(oprot, cancellationToken);
                }
                await oprot.WriteMessageEndAsync(cancellationToken);

                await oprot.Transport.FlushAsync(cancellationToken);
            }
Beispiel #4
0
            public async Task <string> GetNotificationsAsync(CancellationToken cancellationToken)
            {
                await OutputProtocol.WriteMessageBeginAsync(new TMessage("GetNotifications", TMessageType.Call, SeqId), cancellationToken);

                var args = new GetNotificationsArgs();

                await args.WriteAsync(OutputProtocol, cancellationToken);

                await OutputProtocol.WriteMessageEndAsync(cancellationToken);

                await OutputProtocol.Transport.FlushAsync(cancellationToken);

                var msg = await InputProtocol.ReadMessageBeginAsync(cancellationToken);

                if (msg.Type == TMessageType.Exception)
                {
                    var x = await TApplicationException.ReadAsync(InputProtocol, cancellationToken);

                    await InputProtocol.ReadMessageEndAsync(cancellationToken);

                    throw x;
                }

                var result = new GetNotificationsResult();
                await result.ReadAsync(InputProtocol, cancellationToken);

                await InputProtocol.ReadMessageEndAsync(cancellationToken);

                if (result.__isset.success)
                {
                    return(result.Success);
                }
                throw new TApplicationException(TApplicationException.ExceptionType.MissingResult, "GetNotifications failed: unknown result");
            }
        public Task ThenWithinSecondsTheFirstNotificationsStoredInTheTransientTenantForTheUserWithIdHaveTheDeliveryStatusForTheDeliveryChannelWithId(
            int timeoutSeconds,
            int count,
            string userId,
            UserNotificationDeliveryStatus expectedDeliveryStatus,
            string deliveryChannelId)
        {
            var tokenSource = new CancellationTokenSource();

            tokenSource.CancelAfter(TimeSpan.FromSeconds(timeoutSeconds));

            return(Retriable.RetryAsync(
                       async() =>
            {
                GetNotificationsResult userNotifications = await this.GetNotificationsForUserAsync(userId, count).ConfigureAwait(false);

                foreach (UserNotification current in userNotifications.Results)
                {
                    if (current.GetDeliveryStatusForChannel(deliveryChannelId) != expectedDeliveryStatus)
                    {
                        throw new Exception($"Notification with Id '{current.Id}' has delivery status '{current.GetDeliveryStatusForChannel(deliveryChannelId)}' instead of expected value '{expectedDeliveryStatus}'");
                    }
                }
            },
                       tokenSource.Token,
                       new Linear(TimeSpan.FromSeconds(5), int.MaxValue),
                       new AnyExceptionPolicy(),
                       false));
        }
        public async Task <OpenApiResult> GetNotificationsForUserAsync(
            IOpenApiContext context,
            string userId,
            string?sinceNotificationId,
            int?maxItems,
            string?continuationToken)
        {
            // We can guarantee tenant Id is available because it's part of the Uri.
            ITenant tenant = await this.marainServicesTenancy.GetRequestingTenantAsync(context.CurrentTenantId !).ConfigureAwait(false);

            IUserNotificationStore userNotificationStore =
                await this.userNotificationStoreFactory.GetUserNotificationStoreForTenantAsync(tenant).ConfigureAwait(false);

            maxItems ??= 50;

            GetNotificationsResult results = await this.GetNotificationsAsync(
                userId,
                sinceNotificationId,
                maxItems.Value,
                continuationToken,
                userNotificationStore).ConfigureAwait(false);

            await this.EnsureAllNotificationsMarkedAsDelivered(context, results).ConfigureAwait(false);

            HalDocument result = await this.userNotificationsMapper.MapAsync(
                results,
                new UserNotificationsMappingContext(context, userId, sinceNotificationId, maxItems.Value, continuationToken)).ConfigureAwait(false);

            return(this.OkResult(result));
        }
        public async Task WhenIAskTheUserNotificationStoreForNotificationsUsingTheContinuationTokenFromTheResultCalledAndCallTheResult(string userId, string previousResultName, string newResultName)
        {
            IUserNotificationStore store          = this.serviceProvider.GetRequiredService <IUserNotificationStore>();
            GetNotificationsResult previousResult = this.scenarioContext.Get <GetNotificationsResult>(previousResultName);
            GetNotificationsResult result         = await store.GetAsync(userId, previousResult.ContinuationToken !).ConfigureAwait(false);

            this.scenarioContext.Set(result, newResultName);
        }
        public async Task WhenIAskTheUserNotificationStoreForNotificationsSinceTheFirstNotificationInTheResultsCalledForTheUserWithIdAndCallTheResult(int itemCount, string previousResultName, string userId, string newResultName)
        {
            IUserNotificationStore store          = this.serviceProvider.GetRequiredService <IUserNotificationStore>();
            GetNotificationsResult previousResult = this.scenarioContext.Get <GetNotificationsResult>(previousResultName);
            GetNotificationsResult result         = await store.GetAsync(userId, previousResult.Results[0].Id, itemCount).ConfigureAwait(false);

            this.scenarioContext.Set(result, newResultName);
        }
        public void ThenTheGetNotificationsResultCalledShouldOnlyContainNotificationsWithAnEarlierTimestampThanThoseInTheGetNotificationsResult(string earlierResultsName, string laterResultsName)
        {
            GetNotificationsResult earlierResults = this.scenarioContext.Get <GetNotificationsResult>(earlierResultsName);
            GetNotificationsResult laterResults   = this.scenarioContext.Get <GetNotificationsResult>(laterResultsName);

            int overlapCount = earlierResults.Results.Count(e => laterResults.Results.Any(l => l.Timestamp < e.Timestamp));

            Assert.AreEqual(0, overlapCount);
        }
        public void ThenTheGetNotificationsResultsCalledAndShouldNotContainAnyOfTheSameNotifications(string resultsName1, string resultsName2)
        {
            GetNotificationsResult results1 = this.scenarioContext.Get <GetNotificationsResult>(resultsName1);
            GetNotificationsResult results2 = this.scenarioContext.Get <GetNotificationsResult>(resultsName2);

            int overlapCount = results1.Results.Count(r1 => results2.Results.Any(r2 => r2.Id == r1.Id));

            Assert.AreEqual(0, overlapCount);
        }
        public void ThenTheGetNotificationsResultCalledShouldContainNotificationsInDescendingOrderOfTimestamp(string resultName)
        {
            GetNotificationsResult result = this.scenarioContext.Get <GetNotificationsResult>(resultName);

            result.Results.ForEachAtIndex((n, i) =>
            {
                if (i != 0)
                {
                    Assert.GreaterOrEqual(result.Results[i - 1].Timestamp, n.Timestamp);
                }
            });
        }
        public async Task ThenTheFirstNotificationsStoredInTheTransientTenantForTheUserWithIdHaveTheDeliveryStatusForTheDeliveryChannelWithId(
            int count,
            string userId,
            UserNotificationReadStatus expectedReadStatus,
            string deliveryChannelId)
        {
            GetNotificationsResult userNotifications = await this.GetNotificationsForUserAsync(userId, count).ConfigureAwait(false);

            foreach (UserNotification current in userNotifications.Results)
            {
                Assert.AreEqual(expectedReadStatus, current.GetReadStatusForChannel(deliveryChannelId));
            }
        }
        public async Task ThenTheFirstNotificationsStoredInTheTransientTenantForTheUserWithIdHaveTheReadStatusLastUpdatedSetToWithinSecondsOfNow(
            int count,
            string userId,
            int allowableTimeRangeFromNow,
            string deliveryChannelId)
        {
            GetNotificationsResult userNotifications = await this.GetNotificationsForUserAsync(userId, count).ConfigureAwait(false);

            var timeRange = TimeSpan.FromSeconds(allowableTimeRangeFromNow);

            foreach (UserNotification current in userNotifications.Results)
            {
                UserNotificationStatus status = current.ChannelStatuses.Single(x => x.DeliveryChannelId == deliveryChannelId);
                Assert.LessOrEqual(DateTimeOffset.UtcNow - status.ReadStatusLastUpdated, timeRange);
            }
        }
        public void ThenTheGetNotificationsResultShouldContainNotifications(string resultName, int expectedNotificationCount)
        {
            GetNotificationsResult result = this.scenarioContext.Get <GetNotificationsResult>(resultName);

            Assert.AreEqual(expectedNotificationCount, result.Results.Length);
        }
        private async Task EnsureAllNotificationsMarkedAsDelivered(IOpenApiContext context, GetNotificationsResult results)
        {
            // See if there are any notifications we need to mark as delivered. Whilst we want this to happen, we're
            // not going to fail the entire request operation if something goes wrong - hence the catch-all exception handler.
            try
            {
                IEnumerable <UserNotification> notificationsToMarkAsDelivered = results.Results.Where(
                    x => x.GetDeliveryStatusForChannel(Constants.ApiDeliveryChannelId) != UserNotificationDeliveryStatus.Delivered);

                if (notificationsToMarkAsDelivered.Any())
                {
                    this.logger.LogDebug($"Updating notification state to 'Delivered' for {notificationsToMarkAsDelivered.Count()} notifications.");

                    DateTimeOffset timestamp = DateTimeOffset.UtcNow;
                    IEnumerable <BatchDeliveryStatusUpdateRequestItem> deliveryStatusUpdateBatch = notificationsToMarkAsDelivered.Select(
                        n =>
                        new BatchDeliveryStatusUpdateRequestItem
                    {
                        NotificationId    = n.Id,
                        NewStatus         = UpdateNotificationDeliveryStatusRequestNewStatus.Delivered,
                        UpdateTimestamp   = timestamp,
                        DeliveryChannelId = Constants.ApiDeliveryChannelId,
                    });

                    // Although this call returns the location for the long running op it kicks off, we don't really
                    // care. We're going to return the notifications as "delivered" anyway (because the fact that
                    // we're returning them means they are delivered). So we'll send this request and hope that it
                    // succeeds, safe in the knowledge that if it doesn't, we're logging the failure.
                    ApiResponse response = await this.managementApiClient.BatchDeliveryStatusUpdateAsync(
                        context.CurrentTenantId,
                        deliveryStatusUpdateBatch,
                        CancellationToken.None).ConfigureAwait(false);

                    this.logger.LogInformation(
                        $"Sent request to update notification delivery status; long running operation Url is {response.Headers["Location"]}");
                }
            }
            catch (Exception ex)
            {
                this.logger.LogWarning(ex, "Unable to update notification delivery state");
                this.exceptionsInstrumentation.ReportException(ex);
            }
        }