public async Task HandleAsync(CloudEvent cloudEvent, CancellationToken cancellationToken)
    {
        // This is an example of how CloudEvents are unfortunately inconsistent when it
        // comes to Data. Is it "pre-serialized" or not? We prevent parsing date/time values,
        // so that we can get as close to the original JSON as possible.
        var settings = new JsonSerializerSettings {
            DateParseHandling = DateParseHandling.None
        };

        cloudEvent.Data = JsonConvert.DeserializeObject <JObject>((string)cloudEvent.Data, settings);

        // Work around https://github.com/cloudevents/sdk-csharp/issues/59
        var attributes    = cloudEvent.GetAttributes();
        var attributeKeys = attributes.Keys.ToList();

        foreach (var key in attributeKeys)
        {
            var lowerKey = key.ToLowerInvariant();
            var value    = attributes[key];
            attributes.Remove(key);
            attributes[lowerKey] = value;
        }

        // Write out a structured JSON representation of the CloudEvent
        var formatter = new JsonEventFormatter();
        var bytes     = formatter.EncodeStructuredEvent(cloudEvent, out var contentType);
        await File.WriteAllBytesAsync("function_output.json", bytes);
    }
コード例 #2
0
        public void PartitioningJsonTranscode()
        {
            var jsonFormatter = new JsonEventFormatter();
            var cloudEvent1   = jsonFormatter.DecodeStructuredEvent(Encoding.UTF8.GetBytes(jsonPartitioningKey));
            var jsonData      = jsonFormatter.EncodeStructuredEvent(cloudEvent1, out var contentType);
            var cloudEvent    = jsonFormatter.DecodeStructuredEvent(jsonData, new PartitioningExtension());

            Assert.Equal("1", cloudEvent.Extension <PartitioningExtension>().PartitioningKeyValue);
        }
コード例 #3
0
ファイル: SequenceTest.cs プロジェクト: Uvindu96/sdk-csharp
        public void Transcode()
        {
            var jsonFormatter = new JsonEventFormatter();
            var cloudEvent1   = jsonFormatter.DecodeStructuredEvent(Encoding.UTF8.GetBytes(sampleJson));
            var jsonData      = jsonFormatter.EncodeStructuredEvent(cloudEvent1, out var contentType);
            var cloudEvent    = jsonFormatter.DecodeStructuredEvent(jsonData, Sequence.AllAttributes);

            Assert.Equal("Integer", cloudEvent[Sequence.SequenceTypeAttribute]);
            Assert.Equal("25", cloudEvent[Sequence.SequenceAttribute]);
        }
コード例 #4
0
        public void Transcode()
        {
            var jsonFormatter = new JsonEventFormatter();
            var cloudEvent1   = jsonFormatter.DecodeStructuredEvent(Encoding.UTF8.GetBytes(sampleJson));
            var jsonData      = jsonFormatter.EncodeStructuredEvent(cloudEvent1, out _);
            var cloudEvent    = jsonFormatter.DecodeStructuredEvent(jsonData);

            Assert.Equal("abc", cloudEvent["partitionkey"]);
            Assert.Equal("abc", cloudEvent[Partitioning.PartitionKeyAttribute]);
            Assert.Equal("abc", cloudEvent.GetPartitionKey());
        }
コード例 #5
0
        public void Transcode()
        {
            var jsonFormatter = new JsonEventFormatter();
            var cloudEvent1   = jsonFormatter.DecodeStructuredEvent(Encoding.UTF8.GetBytes(sampleJson));
            var jsonData      = jsonFormatter.EncodeStructuredEvent(cloudEvent1, out _);
            var cloudEvent    = jsonFormatter.DecodeStructuredEvent(jsonData, DistributedTracing.AllAttributes);

            Assert.Equal(SampleParent, cloudEvent[DistributedTracing.TraceParentAttribute]);
            Assert.Equal(SampleParent, cloudEvent.GetTraceParent());
            Assert.Equal(SampleState, cloudEvent[DistributedTracing.TraceStateAttribute]);
            Assert.Equal(SampleState, cloudEvent.GetTraceState());
        }
