public async Task IgnoresIfExistingMessageTypeDifferent(MessageType existingType)
            {
                var type      = (MessageType)99;
                var component = new TestComponent("component");

                var existingMessage = new MessageEntity(EventEntity, Time, "existing", existingType);

                Table
                .Setup(x => x.RetrieveAsync <MessageEntity>(MessageEntity.GetRowKey(EventEntity, Time)))
                .ReturnsAsync(existingMessage)
                .Verifiable();

                await Factory.UpdateMessageAsync(EventEntity, Time, type, component);

                Table.Verify();

                Table
                .Verify(
                    x => x.ReplaceAsync(It.IsAny <MessageEntity>()),
                    Times.Never());

                Builder
                .Verify(
                    x => x.Build(It.IsAny <MessageType>(), It.IsAny <IComponent>(), It.IsAny <ComponentStatus>()),
                    Times.Never());
            }
Beispiel #2
0
        public async Task UpdateMessageAsync(EventEntity eventEntity, DateTime time, MessageType type, IComponent component)
        {
            using (_logger.Scope("Updating existing message of type {Type} for event {EventRowKey} at {Timestamp} affecting {ComponentPath}.",
                                 type, eventEntity.RowKey, time, component.Path))
            {
                var existingMessage = await _table.RetrieveAsync <MessageEntity>(MessageEntity.GetRowKey(eventEntity, time));

                if (existingMessage == null)
                {
                    _logger.LogWarning("Cannot update message that doesn't exist.");
                    return;
                }

                var existingMessageType = (MessageType)existingMessage.Type;
                if (existingMessageType != type)
                {
                    if (existingMessageType == MessageType.Manual)
                    {
                        _logger.LogInformation("Message was changed manually, cannot update.");
                    }
                    else
                    {
                        _logger.LogWarning("Cannot update message, has unexpected type {UnexpectedType}.", existingMessageType);
                    }

                    return;
                }

                var newContents = _builder.Build(type, component);
                _logger.LogInformation("Replacing contents of message with time {MessageTimestamp} and contents {OldMessageContents} with {NewMessageContents}.",
                                       existingMessage.Time, existingMessage.Contents, newContents);
                existingMessage.Contents = newContents;
                await _table.ReplaceAsync(existingMessage);
            }
        }
            public async Task ReplacesMessage(MessageType type)
            {
                var component = new TestComponent("component");

                var contents = "new message";

                Builder
                .Setup(x => x.Build(type, component))
                .Returns(contents);

                var message = new MessageEntity(EventEntity, Time, "existing", type);

                Table
                .Setup(x => x.RetrieveAsync <MessageEntity>(MessageEntity.GetRowKey(EventEntity, Time)))
                .ReturnsAsync(message)
                .Verifiable();

                Table
                .Setup(x => x.ReplaceAsync(message))
                .Returns(Task.CompletedTask)
                .Verifiable();

                await Factory.UpdateMessageAsync(EventEntity, Time, type, component);

                Assert.Equal(EventEntity.RowKey, message.ParentRowKey);
                Assert.Equal(Time, message.Time);
                Assert.Equal(contents, message.Contents);

                Table.Verify();
            }
            public async Task SavesNewMessageAndUpdatesEventIfNecessary(bool eventIsActive, bool shouldEventBeActive)
            {
                var eventStartTime = new DateTime(2018, 8, 19);
                var entity         = new AddStatusMessageManualChangeEntity("path", eventStartTime, "message", shouldEventBeActive)
                {
                    Timestamp = new DateTimeOffset(2018, 8, 21, 0, 0, 0, TimeSpan.Zero)
                };

                var time           = entity.Timestamp.UtcDateTime;
                var existingEntity =
                    new EventEntity(
                        entity.EventAffectedComponentPath,
                        eventStartTime,
                        ComponentStatus.Up,
                        eventIsActive ? (DateTime?)null : new DateTime(2018, 8, 20));

                var eventRowKey = existingEntity.RowKey;

                _table
                .Setup(x => x.RetrieveAsync <EventEntity>(eventRowKey))
                .Returns(Task.FromResult(existingEntity));

                _table
                .Setup(x => x.InsertAsync(It.IsAny <MessageEntity>()))
                .Returns(Task.CompletedTask);

                _table
                .Setup(x => x.ReplaceAsync(It.IsAny <EventEntity>()))
                .Returns(Task.CompletedTask);

                await _handler.Handle(entity);

                _table
                .Verify(
                    x => x.InsertAsync(
                        It.Is <MessageEntity>(message =>
                                              message.PartitionKey == MessageEntity.DefaultPartitionKey &&
                                              message.RowKey == MessageEntity.GetRowKey(eventRowKey, time) &&
                                              message.ParentRowKey == eventRowKey &&
                                              message.Time == time &&
                                              message.Contents == entity.MessageContents
                                              )),
                    Times.Once());

                var shouldEventBeUpdated = ManualStatusChangeUtility.ShouldEventBeActive(existingEntity, shouldEventBeActive, time);

                _table
                .Verify(
                    x => x.InsertAsync(
                        It.Is <EventEntity>(eventEntity =>
                                            eventEntity.PartitionKey == EventEntity.DefaultPartitionKey &&
                                            eventEntity.RowKey == eventRowKey &&
                                            eventEntity.AffectedComponentPath == existingEntity.AffectedComponentPath &&
                                            eventEntity.AffectedComponentStatus == existingEntity.AffectedComponentStatus &&
                                            eventEntity.StartTime == time
                                            )),
                    shouldEventBeUpdated ? Times.Once() : Times.Never());
            }
        public async Task Handle(DeleteStatusMessageManualChangeEntity entity)
        {
            var eventRowKey   = EventEntity.GetRowKey(entity.EventAffectedComponentPath, entity.EventStartTime);
            var messageEntity = await _table.RetrieveAsync <MessageEntity>(MessageEntity.GetRowKey(eventRowKey, entity.MessageTimestamp));

            if (messageEntity == null)
            {
                throw new ArgumentException("Cannot delete a message that does not exist.");
            }

            messageEntity.Contents = "";
            messageEntity.Type     = (int)MessageType.Manual;

            await _table.ReplaceAsync(messageEntity);
        }
            public async Task CreatesNewMessage()
            {
                var type            = (MessageType)99;
                var status          = (ComponentStatus)100;
                var componentStatus = (ComponentStatus)101;
                var component       = new TestComponent("component")
                {
                    Status = componentStatus
                };

                var expectedStatus = GetExpectedStatus(component, status);

                var contents = "new message";

                Builder
                .Setup(x => x.Build(type, component, expectedStatus))
                .Returns(contents);

                Table
                .Setup(x => x.RetrieveAsync <MessageEntity>(MessageEntity.GetRowKey(EventEntity, Time)))
                .ReturnsAsync((MessageEntity)null)
                .Verifiable();

                Table
                .Setup(x => x.InsertAsync(It.IsAny <MessageEntity>()))
                .Callback <ITableEntity>(entity =>
                {
                    var message = entity as MessageEntity;
                    Assert.NotNull(message);
                    Assert.Equal(EventEntity.RowKey, message.ParentRowKey);
                    Assert.Equal(Time, message.Time);
                    Assert.Equal(contents, message.Contents);
                })
                .Returns(Task.CompletedTask)
                .Verifiable();

                await InvokeMethod(
                    EventEntity,
                    Time,
                    type,
                    component,
                    status);

                Table.Verify();
            }
            public async Task EditsMessage(MessageType type)
            {
                var entity = new EditStatusMessageManualChangeEntity("path", new DateTime(2018, 8, 20), new DateTime(2018, 8, 21), "message");

                var eventRowKey   = EventEntity.GetRowKey(entity.EventAffectedComponentPath, entity.EventStartTime);
                var messageRowKey = MessageEntity.GetRowKey(eventRowKey, entity.MessageTimestamp);

                var existingEntity =
                    new EventEntity(
                        entity.EventAffectedComponentPath,
                        entity.EventStartTime,
                        ComponentStatus.Up,
                        null);

                _table
                .Setup(x => x.RetrieveAsync <EventEntity>(eventRowKey))
                .Returns(Task.FromResult(existingEntity));

                var existingMessage = new MessageEntity(
                    existingEntity,
                    entity.MessageTimestamp,
                    "old message",
                    type);

                _table
                .Setup(x => x.RetrieveAsync <MessageEntity>(messageRowKey))
                .Returns(Task.FromResult(existingMessage));

                _table
                .Setup(x => x.ReplaceAsync(
                           It.Is <MessageEntity>(messageEntity =>
                                                 messageEntity.PartitionKey == MessageEntity.DefaultPartitionKey &&
                                                 messageEntity.RowKey == messageRowKey &&
                                                 messageEntity.ParentRowKey == eventRowKey &&
                                                 messageEntity.Time == existingMessage.Time &&
                                                 messageEntity.Contents == entity.MessageContents &&
                                                 messageEntity.Type == (int)MessageType.Manual
                                                 )))
                .Returns(Task.CompletedTask)
                .Verifiable();

                await _handler.Handle(entity);

                _table.Verify();
            }
