Пример #1
0
        private void MqttClient_Connected(object sender, MqttClientConnectedEventArgs e)
        {
            var topics = TopicEvent?.Invoke();

            SubscribeAsync(topics);
            ConnectEvent?.Invoke(true, null);
        }
Пример #2
0
 private void PrepareTopicEvent(TopicEvent newTopicEvent)
 {
     if (!newTopicEvent.PublicationDateUtc.HasValue)
     {
         var utcNow = GetNowUtcAsync().GetAwaiter().GetResult();
         newTopicEvent.PublicationDateUtc = utcNow;
     }
     if (newTopicEvent.FunctionalKey == null)
     {
         newTopicEvent.FunctionalKey = string.Empty;
     }
 }
Пример #3
0
        /// <summary>
        /// Subscribes.
        /// </summary>
        ///
        /// <param name="topic"> The topic. </param>
        /// <param name="func">  The function. </param>
        ///
        /// <returns>
        /// A String.
        /// </returns>
        public static String subscribe(String topic, TopicEvent func)
        {
            if (!topics.Keys.Contains(topic))
            {
                topics.Add(topic, new Dictionary <String, TopicEvent>());
            }

            String token = (++subUid).ToString();

            topics[topic].Add(token, func);

            return(token);
        }
Пример #4
0
        public async Task <TopicEvent> PublishTopicEventAsync(TopicEvent newTopicEvent, bool logTopicEvent, IEnumerable <Subscription> subscriptionsMatching, DateTime?deliveryDelayedUntilUtc)
        {
            await BeginTransactionAsync().ConfigureAwait(false);

            try
            {
                PrepareTopicEvent(newTopicEvent);

                if (logTopicEvent)
                {
                    var topicEventId = await AddTopicEventAsync(newTopicEvent).ConfigureAwait(false);

                    newTopicEvent.Id = topicEventId;
                }

                // Create tasks for each subscription
                var subTasks = new List <Task <Int64> >();
                foreach (var subscription in subscriptionsMatching)
                {
                    // By default a SubscriptionEvent takes expirationdate of TopicEvent
                    var subExpirationDateUtc = newTopicEvent.ExpirationDateUtc;

                    // If subscription has its own TTL, it will be applied, but may never exceed the TopicEvent expiration
                    if (subscription.TimeToLive.HasValue)
                    {
                        subExpirationDateUtc = newTopicEvent.PublicationDateUtc.Value.AddSeconds(subscription.TimeToLive.Value);
                        if (newTopicEvent.ExpirationDateUtc < subExpirationDateUtc)
                        {
                            subExpirationDateUtc = newTopicEvent.ExpirationDateUtc;
                        }
                    }

                    // Delivery can be initially delayed, but it cannot exceed the expirationdate (would be useless)
                    DateTime subDeliveryDelayedUntilUtc = MinDateTime;
                    if (deliveryDelayedUntilUtc.HasValue) // Passed values always go overwrite subscription settings
                    {
                        subDeliveryDelayedUntilUtc = deliveryDelayedUntilUtc.Value;
                    }
                    else if (subscription.DeliveryDelay.HasValue)
                    {
                        subDeliveryDelayedUntilUtc = newTopicEvent.PublicationDateUtc.Value.AddSeconds(subscription.DeliveryDelay.Value);
                    }

                    var newSubscriptionEvent = new SubscriptionEvent
                    {
                        SubscriptionId          = subscription.Id.Value,
                        TopicEventId            = newTopicEvent.Id,
                        EventName               = newTopicEvent.EventName,
                        PublicationDateUtc      = newTopicEvent.PublicationDateUtc.Value,
                        FunctionalKey           = newTopicEvent.FunctionalKey,
                        Priority                = newTopicEvent.Priority,
                        PayloadId               = newTopicEvent.PayloadId,
                        Payload                 = null, // Only used when consuming
                        ExpirationDateUtc       = subExpirationDateUtc,
                        DeliveryDelayedUntilUtc = subDeliveryDelayedUntilUtc,
                        DeliveryCount           = 0,
                        DeliveryKey             = string.Empty,
                        InvisibleUntilUtc       = MinDateTime,
                    };

                    if (ParallelQueriesSupport)
                    {
                        subTasks.Add(AddSubscriptionEventAsync(newSubscriptionEvent));
                    }
                    else
                    {
                        await AddSubscriptionEventAsync(newSubscriptionEvent).ConfigureAwait(false);
                    }
                }
                ;

                if (subTasks.Count > 0)                                           // Wait for all tasks (if any) to complete
                {
                    await Task.WhenAll(subTasks.ToArray()).ConfigureAwait(false); // No timeout: db-commandtimeout will do
                }
                await CommitTransactionAsync().ConfigureAwait(false);

                // Return the topic event
                return(newTopicEvent);
            }
            catch (AggregateException aggrEx)
            {
                await RollbackTransactionAsync().ConfigureAwait(false);

                var firstInnerEx = aggrEx.InnerExceptions.FirstOrDefault();
                if (firstInnerEx != null)
                {
                    throw firstInnerEx; // Do we want this?
                }
                else
                {
                    throw;
                }
            }
            catch (Exception)
            {
                await RollbackTransactionAsync().ConfigureAwait(false);

                throw;
            }
        }