コード例 #6
0
        public static string SaveToQueue([ActivityTrigger] DurableActivityContext inputs, ILogger log)
        {
            string notificationMsg;

            var(orderId, parentId) = inputs.GetInput <(string, string)>();

            // dependency tracking
            var requestActivity = new Activity("command://order.update");

            requestActivity.SetParentId(parentId);
            var requestOperation = _telemetryClient.StartOperation <RequestTelemetry>(requestActivity);

            var text = new AsciiArt("complete order");

            log.LogInformation(text.ToString());

            try
            {
                ContentType contentType;
                log.LogInformation($"Sending notification for {orderId} to queue.");
                var notificationEvent = new CloudEvent(
                    "command://order.update",
                    new Uri("app://ticketing.services.shipping"))
                {
                    Id          = Guid.NewGuid().ToString(),
                    ContentType = new ContentType(MediaTypeNames.Application.Json),
                    Data        = JsonConvert.SerializeObject(new ObjectStatus()
                    {
                        Id     = orderId,
                        Status = "Delivered"
                    })
                };
                var jsonFormatter = new JsonEventFormatter();
                var messageBody   = jsonFormatter.EncodeStructuredEvent(notificationEvent, out contentType);
                notificationMsg = Encoding.UTF8.GetString(messageBody);
            }
            catch (Exception ex)
            {
                // dependency tracking
                _telemetryClient.TrackException(ex);
                throw;
            }
            finally
            {
                // dependency tracking
                _telemetryClient.StopOperation(requestOperation);
            }
            return(notificationMsg);
        }
コード例 #7
0
        private static async Task <Response> SendCloudEventsInternalAsync(
            EventGridPublisherClient client,
            IEnumerable <CloudEvent> cloudEvents,
            bool async,
            CancellationToken cancellationToken = default)
        {
            Argument.AssertNotNull(client, nameof(client));
            string   activityId      = null;
            string   traceState      = null;
            Activity currentActivity = Activity.Current;

            if (currentActivity != null && currentActivity.IsW3CFormat())
            {
                activityId = currentActivity.Id;
                currentActivity.TryGetTraceState(out traceState);
            }

            using var stream = new MemoryStream();
            using var writer = new Utf8JsonWriter(stream);
            writer.WriteStartArray();
            foreach (var cloudEvent in cloudEvents)
            {
                var attributes = cloudEvent.GetAttributes();
                if (activityId != null &&
                    !attributes.ContainsKey(TraceParentHeaderName) &&
                    !attributes.ContainsKey(TraceStateHeaderName))
                {
                    attributes.Add(TraceParentHeaderName, activityId);
                    if (traceState != null)
                    {
                        attributes.Add(TraceStateHeaderName, traceState);
                    }
                }

                byte[] bytes = s_eventFormatter.EncodeStructuredEvent(cloudEvent, out var _);
                using JsonDocument document = JsonDocument.Parse(bytes);
                document.RootElement.WriteTo(writer);
            }
            writer.WriteEndArray();
            writer.Flush();
            if (async)
            {
                return(await client.SendEncodedCloudEventsAsync(stream.GetBuffer().AsMemory(0, (int)stream.Position), cancellationToken).ConfigureAwait(false));
            }
            else
            {
                return(client.SendEncodedCloudEvents(stream.GetBuffer().AsMemory(0, (int)stream.Position), cancellationToken));
            }
        }
