/// <summary> /// Invoked when a router gets a message. /// </summary> /// <param name="sender"> /// The <see cref="IMessageRouter"/>. /// </param> /// <param name="msg"> /// The message. /// </param> /// <remarks> /// Invokes any topic handlers and publishes the messages on the other routers. /// </remarks> private void Router_MessageReceived(object sender, PublishedMessage msg) { ++MesssagesReceived; // Check for duplicate message. if (_tracker.RecentlySeen(msg.MessageId)) { ++DuplicateMesssagesReceived; return; } // Call local topic handlers. var handlers = _topicHandlers.Values .Where(th => msg.Topics.Contains(th.Topic)); foreach (var handler in handlers) { try { handler.Handler(msg); } catch (Exception e) { _log.Error($"Topic handler for '{handler.Topic}' failed.", e); } } // Tell other message routers. _ = Task.WhenAll(Routers .Where(r => r != sender) .Select(r => r.PublishAsync(msg, CancellationToken.None)) ); }
/// <inheritdoc /> public Task PublishAsync(PublishedMessage message, CancellationToken cancel) { cancel.ThrowIfCancellationRequested(); if (!_tracker.RecentlySeen(message.MessageId)) { MessageReceived?.Invoke(this, message); } return(Task.CompletedTask); }
/// <inheritdoc /> public Task PublishAsync(PublishedMessage message, CancellationToken cancel) { if (_tracker.RecentlySeen(message.MessageId)) { return(Task.CompletedTask); } // Find a set of peers that are interested in the topic(s). // Exclude author and sender var peers = message.Topics .SelectMany(topic => RemoteTopics.GetPeers(topic)) .Where(peer => peer != message.Sender) .Where(peer => peer != message.Forwarder); // Forward the message. var forward = new PubSubMessage { PublishedMessages = new[] { message } }; return(SendAsync(forward, peers, cancel)); }