public Task <ProcessedMessageStatus> HandleMessageAsync(MotorCloudEvent <InputMessage> dataCloudEvent, CancellationToken token = default)
    {
        var msg = dataCloudEvent?.TypedData;

        Console.WriteLine(msg);
        return(Task.FromResult(ProcessedMessageStatus.Success));
    }
        public async Task StartAsync_CreateSpanAsReference_ContextIsReferenced()
        {
            PrepareQueues();

            var host    = GetReverseStringService();
            var channel = _fixture.Connection.CreateModel();

            await CreateQueueForServicePublisherWithPublisherBindingFromConfig(channel);

            await host.StartAsync();

            var extensions     = new List <ICloudEventExtension>();
            var randomActivity = CreateRandomActivity();
            var distributedTracingExtension = new DistributedTracingExtension();

            distributedTracingExtension.SetActivity(randomActivity);
            extensions.Add(distributedTracingExtension);
            var motorCloudEvent = MotorCloudEvent.CreateTestCloudEvent(new byte[0], extensions: extensions);

            await PublishMessageIntoQueueOfService(channel, "12345", motorCloudEvent);

            var ctx = await GetActivityContextFromDestinationQueue(channel);

            Assert.Equal(randomActivity.Context.TraceId, ctx.TraceId);
            Assert.NotEqual(randomActivity.Context.SpanId, ctx.SpanId);
            await host.StopAsync();
        }
示例#3
0
    public async Task PublishMessageAsync_WithConfig_BasicPropertiesAreSet()
    {
        var basicProperties = Mock.Of <IBasicProperties>();
        var modelMock       = new Mock <IModel>();

        modelMock.Setup(x => x.CreateBasicProperties()).Returns(basicProperties);
        var rabbitConnectionFactoryMock =
            GetDefaultConnectionFactoryMock <string>(modelMock: modelMock, basicProperties: basicProperties);

        var        publisher = GetPublisher(rabbitConnectionFactoryMock.Object, GetConfig());
        const byte priority  = 1;

        var activity = new Activity(nameof(RabbitMQMessagePublisherTests));

        activity.SetIdFormat(ActivityIdFormat.W3C);
        activity.Start();

        var motorCloudEvent = MotorCloudEvent.CreateTestCloudEvent(Array.Empty <byte>());

        motorCloudEvent.SetActivity(activity);
        motorCloudEvent.SetRabbitMQPriority(priority);

        await publisher.PublishMessageAsync(motorCloudEvent);

        Assert.Equal(2, basicProperties.DeliveryMode);
        Assert.Equal(priority, basicProperties.Priority);
        var traceparent = Encoding.UTF8.GetString((byte[])basicProperties.Headers[
                                                      $"{BasicPropertiesExtensions.CloudEventPrefix}{DistributedTracingExtension.TraceParentAttribute.Name}"]);
        var activityContext = ActivityContext.Parse(traceparent, null);

        Assert.Equal(activity.Context.TraceId, activityContext.TraceId);
        Assert.Equal(activity.Context.SpanId, activityContext.SpanId);
        Assert.Equal(activity.Context.TraceFlags, activityContext.TraceFlags);
    }
            public async Task <MotorCloudEvent <string> > ConvertMessageAsync(MotorCloudEvent <string> dataCloudEvent,
                                                                              CancellationToken token = default)
            {
                await Task.Delay(Timeout.InfiniteTimeSpan, token);

                return(dataCloudEvent);
            }
示例#5
0
    private async Task <ProcessedMessageStatus> SingleMessageConsumeAsync(MotorCloudEvent <byte[]> dataCloudEvent,
                                                                          CancellationToken token)
    {
        try
        {
            byte[] decoded;
            using (new AutoObserveStopwatch(() => _messageDecoding))
            {
                decoded = await DecodeMessageAsync(
                    dataCloudEvent.GetEncoding(), dataCloudEvent.TypedData, token);
            }

            TInput deserialized;
            using (new AutoObserveStopwatch(() => _messageDeserialization))
            {
                deserialized = _deserializer.Deserialize(decoded);
            }

            return(await _queue
                   .QueueBackgroundWorkItem(dataCloudEvent.CreateNew(deserialized, true))
                   .ConfigureAwait(true));
        }
        catch (ArgumentException e)
        {
            _logger.LogError(LogEvents.InvalidInput, e, "Invalid Input");
            return(ProcessedMessageStatus.InvalidInput);
        }
        catch (Exception e)
        {
            _logger.LogError(LogEvents.UnexpectedErrorOnMessageProcessing, e, "Invalid Input");
            return(ProcessedMessageStatus.CriticalFailure);
        }
    }
