Пример #1
0
        public void TestEnqueueDequeue()
        {
            TimeSpan         timeout = TimeSpan.FromMilliseconds(1.0);
            AsyncQueue <int> queue   = new AsyncQueue <int>();

            queue.Enqueue(1);
            queue.EnqueueRange(new int[] { 2, 3 });
            Assert.AreEqual(1, queue.TryDequeueAsync(timeout).Sync().Value);
            Assert.AreEqual(2, queue.TryDequeueAsync(timeout).Sync().Value);
            Assert.AreEqual(3, queue.TryDequeueAsync(timeout).Sync().Value);
        }
Пример #2
0
        public async Task Preserve_Order()
        {
            var queue = new AsyncQueue <string>();

            queue.Enqueue("1");
            queue.Enqueue("2");
            queue.Enqueue("3");

            Assert.AreEqual("1", (await queue.TryDequeueAsync(CancellationToken.None)).Item);
            Assert.AreEqual("2", (await queue.TryDequeueAsync(CancellationToken.None)).Item);
            Assert.AreEqual("3", (await queue.TryDequeueAsync(CancellationToken.None)).Item);
        }
Пример #3
0
        public async Task Should_be_notified_about_changed_database_stats()
        {
            using (var database = CreateDocumentDatabase())
            {
                database.NotificationCenter.Options.DatabaseStatsThrottle = TimeSpan.FromMilliseconds(100);

                var actions = new AsyncQueue <DynamicJsonValue>();
                var writer  = new TestWebSocketWriter();

                using (database.NotificationCenter.TrackActions(actions, writer))
                {
                    var notification = await actions.TryDequeueAsync(TimeSpan.FromMilliseconds(5000));

                    Assert.True(notification.Item1);

                    using (database.DocumentsStorage.ContextPool.AllocateOperationContext(out DocumentsOperationContext context))
                        using (var doc = context.ReadObject(new DynamicJsonValue
                        {
                            ["Foo"] = "Bar",
                            [Constants.Documents.Metadata.Key] = new DynamicJsonValue
                            {
                                [Constants.Documents.Metadata.Collection] = "Foos"
                            }
                        }, ""))
                        {
                            using (var tx = context.OpenWriteTransaction())
                            {
                                database.DocumentsStorage.Put(context, "foo/bar", null, doc);
                                tx.Commit();
                            }
                        }

                    notification = await actions.TryDequeueAsync(TimeSpan.FromMilliseconds(500));

                    Assert.True(notification.Item1);

                    var databaseStatsChanged = notification.Item2;

                    Assert.NotNull(databaseStatsChanged);

                    Assert.Equal(1L, databaseStatsChanged[nameof(DatabaseStatsChanged.CountOfDocuments)]);
                    Assert.Equal(0L, databaseStatsChanged[nameof(DatabaseStatsChanged.CountOfIndexes)]);
                    Assert.Equal(0L, databaseStatsChanged[nameof(DatabaseStatsChanged.CountOfStaleIndexes)]);
                    var collections = (databaseStatsChanged[nameof(DatabaseStatsChanged.ModifiedCollections)] as DynamicJsonArray);
                    Assert.Equal(1L, collections.Count);
                    Assert.Equal("Foos", (collections.First() as DynamicJsonValue)["Name"]);
                }
            }
        }
Пример #4
0
        async Task ProcessReceivedPublishPackets(CancellationToken cancellationToken)
        {
            while (!cancellationToken.IsCancellationRequested)
            {
                try
                {
                    var publishPacketDequeueResult = await _publishPacketReceiverQueue.TryDequeueAsync(cancellationToken).ConfigureAwait(false);

                    if (!publishPacketDequeueResult.IsSuccess)
                    {
                        return;
                    }

                    var publishPacket = publishPacketDequeueResult.Item;
                    var eventArgs     = await HandleReceivedApplicationMessageAsync(publishPacket).ConfigureAwait(false);

                    if (eventArgs.AutoAcknowledge)
                    {
                        await eventArgs.AcknowledgeAsync(cancellationToken).ConfigureAwait(false);
                    }
                }
                catch (OperationCanceledException)
                {
                }
                catch (Exception exception)
                {
                    _logger.Error(exception, "Error while handling application message.");
                }
            }
        }
Пример #5
0
        private async Task <DynamicJsonValue> GetNextMessage(bool throttleConnection)
        {
            while (true)
            {
                var nextMessage = await _sendQueue.TryDequeueAsync(TimeSpan.FromSeconds(5));

                if (nextMessage.Item1 == false)
                {
                    var dynamicJsonValue = _skippedMessage;
                    _skippedMessage = null;
                    return(dynamicJsonValue);
                }
                var msg = nextMessage.Item2;
                if (throttleConnection && msg.AllowSkip)
                {
                    if (DateTime.UtcNow - _lastSendMessage < TimeSpan.FromSeconds(5))
                    {
                        _skippedMessage = msg.ValueToSend;
                        continue;
                    }
                }
                _skippedMessage  = null;
                _lastSendMessage = DateTime.UtcNow;
                return(msg.ValueToSend);
            }
        }