コード例 #8
0
ファイル: JsonTest.cs プロジェクト: fabiodaniele/sdk-csharp
        public void ReserializeTest10()
        {
            var jsonFormatter = new JsonEventFormatter();
            var cloudEvent    = jsonFormatter.DecodeStructuredEvent(Encoding.UTF8.GetBytes(jsonv10));
            var jsonData      = jsonFormatter.EncodeStructuredEvent(cloudEvent, out var contentType);
            var cloudEvent2   = jsonFormatter.DecodeStructuredEvent(jsonData);

            Assert.Equal(cloudEvent2.SpecVersion, cloudEvent.SpecVersion);
            Assert.Equal(cloudEvent2.Type, cloudEvent.Type);
            Assert.Equal(cloudEvent2.Source, cloudEvent.Source);
            Assert.Equal(cloudEvent2.Id, cloudEvent.Id);
            AssertTimestampsEqual(cloudEvent2.Time, cloudEvent.Time);
            Assert.Equal(cloudEvent2.DataContentType, cloudEvent.DataContentType);
            Assert.Equal(cloudEvent2.Data, cloudEvent.Data);
        }
コード例 #9
0
        public void ReserializeTest()
        {
            var jsonFormatter = new JsonEventFormatter();
            var cloudEvent    = jsonFormatter.DecodeStructuredEvent(Encoding.UTF8.GetBytes(json));
            var jsonData      = jsonFormatter.EncodeStructuredEvent(cloudEvent, out var contentType);
            var cloudEvent2   = jsonFormatter.DecodeStructuredEvent(jsonData);

            Assert.Equal(cloudEvent2.SpecVersion, cloudEvent.SpecVersion);
            Assert.Equal(cloudEvent2.Type, cloudEvent.Type);
            Assert.Equal(cloudEvent2.Source, cloudEvent.Source);
            Assert.Equal(cloudEvent2.Id, cloudEvent.Id);
            Assert.Equal(cloudEvent2.Time.Value.ToUniversalTime(), cloudEvent.Time.Value.ToUniversalTime());
            Assert.Equal(cloudEvent2.ContentType, cloudEvent.ContentType);
            Assert.Equal(cloudEvent2.Data, cloudEvent.Data);
        }
コード例 #10
0
        public void SamplingJsonTranscode()
        {
            var jsonFormatter = new JsonEventFormatter();
            var cloudEvent1   = jsonFormatter.DecodeStructuredEvent(Encoding.UTF8.GetBytes(sampleJson));

            // Note that the value is just a string here, as we don't know the attribute type.
            Assert.Equal("1", cloudEvent1["sampledrate"]);

            var jsonData   = jsonFormatter.EncodeStructuredEvent(cloudEvent1, out _);
            var cloudEvent = jsonFormatter.DecodeStructuredEvent(jsonData, Sampling.AllAttributes);

            // When parsing with the attributes in place, the value is propagated as an integer.
            Assert.Equal(1, cloudEvent["sampledrate"]);
            Assert.Equal(1, cloudEvent.GetSampledRate());
        }
コード例 #11
0
        public void SamplingJsonTranscode()
        {
            var jsonFormatter = new JsonEventFormatter();
            var cloudEvent1   = jsonFormatter.DecodeStructuredEvent(Encoding.UTF8.GetBytes(jsonSampledRate));
            var jsonData      = jsonFormatter.EncodeStructuredEvent(cloudEvent1, out var contentType);
            var cloudEvent    = jsonFormatter.DecodeStructuredEvent(jsonData, new SamplingExtension());

            Assert.Equal(CloudEventsSpecVersion.Default, cloudEvent.SpecVersion);
            Assert.Equal("com.github.pull.create", cloudEvent.Type);
            Assert.Equal(new Uri("https://github.com/cloudevents/spec/pull/123"), cloudEvent.Source);
            Assert.Equal("A234-1234-1234", cloudEvent.Id);
            AssertTimestampsEqual("2018-04-05T17:31:00Z", cloudEvent.Time.Value);

            Assert.Equal(1, cloudEvent.Extension <SamplingExtension>().SampledRate.Value);
        }