示例#6
0
 public static Version?GetMotorVersion <TData>(this MotorCloudEvent <TData> cloudEvent) where TData : class
 {
     return(CloudEventValidation.CheckNotNull(cloudEvent, nameof(cloudEvent))[MotorVersionAttribute]
            is not string versionString
         ? null
         : System.Version.Parse(versionString));
 }
    public void UpdateAndExtractCloudEvent_V0_6_0Header_ExtensionsAddedToCloudEvent()
    {
        var channel                      = _fixture.Connection.CreateModel();
        var basicProperties              = channel.CreateBasicProperties();
        var publisherOptions             = new RabbitMQPublisherOptions <byte[]>();
        var content                      = new byte[] { 1, 2, 3 };
        var inputCloudEvent              = MotorCloudEvent.CreateTestCloudEvent(content);
        var mockedApplicationNameService = Mock.Of <IApplicationNameService>();

        basicProperties.SetPriority(inputCloudEvent, publisherOptions);
        basicProperties.WriteCloudEventIntoHeader(inputCloudEvent);
        // manipulate basic properties to simulate outdated version
        basicProperties.Headers.Remove($"{BasicPropertiesExtensions.CloudEventPrefix}{MotorVersionExtension.MotorVersionAttribute.Name}");
        basicProperties.ContentEncoding = null;
        basicProperties.Headers.Add(
            $"{BasicPropertiesExtensions.CloudEventPrefix}{CloudEventsSpecVersion.V1_0.DataContentTypeAttribute.Name}",
            Encoding.UTF8.GetBytes($"{basicProperties.ContentType}"));
        foreach (var(key, value) in basicProperties.Headers)
        {
            if (value is byte[] byteValue)
            {
                basicProperties.Headers[key] = EscapeWithQuotes(byteValue);
            }
        }

        var outputCloudEvent = basicProperties.ExtractCloudEvent(mockedApplicationNameService,
                                                                 new ReadOnlyMemory <byte>(content));

        Assert.Equal(MotorCloudEventInfo.RequiredAttributes(Version.Parse("0.6.0.0")).Count(),
                     outputCloudEvent.GetPopulatedAttributes().Count());
        foreach (var requiredAttribute in MotorCloudEventInfo.RequiredAttributes(Version.Parse("0.6.0.0")))
        {
            Assert.Equal(inputCloudEvent[requiredAttribute], outputCloudEvent[requiredAttribute]);
        }
    }
 public static MotorCloudEvent <TData> SetEncoding <TData>(this MotorCloudEvent <TData> cloudEvent, string?value)
     where TData : class
 {
     Validation.CheckNotNull(cloudEvent, nameof(cloudEvent));
     cloudEvent[EncodingAttribute] = value;
     return(cloudEvent);
 }
        public static void Update <T>(this IBasicProperties self, MotorCloudEvent <byte[]> cloudEvent,
                                      RabbitMQPublisherConfig <T> config, ICloudEventFormatter cloudEventFormatter)
        {
            var messagePriority = cloudEvent.Extension <RabbitMQPriorityExtension>()?.Priority ??
                                  config.DefaultPriority;

            if (messagePriority.HasValue)
            {
                self.Priority = messagePriority.Value;
            }
            var dictionary = new Dictionary <string, object>();

            foreach (var attr in cloudEvent.GetAttributes())
            {
                if (string.Equals(attr.Key, CloudEventAttributes.DataAttributeName(cloudEvent.SpecVersion)) ||
                    string.Equals(attr.Key,
                                  CloudEventAttributes.DataContentTypeAttributeName(cloudEvent.SpecVersion)) ||
                    string.Equals(attr.Key, RabbitMQPriorityExtension.PriorityAttributeName) ||
                    string.Equals(attr.Key, RabbitMQBindingConfigExtension.ExchangeAttributeName) ||
                    string.Equals(attr.Key, RabbitMQBindingConfigExtension.RoutingKeyAttributeName))
                {
                    continue;
                }
                dictionary.Add($"{CloudEventPrefix}{attr.Key}",
                               cloudEventFormatter.EncodeAttribute(cloudEvent.SpecVersion, attr.Key, attr.Value,
                                                                   cloudEvent.GetExtensions().Values));
            }

            self.Headers = dictionary;
        }
    public static MotorCloudEvent <byte[]> ToMotorCloudEvent(this Message <string?, byte[]> message,
                                                             IApplicationNameService applicationNameService, CloudEventFormatter cloudEventFormatter)
    {
        if (!message.IsCloudEvent())
        {
            return(new MotorCloudEvent <byte[]>(applicationNameService, message.Value, new Uri("kafka://notset")));
        }

        var cloudEvent = message.ToCloudEvent(cloudEventFormatter);

        if (cloudEvent.Data is null)
        {
            throw new ArgumentException("Data property of CloudEvent is null");
        }
        if (cloudEvent.Source is null)
        {
            throw new ArgumentException("Source property of CloudEvent is null");
        }
        var motorCloudEvent = new MotorCloudEvent <byte[]>(applicationNameService, (byte[])cloudEvent.Data,
                                                           cloudEvent.Type, cloudEvent.Source, cloudEvent.Id, cloudEvent.Time, cloudEvent.DataContentType);

        foreach (var(key, value) in cloudEvent.GetPopulatedAttributes())
        {
            if (motorCloudEvent.GetAttribute(key.Name) is null)
            {
                motorCloudEvent[key] = value;
            }
        }

        return(motorCloudEvent);
    }