Пример #6
0
        public async Task Preserve_ProcessAsync()
        {
            var queue = new AsyncQueue <int>();

            var sum    = 0;
            var worker = Task.Run(async() =>
            {
                while (sum < 6)
                {
                    sum += (await queue.TryDequeueAsync(CancellationToken.None)).Item;
                }
            });

            queue.Enqueue(1);
            await Task.Delay(500);

            queue.Enqueue(2);
            await Task.Delay(500);

            queue.Enqueue(3);
            await Task.Delay(500);

            Assert.AreEqual(6, sum);
            Assert.AreEqual(TaskStatus.RanToCompletion, worker.Status);
        }
Пример #7
0
        public async Task AggregatesTransformationErrorsInSingleAlert()
        {
            using (var src = GetDocumentStore())
                using (var dest = GetDocumentStore())
                {
                    AddEtl(src, dest, "Users", script: @"throw 'super exception';
                                       loadToUsers(this);");

                    var database = await GetDatabase(src.Database);

                    var notifications = new AsyncQueue <DynamicJsonValue>();
                    using (database.NotificationCenter.TrackActions(notifications, null))
                    {
                        for (int i = 0; i < 3; i++)
                        {
                            using (var session = src.OpenSession())
                            {
                                session.Store(new User()
                                {
                                    Name = "Joe Doe"
                                }, $"users/{i}");

                                session.SaveChanges();
                            }

                            // let's ignore notification that's triggered by document put (DatabaseStatsChanged)

                            DynamicJsonValue alert = null;

                            for (int attempt = 0; attempt < 2; attempt++)
                            {
                                var notification = await notifications.TryDequeueAsync(TimeSpan.FromSeconds(30));

                                Assert.True(notification.Item1);

                                if (notification.Item2[nameof(Notification.Type)].ToString() == NotificationType.AlertRaised.ToString())
                                {
                                    alert = notification.Item2;
                                }
                            }

                            Assert.NotNull(alert);

                            var details = (DynamicJsonValue)alert[nameof(AlertRaised.Details)];
                            var errors  = (DynamicJsonArray)details[nameof(EtlErrorsDetails.Errors)];

                            Assert.Equal(i + 1, errors.Items.Count);

                            for (int j = 0; j < i + 1; j++)
                            {
                                var error = (DynamicJsonValue)errors.Items.ToArray()[j];

                                Assert.Equal($"users/{j}", error[nameof(EtlErrorInfo.DocumentId)]);
                                Assert.Contains("super exception", error[nameof(EtlErrorInfo.Error)].ToString());
                                Assert.NotNull(error[nameof(EtlErrorInfo.Date)]);
                            }
                        }
                    }
                }
        }
Пример #8
0
        public async Task ShouldCreateLowDiskSpaceAlert()
        {
            UseNewLocalServer();

            using (var store = GetDocumentStore(new Options()
            {
                Path = NewDataPath()
            }))
            {
                var database = await GetDatabase(store.Database);

                var serverStore = database.ServerStore;

                serverStore.StorageSpaceMonitor.SimulateLowDiskSpace = true;

                var notifications = new AsyncQueue <DynamicJsonValue>();
                using (serverStore.NotificationCenter.TrackActions(notifications, null))
                {
                    serverStore.StorageSpaceMonitor.Run(null);

                    var notification = await notifications.TryDequeueAsync(TimeSpan.FromSeconds(30));

                    Assert.True(notification.Item1);

                    Assert.Equal(AlertType.LowDiskSpace, notification.Item2[nameof(AlertRaised.AlertType)]);
                }
            }
        }
Пример #9
0
        public async Task Process_Async_With_Initial_Delay()
        {
            var queue = new AsyncQueue <int>();

            var sum    = 0;
            var worker = Task.Run(async() =>
            {
                while (sum < 6)
                {
                    sum += (await queue.TryDequeueAsync(CancellationToken.None)).Item;
                }
            });

            // This line is the diff to test _Process_Async_
            await Task.Delay(500);

            queue.Enqueue(1);
            await Task.Delay(500);

            queue.Enqueue(2);
            await Task.Delay(500);

            queue.Enqueue(3);
            await Task.Delay(500);

            Assert.AreEqual(6, sum);
            Assert.AreEqual(TaskStatus.RanToCompletion, worker.Status);
        }
        private async Task TryProcessNextQueuedApplicationMessageAsync(CancellationToken cancellationToken)
        {
            try
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    return;
                }

                var dequeueResult = await _messageQueue.TryDequeueAsync(cancellationToken).ConfigureAwait(false);

                var queuedApplicationMessage = dequeueResult.Item;

                var sender             = queuedApplicationMessage.Sender;
                var applicationMessage = queuedApplicationMessage.ApplicationMessage;

                var interceptorContext = await InterceptApplicationMessageAsync(sender, applicationMessage).ConfigureAwait(false);

                if (interceptorContext != null)
                {
                    if (interceptorContext.CloseConnection)
                    {
                        if (sender != null)
                        {
                            await sender.StopAsync().ConfigureAwait(false);
                        }
                    }

                    if (interceptorContext.ApplicationMessage == null || !interceptorContext.AcceptPublish)
                    {
                        return;
                    }

                    applicationMessage = interceptorContext.ApplicationMessage;
                }

                await _eventDispatcher.HandleApplicationMessageReceivedAsync(sender?.ClientId, applicationMessage).ConfigureAwait(false);

                if (applicationMessage.Retain)
                {
                    await _retainedMessagesManager.HandleMessageAsync(sender?.ClientId, applicationMessage).ConfigureAwait(false);
                }

                foreach (var clientSession in _sessions.Values)
                {
                    clientSession.EnqueueApplicationMessage(
                        applicationMessage,
                        sender?.ClientId,
                        false);
                }
            }
            catch (OperationCanceledException)
            {
            }
            catch (Exception exception)
            {
                _logger.Error(exception, "Unhandled exception while processing next queued application message.");
            }
        }
