private async Task SendAsync(IList <object> events, Func <object, BinaryData> binaryDataFactory, CancellationToken cancellationToken)
        {
            bool isEventGridEvent = false;

            try
            {
                // test the first event to determine CloudEvent vs EventGridEvent
                // both event types are NOT supported in same list
                EventGridEvent.Parse(binaryDataFactory(events.First()));
                isEventGridEvent = true;
            }
            catch (ArgumentException)
            {
            }
            if (isEventGridEvent)
            {
                List <EventGridEvent> egEvents = new(events.Count);
                foreach (object evt in events)
                {
                    egEvents.Add(EventGridEvent.Parse(binaryDataFactory(evt)));
                }

                await _client.SendEventsAsync(egEvents, cancellationToken).ConfigureAwait(false);
            }
            else
            {
                List <CloudEvent> cloudEvents = new(events.Count);
                foreach (object evt in events)
                {
                    cloudEvents.Add(CloudEvent.Parse(binaryDataFactory(evt)));
                }

                await _client.SendEventsAsync(cloudEvents, cancellationToken).ConfigureAwait(false);
            }
        }
        public void Initialize(ExtensionConfigContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            _logger = _loggerFactory.CreateLogger <EventGridExtensionConfigProvider>();

#pragma warning disable 618
            Uri url = context.GetWebhookHandler();
#pragma warning restore 618
            _logger.LogInformation($"registered EventGrid Endpoint = {url?.GetLeftPart(UriPartial.Path)}");

            // Register our extension binding providers
            // use converterManager as a hashTable
            // also take benefit of identity converter
            context
            .AddBindingRule <EventGridTriggerAttribute>()    // following converters are for EventGridTriggerAttribute only
            .AddConverter <JToken, string>(jtoken => jtoken.ToString(Formatting.Indented))
            .AddConverter <JToken, string[]>(jarray => jarray.Select(ar => ar.ToString(Formatting.Indented)).ToArray())
            .AddConverter <JToken, DirectInvokeString>(jtoken => new DirectInvokeString(null))
            .AddConverter <JToken, EventGridEvent>(jobject => EventGridEvent.Parse(new BinaryData(jobject.ToString())))    // surface the type to function runtime
            .AddConverter <JToken, EventGridEvent[]>(jobject => EventGridEvent.ParseMany(new BinaryData(jobject.ToString())))
            .AddConverter <JToken, CloudEvent>(jobject => CloudEvent.Parse(new BinaryData(jobject.ToString())))
            .AddConverter <JToken, CloudEvent[]>(jobject => CloudEvent.ParseMany(new BinaryData(jobject.ToString())))
            .AddConverter <JToken, BinaryData>(jobject => new BinaryData(jobject.ToString()))
            .AddConverter <JToken, BinaryData[]>(jobject => jobject.Select(obj => new BinaryData(obj.ToString())).ToArray())
            .AddOpenConverter <JToken, OpenType.Poco>(typeof(JTokenToPocoConverter <>))
            .AddOpenConverter <JToken, OpenType.Poco[]>(typeof(JTokenToPocoConverter <>))
            .BindToTrigger <JToken>(new EventGridTriggerAttributeBindingProvider(this));

            // Register the output binding
            var rule = context.AddBindingRule <EventGridAttribute>();
            rule.BindToCollector(_converter);
            rule.AddValidator((a, t) =>
            {
                // if app setting is missing, it will be caught by runtime
                // this logic tries to validate the practicality of attribute properties
                if (string.IsNullOrWhiteSpace(a.TopicKeySetting))
                {
                    throw new InvalidOperationException($"The '{nameof(EventGridAttribute.TopicKeySetting)}' property must be the name of an application setting containing the Topic Key");
                }

                if (!Uri.IsWellFormedUriString(a.TopicEndpointUri, UriKind.Absolute))
                {
                    throw new InvalidOperationException($"The '{nameof(EventGridAttribute.TopicEndpointUri)}' property must be a valid absolute Uri");
                }
            });
        }