示例#11
0
        public async Task Consume_PublishIntoExtensionDefinedTopic_ConsumedEqualsPublished()
        {
            var topic           = randomizerString.Generate();
            var message         = "testMessage";
            var publisher       = GetPublisher <byte[]>("wrong_topic");
            var motorCloudEvent =
                MotorCloudEvent.CreateTestCloudEvent(message).CreateNew(Encoding.UTF8.GetBytes(message));

            motorCloudEvent.GetExtensionOrCreate(() => new KafkaTopicExtension(topic));
            await publisher.PublishMessageAsync(motorCloudEvent, CancellationToken.None);

            var    consumer             = GetConsumer <byte[]>(topic);
            string id                   = null;
            var    taskCompletionSource = new TaskCompletionSource();

            consumer.ConsumeCallbackAsync = async(dataEvent, _) =>
            {
                id = dataEvent.Id;
                taskCompletionSource.TrySetResult();
                return(await Task.FromResult(ProcessedMessageStatus.Success));
            };

            await consumer.StartAsync();

            var consumerStartTask = consumer.ExecuteAsync();

            await Task.WhenAny(consumerStartTask, taskCompletionSource.Task);

            Assert.Equal(motorCloudEvent.Id, id);
        }
示例#12
0
    public override async Task <ProcessedMessageStatus> HandleMessageAsync(MotorCloudEvent <TInput> dataCloudEvent,
                                                                           CancellationToken token = default)
    {
        ProcessedMessageStatus processedMessageStatus;

        try
        {
            processedMessageStatus = await base.HandleMessageAsync(dataCloudEvent, token)
                                     .ConfigureAwait(false);
        }
        catch (ArgumentException ex)
        {
            _logger.LogWarning(LogEvents.InvalidInput, ex, "Invalid input (first 100 chars): {message}",
                               dataCloudEvent.Data?.ToString()?.Take(100));
            processedMessageStatus = ProcessedMessageStatus.InvalidInput;
        }
        catch (TemporaryFailureException ex)
        {
            _logger.LogError(LogEvents.ProcessingFailed, ex, "Processing failed");
            processedMessageStatus = ProcessedMessageStatus.TemporaryFailure;
        }
        catch (Exception ex)
        {
            _logger.LogCritical(LogEvents.UnexpectedErrorOnMessageProcessing, ex,
                                "Unexpected error on message processing.");

            processedMessageStatus = ProcessedMessageStatus.CriticalFailure;
        }

        return(processedMessageStatus);
    }
    public async Task SingleMessageConsumeAsync_SomeEvent_PreprocessedEventAddedToQueue()
    {
        var inputMessage   = new byte[] { 1, 2, 3 };
        var inputEvent     = MotorCloudEvent.CreateTestCloudEvent(inputMessage);
        var fakeDecoder    = new Mock <IMessageDecoder>();
        var decodedMessage = new byte[] { 4, 5, 6 };

        fakeDecoder.Setup(f => f.DecodeAsync(inputMessage, It.IsAny <CancellationToken>()))
        .ReturnsAsync(decodedMessage);
        fakeDecoder.Setup(m => m.Encoding).Returns(NoOpMessageEncoder.NoEncoding);
        var preprocessedMessage = "test";
        var fakeDeserializer    = new Mock <IMessageDeserializer <string> >();

        fakeDeserializer.Setup(f => f.Deserialize(decodedMessage)).Returns(preprocessedMessage);
        var mockQueue           = new Mock <IBackgroundTaskQueue <MotorCloudEvent <string> > >();
        var fakeMessageConsumer = new Mock <IMessageConsumer <string> >();

        fakeMessageConsumer.SetupProperty(p => p.ConsumeCallbackAsync);
        CreateConsumerService(mockQueue.Object, fakeDeserializer.Object, fakeDecoder.Object,
                              fakeMessageConsumer.Object);

        await fakeMessageConsumer.Object.ConsumeCallbackAsync?.Invoke(inputEvent, CancellationToken.None) !;

        mockQueue.Verify(m =>
                         m.QueueBackgroundWorkItem(
                             It.Is <MotorCloudEvent <string> >(cloudEvent => cloudEvent.TypedData == preprocessedMessage)));
    }
    public async Task <ProcessedMessageStatus> HandleMessageAsync(MotorCloudEvent <TInput> dataCloudEvent,
                                                                  CancellationToken token = default)
    {
        try
        {
            using (new AutoObserveStopwatch(() => _messageProcessing))
            {
                await foreach (var message in _converter.ConvertMessageAsync(dataCloudEvent, token)
                               .ConfigureAwait(false).WithCancellation(token))
                {
                    if (message?.Data is not null)
                    {
                        await _publisher.PublishMessageAsync(message, token)
                        .ConfigureAwait(false);
                    }
                }
            }

            return(ProcessedMessageStatus.Success);
        }
        catch (ArgumentException)
        {
            throw;
        }
        catch (Exception e)
        {
            _logger.LogError(LogEvents.ProcessingFailed, e, "Processing failed.");
            return(ProcessedMessageStatus.TemporaryFailure);
        }
    }