Пример #11
0
        async Task ProcessReceivedPublishPackets(CancellationToken cancellationToken)
        {
            while (!cancellationToken.IsCancellationRequested)
            {
                try
                {
                    var publishPacketDequeueResult = await _publishPacketReceiverQueue.TryDequeueAsync(cancellationToken).ConfigureAwait(false);

                    if (!publishPacketDequeueResult.IsSuccess)
                    {
                        return;
                    }

                    var publishPacket = publishPacketDequeueResult.Item;

                    if (publishPacket.QualityOfServiceLevel == MqttQualityOfServiceLevel.AtMostOnce)
                    {
                        await HandleReceivedApplicationMessageAsync(publishPacket).ConfigureAwait(false);
                    }
                    else if (publishPacket.QualityOfServiceLevel == MqttQualityOfServiceLevel.AtLeastOnce)
                    {
                        var eventArgs = await HandleReceivedApplicationMessageAsync(publishPacket).ConfigureAwait(false);

                        if (!eventArgs.ProcessingFailed)
                        {
                            await SendAsync(new MqttPubAckPacket
                            {
                                PacketIdentifier = publishPacket.PacketIdentifier,
                                ReasonCode       = (MqttPubAckReasonCode)eventArgs.ReasonCode
                            }, cancellationToken).ConfigureAwait(false);
                        }
                    }
                    else if (publishPacket.QualityOfServiceLevel == MqttQualityOfServiceLevel.ExactlyOnce)
                    {
                        var eventArgs = await HandleReceivedApplicationMessageAsync(publishPacket).ConfigureAwait(false);

                        if (!eventArgs.ProcessingFailed)
                        {
                            await SendAsync(new MqttPubRecPacket
                            {
                                PacketIdentifier = publishPacket.PacketIdentifier,
                                ReasonCode       = (MqttPubRecReasonCode)eventArgs.ReasonCode
                            }, cancellationToken).ConfigureAwait(false);
                        }
                    }
                    else
                    {
                        throw new MqttProtocolViolationException("Received a not supported QoS level.");
                    }
                }
                catch (OperationCanceledException)
                {
                }
                catch (Exception exception)
                {
                    _logger.Error(exception, "Error while handling application message.");
                }
            }
        }
Пример #12
0
        private static async Task <DynamicJsonValue> GetAlert(AsyncQueue <DynamicJsonValue> notifications)
        {
            var notification = await notifications.TryDequeueAsync(TimeSpan.FromSeconds(30));

            Assert.True(notification.Item1);

            return(notification.Item2);
        }
        public async Task <MqttQueuedApplicationMessage> DequeueAsync(CancellationToken cancellationToken)
        {
            var dequeueResult = await _messageQueue.TryDequeueAsync(cancellationToken).ConfigureAwait(false);

            if (!dequeueResult.IsSuccess)
            {
                return(null);
            }

            return(dequeueResult.Item);
        }
Пример #14
0
        public async Task Cancellation()
        {
            var queue = new AsyncQueue <int>();

            bool success;

            using (var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(3)))
            {
                success = (await queue.TryDequeueAsync(cancellationTokenSource.Token)).IsSuccess;
            }

            Assert.AreEqual(false, success);
        }