Пример #5
0
 protected abstract Task <Int64> AddTopicEventAsync(TopicEvent newTopicEvent);
Пример #6
0
 protected virtual void RaiseTopicEvent(TokenEventArgs e)
 {
     TopicEvent?.Invoke(this, e);
 }
        /// <summary>
        /// Subscribes.
        /// </summary>
        ///
        /// <param name="topic"> The topic. </param>
        /// <param name="func">  The function. </param>
        ///
        /// <returns>
        /// A String.
        /// </returns>
        public static String subscribe(String topic, TopicEvent func)
        {
            if (!topics.Keys.Contains(topic))
            {
                topics.Add(topic, new Dictionary<String, TopicEvent>());
            }

            String token = (++subUid).ToString();

            topics[topic].Add(token, func);

            return token;
        }
Пример #8
0
        public async Task <TopicEvent> PublishAsync(string topicName, string eventName = null, DateTime?publicationDateUtc = default(DateTime?), DateTime?deliveryDelayedUntilUtc = default(DateTime?), DateTime?expirationDateUtc = default(DateTime?), string functionalKey = null, int priority = 100, Dictionary <string, string> headers = null, string payload = null)
        {
            var topic = await GetTopicByNameAsync(topicName).ConfigureAwait(false);

            if (topic == null)
            {
                throw new ArgumentException($"Topic with name {topicName} not found", "topicName");
            }

            // Store payload (outside transaction, no need to lock right now already)
            var payloadId = (payload != null) ? await _repoFactory.InvokeFuncAsync(r => r.StorePayloadAsync(payload), _invokeOptions) : default(Int64?);

            var subscriptions = await GetTopicSubscriptionsAsync(topic.Id.Value).ConfigureAwait(false);

            var eventNameToUse = eventName;

            if (eventNameToUse == null && headers != null)
            {
                var eventNameHeader = headers.FirstOrDefault(h => h.Key.Equals("EventName", StringComparison.OrdinalIgnoreCase));
                if (eventNameHeader.Key != null)
                {
                    eventNameToUse = eventNameHeader.Value;
                }
            }

            var utcNow = _dtProvider == DateTimeProvider.Repository ? await _repoFactory.InvokeFuncAsync(r => r.GetNowUtcAsync(), _invokeOptions) : DateTime.UtcNow;

            // Store topic event
            var newTopicEvent = new TopicEvent
            {
                TopicId            = topic.Id.Value,
                EventName          = eventNameToUse,
                PublicationDateUtc = publicationDateUtc.GetValueOrDefault(utcNow),
                FunctionalKey      = functionalKey ?? string.Empty,
                Priority           = priority,
                ExpirationDateUtc  = expirationDateUtc.GetValueOrDefault(BaseEventingRepo.MaxDateTime),
                Headers            = headers,
                PayloadId          = payloadId,
            };

            // Determine for which subscriptions the topic must be published
            var subscriptionsMatching = subscriptions
                                        .Where((s) => s.TopicSubscriptions.Any((ts) => ((ts.TopicId == topic.Id.Value) && ts.Enabled && (!ts.Filtered || CheckFilters(ts.Filters, headers)))))
                                        .Distinct(); // Nessecary when one subscription has more than once topicsubscription for the same topic (probably with different filters)

            try
            {
                var topicEvent = await _repoFactory.InvokeFuncAsync(r => r.PublishTopicEventAsync(newTopicEvent, topic.Log, subscriptionsMatching, deliveryDelayedUntilUtc), _invokeOptions);

                return(topicEvent);
            }
            catch (Exception)
            {
                if (payloadId.HasValue)
                {
                    try
                    {
                        await _repoFactory.InvokeFuncAsync(r => r.DeletePayloadAsync(payloadId.Value), InvokeOptions.NoRetries); // Something went wrong, so don't bother retrying here
                    }
                    catch (Exception) { } // Don't bother, not too much of a problem (just a little storage lost)
                }

                throw;
            }
        }
Пример #9
0
        private IrcEvent ParseTopic(UserData sender, EntityData target, string[] param, string text)
        {
            // Export before updating data
            var ev = new TopicEvent((User)sender, (Channel)target, text);

            var target_c = (ChannelData)target;
            if (text == "") {
                target_c.topic = "";
                target_c.topic_setter = "";
                target_c.topic_settime = null;
            } else {
                target_c.topic = text;
                target_c.topic_setter = sender.nick;
                target_c.topic_settime = DateTime.Now;
            }
            return ev;
        }