示例#15
0
            public async Task <MotorCloudEvent <string>?> ConvertMessageAsync(MotorCloudEvent <string> dataCloudEvent,
                                                                              CancellationToken token = default)
            {
                await Task.Delay(Timeout.InfiniteTimeSpan, token).ConfigureAwait(false);

                return(dataCloudEvent.CreateNew(string.Empty));
            }
示例#16
0
        public async Task <IEnumerable <MotorCloudEvent <TOutput> > > ConvertMessageAsync(
            MotorCloudEvent <TInput> dataCloudEvent, CancellationToken token)
        {
            var convertMessage = await _service.ConvertMessageAsync(dataCloudEvent, token)
                                 .ConfigureAwait(false);

            return(convertMessage == null ? new MotorCloudEvent <TOutput> [0] : new[] { convertMessage });
        }
 public static MotorCloudEvent <TData> SetRabbitMQBinding <TData>(this MotorCloudEvent <TData> cloudEvent,
                                                                  string?exchange, string?routingKey) where TData : class
 {
     CloudEventValidation.CheckNotNull(cloudEvent, nameof(cloudEvent));
     cloudEvent[RabbitMQExchangeAttribute]   = exchange;
     cloudEvent[RabbitMQRoutingKeyAttribute] = routingKey;
     return(cloudEvent);
 }
    private static MotorCloudEvent <byte[]> CreateMotorCloudEventWithEncoding(string encoding,
                                                                              byte[]?inputMessage = null)
    {
        var cloudEvent = MotorCloudEvent.CreateTestCloudEvent(inputMessage ?? Array.Empty <byte>());

        cloudEvent.SetEncoding(encoding);
        return(cloudEvent);
    }