Пример #15
0
        public async Task WriteNotifications(Func <string, bool> shouldWriteByDb)
        {
            var receiveBuffer = new ArraySegment <byte>(new byte[1024]);
            var receive       = _webSocket.ReceiveAsync(receiveBuffer, _resourceShutdown);

            var asyncQueue = new AsyncQueue <DynamicJsonValue>();

            try
            {
                var sp = shouldWriteByDb == null ? null : Stopwatch.StartNew();
                using (_notificationsBase.TrackActions(asyncQueue, this))
                {
                    while (_resourceShutdown.IsCancellationRequested == false)
                    {
                        // we use this to detect client-initialized closure
                        if (receive.IsCompleted)
                        {
                            break;
                        }

                        var tuple = await asyncQueue.TryDequeueAsync(TimeSpan.FromSeconds(5));

                        if (tuple.Item1 == false)
                        {
                            await SendHeartbeat();

                            continue;
                        }

                        if (shouldWriteByDb != null &&
                            shouldWriteByDb((string)tuple.Item2["Database"]) == false)
                        {
                            if (sp.ElapsedMilliseconds > 5000)
                            {
                                sp.Restart();
                                await SendHeartbeat();
                            }

                            continue;
                        }

                        await WriteToWebSocket(tuple.Item2);
                    }
                }
            }
            catch (OperationCanceledException)
            {
            }
        }
Пример #16
0
        public async Task Duplicated_notification_should_not_arrive_before_postponed_until_date()
        {
            using (var database = CreateDocumentDatabase())
            {
                database.NotificationCenter.Options.DatabaseStatsThrottle = TimeSpan.MaxValue;

                var alert = GetSampleAlert();
                database.NotificationCenter.Add(alert);

                database.NotificationCenter.Postpone(alert.Id, SystemTime.UtcNow.AddDays(1));

                var actions = new AsyncQueue <DynamicJsonValue>();
                var writer  = new TestWebSocketWriter();

                using (database.NotificationCenter.TrackActions(actions, writer))
                {
                    database.NotificationCenter.Add(alert);
                    Assert.False((await actions.TryDequeueAsync(TimeSpan.FromMilliseconds(10))).Item1);

                    database.NotificationCenter.Add(alert);
                    Assert.False((await actions.TryDequeueAsync(TimeSpan.FromMilliseconds(10))).Item1);
                }
            }
        }
Пример #17
0
        public async Task WriteNotifications(Func <string, bool> shouldWriteByDb, Action firstTime = null)
        {
            var receiveBuffer = new ArraySegment <byte>(new byte[1024]);
            var receive       = _webSocket.ReceiveAsync(receiveBuffer, _resourceShutdown);

            var asyncQueue = new AsyncQueue <DynamicJsonValue>();

            try
            {
                using (_notificationsBase.TrackActions(asyncQueue, this))
                {
                    firstTime?.Invoke();
                    while (_resourceShutdown.IsCancellationRequested == false)
                    {
                        // we use this to detect client-initialized closure
                        if (receive.IsCompleted)
                        {
                            break;
                        }

                        var tuple = await asyncQueue.TryDequeueAsync(TimeSpan.FromSeconds(5));

                        if (tuple.Item1 == false)
                        {
                            await _webSocket.SendAsync(WebSocketHelper.Heartbeat, WebSocketMessageType.Text, true, _resourceShutdown);

                            continue;
                        }

                        if (shouldWriteByDb != null &&
                            shouldWriteByDb((string)tuple.Item2["Database"]) == false)
                        {
                            continue;
                        }

                        await WriteToWebSocket(tuple.Item2);
                    }
                }
            }
            catch (OperationCanceledException)
            {
            }
        }
Пример #18
0
        public async Task GetChanges()
        {
            var heartbeat = new ArraySegment <byte>(new[] { (byte)'\r', (byte)'\n' });
            var ms        = new MemoryStream();

            using (var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync())
            {
                var asyncQueue = new AsyncQueue <GlobalAlertNotification>();

                using (ServerStore.TrackChanges(asyncQueue))
                {
                    while (ServerStore.ServerShutdown.IsCancellationRequested == false)
                    {
                        var tuple = await asyncQueue.TryDequeueAsync(TimeSpan.FromSeconds(5));

                        if (tuple.Item1 == false)
                        {
                            await
                            webSocket.SendAsync(heartbeat, WebSocketMessageType.Text, true,
                                                ServerStore.ServerShutdown);

                            continue;
                        }

                        ms.SetLength(0);

                        JsonOperationContext context;
                        using (ServerStore.ContextPool.AllocateOperationContext(out context))
                            using (var writer = new BlittableJsonTextWriter(context, ms))
                            {
                                context.Write(writer, tuple.Item2.ToJson());
                            }

                        ArraySegment <byte> bytes;
                        ms.TryGetBuffer(out bytes);

                        await webSocket.SendAsync(bytes, WebSocketMessageType.Text, true, ServerStore.ServerShutdown);
                    }
                }
            }
        }