Beispiel #8
0
        public async Task CreateMessageAsync(EventEntity eventEntity, DateTime time, MessageType type, IComponent component, ComponentStatus status)
        {
            using (_logger.Scope("Creating new message of type {Type} for event {EventRowKey} at {Timestamp} affecting {ComponentPath} with status {ComponentStatus}.",
                                 type, eventEntity.RowKey, time, component.Path, status))
            {
                var existingMessage = await _table.RetrieveAsync <MessageEntity>(MessageEntity.GetRowKey(eventEntity, time));

                if (existingMessage != null)
                {
                    _logger.LogInformation("Message already exists, will not recreate.");
                    return;
                }

                var contents      = _builder.Build(type, component, status);
                var messageEntity = new MessageEntity(eventEntity, time, contents, type);
                _logger.LogInformation("Creating message with time {MessageTimestamp} and contents {MessageContents}.",
                                       messageEntity.Time, messageEntity.Contents);
                await _table.InsertAsync(messageEntity);
            }
        }
            public async Task IgnoresIfMessageDoesNotExist()
            {
                var type      = (MessageType)99;
                var component = new TestComponent("component");

                Table
                .Setup(x => x.RetrieveAsync <MessageEntity>(MessageEntity.GetRowKey(EventEntity, Time)))
                .ReturnsAsync((MessageEntity)null);

                await Factory.UpdateMessageAsync(EventEntity, Time, type, component);

                Table
                .Verify(
                    x => x.ReplaceAsync(It.IsAny <MessageEntity>()),
                    Times.Never());

                Builder
                .Verify(
                    x => x.Build(It.IsAny <MessageType>(), It.IsAny <IComponent>(), It.IsAny <ComponentStatus>()),
                    Times.Never());
            }