示例#19
0
    public static MotorCloudEvent <byte[]> ToMotorCloudEvent(this string message,
                                                             IApplicationNameService applicationNameService)
    {
        var motorCloudEvent = new MotorCloudEvent <byte[]>(applicationNameService,
                                                           Encoding.UTF8.GetBytes(message), new Uri("sqs://notset"));

        return(motorCloudEvent);
    }
    public static MotorCloudEvent <byte[]> ToMotorCloudEvent(this byte[] message,
                                                             IApplicationNameService applicationNameService)
    {
        var motorCloudEvent = new MotorCloudEvent <byte[]>(applicationNameService,
                                                           message, new Uri("nats://notset"));

        return(motorCloudEvent);
    }
 public static byte?GetRabbitMQPriority <TData>(this MotorCloudEvent <TData> cloudEvent) where TData : class
 {
     return(CloudEventValidation.CheckNotNull(cloudEvent, nameof(cloudEvent))[RabbitMQPriorityAttribute] switch
     {
         int and(< 0 or > 255) => null,
         int priority => (byte)priority,
         _ => null
     });
示例#22
0
 public static MotorCloudEvent <TData> SetMotorVersion <TData>(this MotorCloudEvent <TData> cloudEvent)
     where TData : class
 {
     CloudEventValidation.CheckNotNull(cloudEvent, nameof(cloudEvent));
     cloudEvent[MotorVersionAttribute] =
         CurrentVersion ?? throw new InvalidOperationException("Motor.NET version is undefined.");
     return(cloudEvent);
 }
    public override async Task <ProcessedMessageStatus> HandleMessageAsync(MotorCloudEvent <TInput> dataCloudEvent,
                                                                           CancellationToken token = default)
    {
        var processedMessageStatus = await base.HandleMessageAsync(dataCloudEvent, token).ConfigureAwait(false);

        await _statistics.RegisterMessageStatusAsync(processedMessageStatus).ConfigureAwait(false);

        return(processedMessageStatus);
    }
示例#24
0
 public static void SetActivity <TData>(this MotorCloudEvent <TData> cloudEvent, Activity activity) where TData : class
 {
     Validation.CheckNotNull(cloudEvent, nameof(cloudEvent));
     cloudEvent[TraceParentAttribute] = activity.Id;
     if (!string.IsNullOrWhiteSpace(activity.TraceStateString))
     {
         cloudEvent[TraceStateAttribute] = activity.TraceStateString;
     }
 }
示例#25
0
    public async Task PublishMessageAsync_WithConfig_ChannelEstablished()
    {
        var rabbitConnectionFactoryMock = GetDefaultConnectionFactoryMock <string>();
        var publisher = GetPublisher(rabbitConnectionFactoryMock.Object, GetConfig());

        await publisher.PublishMessageAsync(MotorCloudEvent.CreateTestCloudEvent(Array.Empty <byte>()));

        rabbitConnectionFactoryMock.Verify(x => x.CurrentChannel, Times.Exactly(1));
    }
示例#26
0
 public virtual Task <ProcessedMessageStatus> HandleMessageAsync(MotorCloudEvent <TInput> dataCloudEvent,
                                                                 CancellationToken token = default)
 {
     if (InnerService is null)
     {
         throw new IndexOutOfRangeException("No message handler was set.");
     }
     return(InnerService.HandleMessageAsync(dataCloudEvent, token));
 }
        public async Task PublishMessageAsync_WithConfig_ConnectionFactoryIsSet()
        {
            var mock      = GetDefaultConnectionFactoryMock();
            var config    = GetConfig();
            var publisher = GetPublisher(mock.Object, config);

            await publisher.PublishMessageAsync(MotorCloudEvent.CreateTestCloudEvent(new byte [0]));

            mock.Verify(x => x.From(config), Times.Exactly(1));
        }
        public async Task PublishMessageAsync_WithConfig_ChannelEstablished()
        {
            var connectionMock = new Mock <IConnection>();
            var rabbitConnectionFactoryMock = GetDefaultConnectionFactoryMock(connectionMock: connectionMock);
            var publisher = GetPublisher(rabbitConnectionFactoryMock.Object, GetConfig());

            await publisher.PublishMessageAsync(MotorCloudEvent.CreateTestCloudEvent(new byte[0]));

            connectionMock.Verify(x => x.CreateModel(), Times.Exactly(1));
        }
            public Task <MotorCloudEvent <string> > ConvertMessageAsync(MotorCloudEvent <string> dataCloudEvent,
                                                                        CancellationToken token = default)
            {
                _logger.LogInformation("log your request");
                var tmpChar  = dataCloudEvent.TypedData.ToCharArray();
                var reversed = tmpChar.Reverse().ToArray();

                _summary.WithLabels("collect_your_metrics").Observe(1.0);
                return(Task.FromResult(dataCloudEvent.CreateNew(new string(reversed))));
            }
示例#30
0
    public async Task PublishMessageAsync_WithConfig_BasicPropertiesAreCreated()
    {
        var modelMock = new Mock <IModel>();
        var rabbitConnectionFactoryMock = GetDefaultConnectionFactoryMock <string>(modelMock: modelMock);
        var publisher = GetPublisher(rabbitConnectionFactoryMock.Object, GetConfig());

        await publisher.PublishMessageAsync(MotorCloudEvent.CreateTestCloudEvent(Array.Empty <byte>()));

        modelMock.Verify(x => x.CreateBasicProperties(), Times.Exactly(1));
    }