コード例 #12
0
        public void IntegerSequenceJsonTranscode()
        {
            var jsonFormatter = new JsonEventFormatter();
            var cloudEvent1   = jsonFormatter.DecodeStructuredEvent(Encoding.UTF8.GetBytes(jsonSequence));
            var jsonData      = jsonFormatter.EncodeStructuredEvent(cloudEvent1, out var contentType);
            var cloudEvent    = jsonFormatter.DecodeStructuredEvent(jsonData, new IntegerSequenceExtension());

            Assert.Equal(CloudEventsSpecVersion.V0_2, cloudEvent.SpecVersion);
            Assert.Equal("com.github.pull.create", cloudEvent.Type);
            Assert.Equal(new Uri("https://github.com/cloudevents/spec/pull/123"), cloudEvent.Source);
            Assert.Equal("A234-1234-1234", cloudEvent.Id);
            Assert.Equal(DateTime.Parse("2018-04-05T17:31:00Z").ToUniversalTime(),
                         cloudEvent.Time.Value.ToUniversalTime());

            Assert.Equal(25, cloudEvent.Extension <IntegerSequenceExtension>().Sequence);
        }
コード例 #13
0
        public void DistTraceJsonTranscode()
        {
            var jsonFormatter = new JsonEventFormatter();
            var cloudEvent1   = jsonFormatter.DecodeStructuredEvent(Encoding.UTF8.GetBytes(jsonDistTrace));
            var jsonData      = jsonFormatter.EncodeStructuredEvent(cloudEvent1, out var contentType);
            var cloudEvent    = jsonFormatter.DecodeStructuredEvent(jsonData, new DistributedTracingExtension());

            Assert.Equal(CloudEventsSpecVersion.Default, cloudEvent.SpecVersion);
            Assert.Equal("com.github.pull.create", cloudEvent.Type);
            Assert.Equal(new Uri("https://github.com/cloudevents/spec/pull/123"), cloudEvent.Source);
            Assert.Equal("A234-1234-1234", cloudEvent.Id);
            AssertTimestampsEqual("2018-04-05T17:31:00Z", cloudEvent.Time.Value);

            Assert.Equal("00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01", cloudEvent.Extension <DistributedTracingExtension>().TraceParent);
            Assert.Equal("rojo=00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01,congo=lZWRzIHRoNhcm5hbCBwbGVhc3VyZS4=", cloudEvent.Extension <DistributedTracingExtension>().TraceState);
        }
コード例 #14
0
        public void SerializedCloudEvent_AsJObject_IsCloudEvent(CloudEventsSpecVersion specVersion)
        {
            // Arrange
            var cloudEvent = new CloudEvent(
                specVersion,
                $"event-type-{Guid.NewGuid()}",
                new Uri("http://test-host"),
                id: $"event-id-{Guid.NewGuid()}")
            {
                Data            = $"event-data-{Guid.NewGuid()}",
                DataContentType = new ContentType("text/plain")
            };
            var jsonFormatter = new JsonEventFormatter();

            byte[]  serialized = jsonFormatter.EncodeStructuredEvent(cloudEvent, out ContentType contentType);
            JObject jObject    = JObject.Parse(Encoding.UTF8.GetString(serialized));

            // Act
            bool isCloudEvent = jObject.IsCloudEvent();

            // Assert
            Assert.True(isCloudEvent, "Serialized CloudEvent object should be evaluated as CloudEvent schema");
        }