Пример #19
0
        public void TestMultipleThreads()
        {
            AsyncQueue <int> queue              = new AsyncQueue <int>();
            int                     count       = 0;
            List <Task>             tasks       = new List <Task>();
            CancellationTokenSource cancelToken = new CancellationTokenSource();

            for (int i = 0; i < 10; i++)
            {
                Task task = Task.Run(async() =>
                {
                    int value;
                    try
                    {
                        while ((value = (await queue.TryDequeueAsync(cancelToken.Token)).Value) > 0)
                        {
                            Interlocked.Add(ref count, value);
                        }
                    }
                    catch (OperationCanceledException)
                    {
                    }
                });
                tasks.Add(task);
            }

            for (int i = 1; i <= 1000; i++)
            {
                queue.Enqueue(i);
            }

            for (int i = 0; i < 10 && count != 1000; i++)
            {
                Thread.Sleep(100);
            }

            cancelToken.Cancel();
            Assert.IsTrue(Task.WhenAll(tasks.ToArray()).Wait(1000));
            Assert.AreEqual(500500, count); // sum of 1 to 1000
        }
Пример #20
0
        public async Task WriteNotifications(Func <string, bool> shouldWriteByDb)
        {
            var receiveBuffer = new ArraySegment <byte>(new byte[1024]);
            var receive       = _webSocket.ReceiveAsync(receiveBuffer, _resourceShutdown);

            var asyncQueue = new AsyncQueue <DynamicJsonValue>();

            try
            {
                using (_notificationsBase.TrackActions(asyncQueue, this, shouldWriteByDb))
                {
                    AfterTrackActionsRegistration?.Invoke();

                    while (_resourceShutdown.IsCancellationRequested == false)
                    {
                        // we use this to detect client-initialized closure
                        if (receive.IsCompleted)
                        {
                            break;
                        }

                        var tuple = await asyncQueue.TryDequeueAsync(TimeSpan.FromSeconds(5));

                        if (tuple.Item1 == false)
                        {
                            await SendHeartbeat();

                            continue;
                        }

                        await WriteToWebSocket(tuple.Item2);
                    }
                }
            }
            catch (OperationCanceledException)
            {
            }
        }
Пример #21
0
        public async Task WriteNotifications()
        {
            var receiveBuffer = new ArraySegment <byte>(new byte[1024]);
            var receive       = _webSocket.ReceiveAsync(receiveBuffer, _resourceShutdown);

            var asyncQueue = new AsyncQueue <Notification>();

            try
            {
                using (_notificationCenter.TrackActions(asyncQueue, this))
                {
                    while (_resourceShutdown.IsCancellationRequested == false)
                    {
                        // we use this to detect client-initialized closure
                        if (receive.IsCompleted)
                        {
                            break;
                        }

                        var tuple = await asyncQueue.TryDequeueAsync(TimeSpan.FromSeconds(5));

                        if (tuple.Item1 == false)
                        {
                            await _webSocket.SendAsync(WebSocketHelper.Heartbeat, WebSocketMessageType.Text, true, _resourceShutdown);

                            continue;
                        }

                        await WriteToWebSocket(tuple.Item2.ToJson());
                    }
                }
            }
            catch (OperationCanceledException)
            {
            }
        }
Пример #22
0
        public async Task Should_create_performance_hint_notification_when_exceeding_max_index_outputs()
        {
            var index      = new UsersAndFriendsIndex();
            var definition = index.CreateIndexDefinition();

            using (var store = GetDocumentStore())
            {
                var db = await GetDatabase(store.Database);

                db.Configuration.PerformanceHints.MaxWarnIndexOutputsPerDocument = 2;

                using (var session = store.OpenSession())
                {
                    var user1 = new User
                    {
                        Name    = "user/1",
                        Friends = new List <User>
                        {
                            new User {
                                Name = "friend/1/1"
                            },
                            new User {
                                Name = "friend/1/2"
                            }
                        }
                    };

                    var user2 = new User
                    {
                        Name    = "user/2",
                        Friends = new List <User>
                        {
                            new User {
                                Name = "friend/2/1"
                            },
                            new User {
                                Name = "friend/2/2"
                            },
                            new User {
                                Name = "friend/2/3"
                            }
                        }
                    };

                    var user3 = new User
                    {
                        Name    = "user/3",
                        Friends = new List <User>
                        {
                            new User {
                                Name = "friend/3/1"
                            }
                        }
                    };

                    session.Store(user1);
                    session.Store(user2);
                    session.Store(user3);

                    session.SaveChanges();
                }

                var notificationsQueue = new AsyncQueue <DynamicJsonValue>();
                using (db.NotificationCenter.TrackActions(notificationsQueue, null))
                {
                    definition.Name = index.IndexName;
                    store.Maintenance.Send(new PutIndexesOperation(new[] { definition }));

                    Indexes.WaitForIndexing(store);

                    // we might have other notifications like StatsChanged
                    Assert.True(WaitForValue(() => notificationsQueue.Count > 0, true, interval: 100));

                    Tuple <bool, DynamicJsonValue> performanceHint;

                    do
                    {
                        performanceHint = await notificationsQueue.TryDequeueAsync(TimeSpan.Zero);
                    } while (performanceHint.Item2["Type"].ToString() != NotificationType.PerformanceHint.ToString());

                    Assert.NotNull(performanceHint.Item2);

                    Assert.Equal("Number of map results produced by an index exceeds the performance hint configuration key (MaxIndexOutputsPerDocument).",
                                 performanceHint.Item2[nameof(PerformanceHint.Message)]);

                    Assert.Equal(PerformanceHintType.Indexing, performanceHint.Item2[nameof(PerformanceHint.HintType)]);

                    var details = performanceHint.Item2[nameof(PerformanceHint.Details)] as DynamicJsonValue;
                    Assert.NotNull(details);

                    var warnings = details[nameof(WarnIndexOutputsPerDocument.Warnings)] as DynamicJsonValue;
                    Assert.NotNull(warnings);

                    Assert.Contains(warnings.Properties.ToArray()[0].Name, "UsersAndFriends");
                    var indexWarningsArray = (warnings["UsersAndFriends"] as DynamicJsonArray).ToArray();

                    var indexWarning = indexWarningsArray[0] as DynamicJsonValue;

                    var numberOfExceedingDocs = indexWarning[nameof(WarnIndexOutputsPerDocument.WarningDetails.NumberOfExceedingDocuments)];
                    var numberOfOutputsPerDoc = indexWarning[nameof(WarnIndexOutputsPerDocument.WarningDetails.MaxNumberOutputsPerDocument)];
                    var sampleDoc             = indexWarning[nameof(WarnIndexOutputsPerDocument.WarningDetails.SampleDocumentId)];

                    Assert.Equal(1L, numberOfExceedingDocs);
                    Assert.Equal(3, numberOfOutputsPerDoc);
                    Assert.Equal("users/2-A", sampleDoc);
                }

                Assert.Equal(3, WaitForValue(() =>
                {
                    var indexStats = store.Maintenance.Send(new GetIndexStatisticsOperation(index.IndexName));
                    return(indexStats.MaxNumberOfOutputsPerDocument);
                }, 3));
            }
        }