Exemplo n.º 3
0
        public async Task FlushAsync(CancellationToken cancellationToken = default(CancellationToken))
        {
            IList <object> events;
            var            newEventList = new List <object>();

            lock (_syncroot)
            {
                // swap the events to send out with a new list; locking so 'AddAsync' doesn't take place while we do this
                events        = _eventsToSend;
                _eventsToSend = newEventList;
            }

            if (events.Any())
            {
                // determine the schema by inspecting the first event (a topic can only support a single schema)
                var firstEvent = events.First();
                if (firstEvent is string str)
                {
                    bool isEventGridEvent = false;
                    try
                    {
                        var ev = EventGridEvent.Parse(new BinaryData(str));
                        isEventGridEvent = true;
                    }
                    catch (ArgumentException)
                    {
                    }

                    if (isEventGridEvent)
                    {
                        List <EventGridEvent> egEvents = new(events.Count);
                        foreach (string evt in events)
                        {
                            egEvents.Add(EventGridEvent.Parse(new BinaryData(evt)));
                        }

                        await _client.SendEventsAsync(egEvents, cancellationToken).ConfigureAwait(false);
                    }
                    else
                    {
                        List <CloudEvent> cloudEvents = new(events.Count);
                        foreach (string evt in events)
                        {
                            cloudEvents.Add(CloudEvent.Parse(new BinaryData(evt)));
                        }

                        await _client.SendEventsAsync(cloudEvents, cancellationToken).ConfigureAwait(false);
                    }
                }
                else if (firstEvent is BinaryData data)
                {
                    bool isEventGridEvent = false;
                    try
                    {
                        var ev = EventGridEvent.Parse(data);
                        isEventGridEvent = true;
                    }
                    catch (ArgumentException)
                    {
                    }

                    if (isEventGridEvent)
                    {
                        List <EventGridEvent> egEvents = new(events.Count);
                        foreach (BinaryData evt in events)
                        {
                            egEvents.Add(EventGridEvent.Parse(evt));
                        }

                        await _client.SendEventsAsync(egEvents, cancellationToken).ConfigureAwait(false);
                    }
                    else
                    {
                        List <CloudEvent> cloudEvents = new(events.Count);
                        foreach (BinaryData evt in events)
                        {
                            cloudEvents.Add(CloudEvent.Parse(evt));
                        }

                        await _client.SendEventsAsync(cloudEvents, cancellationToken).ConfigureAwait(false);
                    }
                }
                else if (firstEvent is JObject jObject)
                {
                    bool isEventGridEvent = false;
                    try
                    {
                        var ev = EventGridEvent.Parse(new BinaryData(jObject.ToString()));
                        isEventGridEvent = true;
                    }
                    catch (ArgumentException)
                    {
                    }

                    if (isEventGridEvent)
                    {
                        List <EventGridEvent> egEvents = new(events.Count);
                        foreach (JObject evt in events)
                        {
                            egEvents.Add(EventGridEvent.Parse(new BinaryData(evt.ToString())));
                        }

                        await _client.SendEventsAsync(egEvents, cancellationToken).ConfigureAwait(false);
                    }
                    else
                    {
                        List <CloudEvent> cloudEvents = new(events.Count);
                        foreach (JObject evt in events)
                        {
                            cloudEvents.Add(CloudEvent.Parse(new BinaryData(evt.ToString())));
                        }

                        await _client.SendEventsAsync(cloudEvents, cancellationToken).ConfigureAwait(false);
                    }
                }
                else if (firstEvent is EventGridEvent)
                {
                    List <EventGridEvent> egEvents = new(events.Count);
                    foreach (object evt in events)
                    {
                        egEvents.Add((EventGridEvent)evt);
                    }
                    await _client.SendEventsAsync(egEvents, cancellationToken).ConfigureAwait(false);
                }
                else if (firstEvent is CloudEvent)
                {
                    List <CloudEvent> cloudEvents = new(events.Count);
                    foreach (object evt in events)
                    {
                        cloudEvents.Add((CloudEvent)evt);
                    }
                    await _client.SendEventsAsync(cloudEvents, cancellationToken).ConfigureAwait(false);
                }
                else
                {
                    throw new InvalidOperationException(
                              $"{firstEvent?.GetType().ToString()} is not a valid event type.");
                }
            }
        }