コード例 #15
0
ファイル: fx_payment.cs プロジェクト: MassimoC/PaaSTicketing
        public static void Run(
            [ServiceBusTrigger("q-payment-in", Connection = "SB-Queue-In-AppSettings")]
            string paymentItem,
            [ServiceBus("q-notifications", Connection = "SB-Queue-In-AppSettings")] out string notificationEventString,
            [ServiceBus("q-shipping-in", Connection = "SB-Queue-In-AppSettings")] out string outboundEventString,
            ILogger log,
            ExecutionContext context)
        {
            log.LogInformation("start fx_payment function");
            outboundEventString     = null;
            notificationEventString = null;
            byte[] messageBody;

            var telemetryClient = new TelemetryClient(TelemetryConfiguration.Active);

            var config = new ConfigurationBuilder()
                         .SetBasePath(context.FunctionAppDirectory)
                         .AddJsonFile("local.settings.json", optional: true, reloadOnChange: true)
                         .AddEnvironmentVariables()
                         .Build();

            var securityVault = new VaultService(config["Values:VaultName"]);

            var sbConnectionString = String.Empty;

            try
            {
                sbConnectionString = securityVault.GetSecret("cn-servicebus").Result;
            }
            catch (Exception)
            {
                sbConnectionString = config["Values:SB-Queue-In-AppSettings"];
            }

            try
            {
                ContentType contentType;
                var         jsonFormatter = new JsonEventFormatter();
                var         inboundEvent  = jsonFormatter.DecodeStructuredEvent(Encoding.UTF8.GetBytes(paymentItem));
                log.LogInformation($" message type : { inboundEvent.Type}");

                // TODO: This should be done with a DURABLE function
                // or implement compensation
                var text = new AsciiArt("payment");
                log.LogInformation(text.ToString());

                // 1. perform the payment
                var paymentCtx = JsonConvert.DeserializeObject <PaymentContext>((string)inboundEvent.Data);
                Pay(paymentCtx);
                log.LogInformation("Payment is done for {paymentCtx.Attendee}. OrderId : {paymentCtx.OrderId} - Token {paymentCtx.Token}");

                log.LogInformation(new EventId((int)LoggingContext.EventId.Processing),
                                   LoggingContext.Template,
                                   "cloud event publishing [command://order.pay]",
                                   LoggingContext.EntityType.Order.ToString(),
                                   LoggingContext.EventId.Processing.ToString(),
                                   LoggingContext.Status.Pending.ToString(),
                                   "correlationId",
                                   LoggingContext.CheckPoint.Publisher.ToString(),
                                   "long description");

                #region "command://order.update"

                // new activity introduced for better readibility in E2E dependency tree
                var requestActivity  = new Activity("command://order.update");
                var requestOperation = telemetryClient.StartOperation <RequestTelemetry>(requestActivity);
                try
                {
                    // 2. notify the change
                    var notificationEvent = new CloudEvent(
                        "command://order.update",
                        new Uri("app://ticketing.services.payment"))
                    {
                        Id          = Guid.NewGuid().ToString(),
                        ContentType = new ContentType(MediaTypeNames.Application.Json),
                        Data        = JsonConvert.SerializeObject(new ObjectStatus()
                        {
                            Id     = paymentCtx.OrderId,
                            Status = "Paid"
                        })
                    };
                    // return as string to avoid ContentType deserialization problem
                    messageBody             = jsonFormatter.EncodeStructuredEvent(notificationEvent, out contentType);
                    notificationEventString = Encoding.UTF8.GetString(messageBody);
                }
                catch (Exception ex)
                {
                    // dependency tracking
                    telemetryClient.TrackException(ex);
                    throw;
                }
                finally
                {
                    // dependency tracking
                    telemetryClient.StopOperation(requestOperation);
                }

                #endregion

                #region "command://order.deliver"
                requestActivity  = new Activity("command://order.deliver");
                requestOperation = telemetryClient.StartOperation <RequestTelemetry>(requestActivity);
                try
                {
                    // 3. trigger next step
                    var outboundEvent = new CloudEvent(
                        "command://order.deliver",
                        new Uri("app://ticketing.services.payment"))
                    {
                        Id          = Guid.NewGuid().ToString(),
                        ContentType = new ContentType(MediaTypeNames.Application.Json),
                        Data        = JsonConvert.SerializeObject(paymentCtx)
                    };
                    messageBody         = jsonFormatter.EncodeStructuredEvent(outboundEvent, out contentType);
                    outboundEventString = Encoding.UTF8.GetString(messageBody);
                }
                catch (Exception ex)
                {
                    // dependency tracking
                    telemetryClient.TrackException(ex);
                    throw;
                }
                finally
                {
                    // dependency tracking
                    telemetryClient.StopOperation(requestOperation);
                }
                #endregion
            }
            catch (System.Exception ex)
            {
                // TODO : compensation
                var pub    = new Publisher("q-errors", sbConnectionString);
                var result = pub.SendMessagesAsync(paymentItem);
                log.LogError(ex.Message);
            }

            log.LogInformation("end function");
        }