Пример #23
0
        public async Task Should_create_performance_hint_notification_when_exceeding_max_index_outputs()
        {
            var index      = new UsersAndFriendsIndex();
            var definition = index.CreateIndexDefinition();

            using (var store = GetDocumentStore())
            {
                var db = await GetDatabase(store.Database);

                db.Configuration.PerformanceHints.MaxWarnIndexOutputsPerDocument = 2;

                using (var session = store.OpenSession())
                {
                    var user1 = new User
                    {
                        Name    = "user/1",
                        Friends = new List <User>
                        {
                            new User {
                                Name = "friend/1/1"
                            },
                            new User {
                                Name = "friend/1/2"
                            }
                        }
                    };

                    var user2 = new User
                    {
                        Name    = "user/2",
                        Friends = new List <User>
                        {
                            new User {
                                Name = "friend/2/1"
                            },
                            new User {
                                Name = "friend/2/2"
                            },
                            new User {
                                Name = "friend/2/3"
                            }
                        }
                    };

                    var user3 = new User
                    {
                        Name    = "user/3",
                        Friends = new List <User>
                        {
                            new User {
                                Name = "friend/3/1"
                            }
                        }
                    };

                    session.Store(user1);
                    session.Store(user2);
                    session.Store(user3);

                    session.SaveChanges();
                }

                var notificationsQueue = new AsyncQueue <DynamicJsonValue>();
                using (db.NotificationCenter.TrackActions(notificationsQueue, null))
                {
                    definition.Name = index.IndexName;
                    store.Maintenance.Send(new PutIndexesOperation(new[] { definition }));

                    WaitForIndexing(store);

                    // we might have other notifications like StatsChanged
                    Assert.True(notificationsQueue.Count > 0);

                    Tuple <bool, DynamicJsonValue> performanceHint;

                    do
                    {
                        performanceHint = await notificationsQueue.TryDequeueAsync(TimeSpan.Zero);
                    } while (performanceHint.Item2["Type"].ToString() != NotificationType.PerformanceHint.ToString());

                    Assert.NotNull(performanceHint.Item2);
                    Assert.Equal("Index 'UsersAndFriends' has produced more than 2 map results from a single document", performanceHint.Item2[nameof(PerformanceHint.Message)]);
                    Assert.Equal("UsersAndFriends", performanceHint.Item2[nameof(PerformanceHint.Source)]);
                    Assert.Equal(PerformanceHintType.Indexing, performanceHint.Item2[nameof(PerformanceHint.HintType)]);

                    var details = performanceHint.Item2[nameof(PerformanceHint.Details)] as DynamicJsonValue;

                    Assert.NotNull(details);
                    Assert.Equal(1L, details[nameof(WarnIndexOutputsPerDocument.NumberOfExceedingDocuments)]);
                    Assert.Equal(3, details[nameof(WarnIndexOutputsPerDocument.MaxNumberOutputsPerDocument)]);
                    Assert.Equal("users/2-a", details[nameof(WarnIndexOutputsPerDocument.SampleDocumentId)]);
                }

                var indexStats = store.Maintenance.Send(new GetIndexStatisticsOperation(index.IndexName));

                Assert.Equal(3, indexStats.MaxNumberOfOutputsPerDocument);
            }
        }