Beispiel #10
0
            public async Task SavesMessageAndEvent(bool eventIsActive)
            {
                var entity = new AddStatusEventManualChangeEntity("path", ComponentStatus.Up, "message", eventIsActive)
                {
                    Timestamp = new DateTimeOffset(2018, 8, 21, 0, 0, 0, TimeSpan.Zero)
                };

                var time        = entity.Timestamp.UtcDateTime;
                var eventRowKey = EventEntity.GetRowKey(entity.EventAffectedComponentPath, time);

                _table.Setup(x => x.InsertAsync(
                                 It.Is <MessageEntity>(messageEntity =>
                                                       messageEntity.PartitionKey == MessageEntity.DefaultPartitionKey &&
                                                       messageEntity.RowKey == MessageEntity.GetRowKey(eventRowKey, time) &&
                                                       messageEntity.ParentRowKey == eventRowKey &&
                                                       messageEntity.Time == time &&
                                                       messageEntity.Contents == entity.MessageContents
                                                       )))
                .Returns(Task.CompletedTask)
                .Verifiable();

                _table.Setup(x => x.InsertAsync(
                                 It.Is <EventEntity>(eventEntity =>
                                                     eventEntity.PartitionKey == EventEntity.DefaultPartitionKey &&
                                                     eventEntity.RowKey == eventRowKey &&
                                                     eventEntity.AffectedComponentPath == entity.EventAffectedComponentPath &&
                                                     eventEntity.AffectedComponentStatus == entity.EventAffectedComponentStatus &&
                                                     eventEntity.StartTime == time &&
                                                     eventEntity.EndTime == (entity.EventIsActive ? (DateTime?)null : time)
                                                     )))
                .Returns(Task.CompletedTask)
                .Verifiable();

                await _handler.Handle(entity);

                _table.Verify();
            }
            public async Task ReturnsExistingMessage()
            {
                var type            = (MessageType)99;
                var status          = (ComponentStatus)100;
                var componentStatus = (ComponentStatus)101;
                var component       = new TestComponent("component")
                {
                    Status = componentStatus
                };

                var existingMessage = new MessageEntity(EventEntity, Time, "existing", (MessageType)98);

                Table
                .Setup(x => x.RetrieveAsync <MessageEntity>(MessageEntity.GetRowKey(EventEntity, Time)))
                .ReturnsAsync(existingMessage)
                .Verifiable();

                await InvokeMethod(
                    EventEntity,
                    Time,
                    type,
                    component,
                    status);

                Table.Verify();

                Table
                .Verify(
                    x => x.InsertAsync(It.IsAny <MessageEntity>()),
                    Times.Never());

                Builder
                .Verify(
                    x => x.Build(It.IsAny <MessageType>(), It.IsAny <IComponent>(), It.IsAny <ComponentStatus>()),
                    Times.Never());
            }
            public async Task ThrowsArgumentExceptionIfMissingMessage()
            {
                var entity = new EditStatusMessageManualChangeEntity("path", new DateTime(2018, 8, 20), new DateTime(2018, 8, 21), "message");

                var eventRowKey   = EventEntity.GetRowKey(entity.EventAffectedComponentPath, entity.EventStartTime);
                var messageRowKey = MessageEntity.GetRowKey(eventRowKey, entity.MessageTimestamp);

                var existingEntity =
                    new EventEntity(
                        entity.EventAffectedComponentPath,
                        entity.EventStartTime,
                        ComponentStatus.Up,
                        null);

                _table
                .Setup(x => x.RetrieveAsync <EventEntity>(eventRowKey))
                .Returns(Task.FromResult(existingEntity));

                _table
                .Setup(x => x.RetrieveAsync <MessageEntity>(messageRowKey))
                .Returns(Task.FromResult <MessageEntity>(null));

                await Assert.ThrowsAsync <ArgumentException>(() => _handler.Handle(entity));
            }