コード例 #16
0
        public async Task <IActionResult> PlaceOrder([FromBody] OrderCreateDto orderCreate)
        {
            // dependency tracking
            var telemetryClient = _telemetryClientFactory.Create();

            _logger.LogInformation("API - Order controller - PlaceOrders");
            ConcertUser entityConcertUser;

            try
            {
                entityConcertUser = Mapper.Map <ConcertUser>(orderCreate);
                _ordersRepository.PlaceOrderAsync(entityConcertUser);
                await _ordersRepository.SaveChangesAsync();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex.Message);
                if (ex.InnerException.Message.Contains("PK_"))
                {
                    return(BadRequest(new ProblemDetailsError(StatusCodes.Status400BadRequest, "Duplicate order.")));
                }
                throw;
            }

            _logger.LogInformation($"Retrieving new order");
            var orderDb = await _ordersRepository.GetOrderAsync(entityConcertUser.Token);

            var orderDto = Mapper.Map <ApiLib.DTOs.OrderDto>(orderDb);

            // dependency tracking
            var current          = Activity.Current;
            var requestActivity  = new Activity("command://order.pay");
            var requestOperation = telemetryClient.StartOperation <RequestTelemetry>(requestActivity);

            try
            {
                // drop message in the queue
                _logger.LogInformation($"Drop message in the queue");

                //TODO KeyVault : local MSI and docker
                var sbConnectionString = String.Empty;
                try
                {
                    sbConnectionString = _vaultService.GetSecret("cn-servicebus").Result;
                }
                catch (Exception ex)
                {
                    // TODO local debug with docker
                    // MSI + docker not working in debug mode?
                    _logger.LogError(ex.Message);
                }
                if (String.IsNullOrEmpty(sbConnectionString))
                {
                    sbConnectionString = _configuration.GetConnectionString(name: "ServiceBus");
                }

                var pub        = new Publisher("q-payment-in", sbConnectionString);
                var cloudEvent = new CloudEvent("command://order.pay", new Uri("app://ticketing.api"))
                {
                    Id          = Guid.NewGuid().ToString(),
                    ContentType = new ContentType(MediaTypeNames.Application.Json),
                    Data        = JsonConvert.SerializeObject(new PaymentContext()
                    {
                        Attendee = orderDto.Attendee,
                        OrderId  = orderDto.OrderId.ToString(),
                        Token    = orderDto.Token,
                    })
                };

                _logger.LogInformation(new EventId((int)LoggingContext.EventId.Processing),
                                       LoggingContext.Template,
                                       "cloud event publishing [command://order.pay]",
                                       LoggingContext.EntityType.Order.ToString(),
                                       LoggingContext.EventId.Processing.ToString(),
                                       LoggingContext.Status.Pending.ToString(),
                                       "correlationId",
                                       LoggingContext.CheckPoint.Publisher.ToString(),
                                       "long description");

                _logger.LogInformation("COMMAND - Sending message to the bus.");
                var jsonFormatter = new JsonEventFormatter();
                var messageBody   = jsonFormatter.EncodeStructuredEvent(cloudEvent, out var contentType);
                await pub.SendMessagesAsync(Encoding.UTF8.GetString(messageBody));
            }
            catch (Exception ex)
            {
                // dependency tracking
                telemetryClient.TrackException(ex);
                throw;
            }
            finally
            {
                // dependency tracking
                telemetryClient.StopOperation(requestOperation);
            }

            _logger.LogInformation($"Returning order token '{entityConcertUser.Token}'");
            return(CreatedAtRoute("Orders_GetOrderDetails",
                                  new { token = entityConcertUser.Token },
                                  orderDto));
        }