Пример #24
0
        public async Task Should_unload_db_and_send_notification_on_catastrophic_failure()
        {
            UseNewLocalServer();
            using (var store = GetDocumentStore())
            {
                var notifications = new AsyncQueue <DynamicJsonValue>();

                using (Server.ServerStore.NotificationCenter.TrackActions(notifications, null))
                {
                    var database = await GetDatabase(store.Database);

                    Assert.Equal(1, Server.ServerStore.DatabasesLandlord.DatabasesCache.Count());

                    try
                    {
                        throw new Exception("Catastrophy");
                    }
                    catch (Exception e)
                    {
                        database.GetAllStoragesEnvironment().First().Environment.Options.SetCatastrophicFailure(ExceptionDispatchInfo.Capture(e));
                    }

                    var ex = Assert.Throws <Exception>(() =>
                    {
                        using (var context = DocumentsOperationContext.ShortTermSingleUse(database))
                        {
                            using (var tx = context.OpenWriteTransaction())
                            {
                                var dynamicJsonValue = new DynamicJsonValue();
                                using (var doc = context.ReadObject(dynamicJsonValue, "users/1", BlittableJsonDocumentBuilder.UsageMode.ToDisk))
                                {
                                    database.DocumentsStorage.Put(context, "users/1", null, doc);
                                }

                                tx.Commit();
                            }
                        }
                    });

                    Assert.Equal("Catastrophy", ex.Message);

                    // db unloaded
                    Assert.True(SpinWait.SpinUntil(() => Server.ServerStore.DatabasesLandlord.DatabasesCache.Any() == false, TimeSpan.FromMinutes(1)));

                    Tuple <bool, DynamicJsonValue> alert;
                    do
                    {
                        alert = await notifications.TryDequeueAsync(TimeSpan.Zero);
                    } while (alert.Item2["Type"].ToString() != NotificationType.AlertRaised.ToString());


                    Assert.Equal(AlertType.CatastrophicDatabaseFailure, alert.Item2[nameof(AlertRaised.AlertType)]);
                    Assert.Contains(database.Name, alert.Item2[nameof(AlertRaised.Title)] as string);
                }

                using (var session = store.OpenSession())
                {
                    session.Store(new User());

                    session.SaveChanges();
                }

                // db loaded again
                Assert.Equal(1, Server.ServerStore.DatabasesLandlord.DatabasesCache.Count());
            }
        }
