private void MqttClient_Connected(object sender, MqttClientConnectedEventArgs e) { var topics = TopicEvent?.Invoke(); SubscribeAsync(topics); ConnectEvent?.Invoke(true, null); }
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; } }
/// <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); }
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; } }
protected abstract Task <Int64> AddTopicEventAsync(TopicEvent newTopicEvent);
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; }
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; } }
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; }