Пример #25
0
        public async Task Should_create_performance_hint_notification_when_exceeding_max_number_of_LoadDocument_calls_per_reference()
        {
            using (var store = GetDocumentStore())
            {
                var db = await GetDatabase(store.Database);

                db.Configuration.PerformanceHints.MaxNumberOfLoadsPerReference = 10;

                db.NotificationCenter.Indexing.MinUpdateInterval = TimeSpan.MinValue;

                var index = new Products_ByCategory();

                using (var session = store.OpenSession())
                {
                    session.Store(new Category {
                        Id = "categories/0", Name = "foo"
                    });
                    session.Store(new Category {
                        Id = "categories/1", Name = "bar"
                    });

                    for (int i = 0; i < 200; i++)
                    {
                        session.Store(new Product {
                            Category = $"categories/{i % 2}"
                        });
                    }

                    session.SaveChanges();
                }

                await index.ExecuteAsync(store);

                Indexes.WaitForIndexing(store);

                var notificationsQueue = new AsyncQueue <DynamicJsonValue>();

                using (db.NotificationCenter.TrackActions(notificationsQueue, null))
                {
                    using (var session = store.OpenSession())
                    {
                        session.Store(new Category {
                            Id = "categories/0", Name = "abc"
                        });

                        session.SaveChanges();
                    }

                    Indexes.WaitForIndexing(store);

                    Tuple <bool, DynamicJsonValue> performanceHint;

                    do
                    {
                        performanceHint = await notificationsQueue.TryDequeueAsync(TimeSpan.FromSeconds(5));
                    } while (performanceHint.Item2["Type"].ToString() != NotificationType.PerformanceHint.ToString());

                    Assert.NotNull(performanceHint.Item2);

                    Assert.Equal("We have detected high number of LoadDocument() / LoadCompareExchangeValue() calls per single reference item. The update of a reference will result in reindexing all documents that reference it. Please see Indexing Performance graph to check the performance of your indexes.",
                                 performanceHint.Item2[nameof(PerformanceHint.Message)]);

                    Assert.Equal(PerformanceHintType.Indexing_References, performanceHint.Item2[nameof(PerformanceHint.HintType)]);

                    var details = performanceHint.Item2[nameof(PerformanceHint.Details)] as DynamicJsonValue;

                    Assert.NotNull(details);

                    using (var ctx = JsonOperationContext.ShortTermSingleUse())
                    {
                        var json = ctx.ReadObject(details, "foo");

                        var detailsObject = DocumentConventions.DefaultForServer.Serialization.DefaultConverter.FromBlittable <IndexingReferenceLoadWarning>(json, "bar");

                        Assert.Contains("Products/ByCategory", detailsObject.Warnings.Keys);
                        Assert.Equal(1, detailsObject.Warnings.Count);

                        var top10LoadedReferences = detailsObject.Warnings["Products/ByCategory"].Top10LoadedReferences;

                        Assert.Equal(1, top10LoadedReferences.Count);
                        Assert.Equal("categories/0", top10LoadedReferences["categories/0"].ReferenceId);
                        Assert.Equal(100, top10LoadedReferences["categories/0"].NumberOfLoads);
                    }

                    // update of the hint

                    using (var session = store.OpenSession())
                    {
                        session.Store(new Category {
                            Id = "categories/1", Name = "def"
                        });

                        session.SaveChanges();
                    }

                    Indexes.WaitForIndexing(store);

                    db.NotificationCenter.Indexing.UpdateIndexing(null);

                    do
                    {
                        performanceHint = await notificationsQueue.TryDequeueAsync(TimeSpan.FromSeconds(5));
                    } while (performanceHint.Item2["Type"].ToString() != NotificationType.PerformanceHint.ToString());

                    details = performanceHint.Item2[nameof(PerformanceHint.Details)] as DynamicJsonValue;

                    Assert.NotNull(details);

                    using (var ctx = JsonOperationContext.ShortTermSingleUse())
                    {
                        var json = ctx.ReadObject(details, "foo");

                        var detailsObject = DocumentConventions.DefaultForServer.Serialization.DefaultConverter.FromBlittable <IndexingReferenceLoadWarning>(json, "bar");


                        Assert.Contains("Products/ByCategory", detailsObject.Warnings.Keys);
                        Assert.Equal(1, detailsObject.Warnings.Count);

                        var top10LoadedReferences = detailsObject.Warnings["Products/ByCategory"].Top10LoadedReferences;

                        Assert.Equal(2, top10LoadedReferences.Count);

                        Assert.Equal("categories/0", top10LoadedReferences["categories/0"].ReferenceId);
                        Assert.Equal(100, top10LoadedReferences["categories/0"].NumberOfLoads);


                        Assert.Equal("categories/1", top10LoadedReferences["categories/1"].ReferenceId);
                        Assert.Equal(100, top10LoadedReferences["categories/1"].NumberOfLoads);
                    }
                }
            }
        }
Пример #26
0
        async Task TryProcessNextQueuedApplicationMessageAsync(CancellationToken cancellationToken)
        {
            try
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    return;
                }

                var dequeueResult = await _messageQueue.TryDequeueAsync(cancellationToken).ConfigureAwait(false);

                if (!dequeueResult.IsSuccess)
                {
                    return;
                }

                var queuedApplicationMessage = dequeueResult.Item;

                var sender             = queuedApplicationMessage.Sender;
                var applicationMessage = queuedApplicationMessage.ApplicationMessage;

                var interceptorContext = await InterceptApplicationMessageAsync(sender, applicationMessage).ConfigureAwait(false);

                if (interceptorContext != null)
                {
                    if (interceptorContext.CloseConnection)
                    {
                        if (sender != null)
                        {
                            await sender.StopAsync().ConfigureAwait(false);
                        }
                    }

                    if (interceptorContext.ApplicationMessage == null || !interceptorContext.AcceptPublish)
                    {
                        return;
                    }

                    applicationMessage = interceptorContext.ApplicationMessage;
                }

                await _eventDispatcher.SafeNotifyApplicationMessageReceivedAsync(sender?.ClientId, applicationMessage).ConfigureAwait(false);

                if (applicationMessage.Retain)
                {
                    await _retainedMessagesManager.HandleMessageAsync(sender?.ClientId, applicationMessage).ConfigureAwait(false);
                }

                var deliveryCount = 0;

                foreach (var clientSession in _sessions.Values)
                {
                    var isSubscribed = clientSession.EnqueueApplicationMessage(
                        applicationMessage,
                        sender?.ClientId,
                        false);

                    if (isSubscribed)
                    {
                        deliveryCount++;
                    }
                }

                if (deliveryCount == 0)
                {
                    var undeliveredMessageInterceptor = _options.UndeliveredMessageInterceptor;

                    if (undeliveredMessageInterceptor == null)
                    {
                        return;
                    }

                    await undeliveredMessageInterceptor.InterceptApplicationMessagePublishAsync(new MqttApplicationMessageInterceptorContext(sender?.ClientId, sender?.Session?.Items, applicationMessage));
                }
            }
            catch (OperationCanceledException)
            {
            }
            catch (Exception exception)
            {
                _logger.Error(exception, "Unhandled exception while processing next queued application message.");
            }
        }