private void Broadcast(string eventKey, Message message) { LockedList<Action<IList<Message>>> callbacks; if (_waitingTasks.TryGetValue(eventKey, out callbacks)) { var delegates = callbacks.CopyWithLock(); var messages = new[] { message }; _trace.Source.TraceInformation("MessageBus: Sending message {0} to {1} waiting connections", message.Id, delegates.Count); foreach (var callback in delegates) { if (callback != null) { callback.Invoke(messages); } } } }
/// <summary> /// Invoked when a payload is received from the backplane. There should only be one active call at any time. /// </summary> /// <param name="streamId">id of the stream</param> /// <param name="id">id of the payload within that stream</param> /// <param name="messages">List of messages associated</param> /// <returns></returns> protected Task<bool> OnReceived(string streamId, ulong id, Message[] messages) { var stream = _streamMappings.GetOrAdd(streamId, _ => new Linktionary<ulong, ScaleoutMapping>()); var mapping = new ScaleoutMapping(); stream.Add(id, mapping); foreach (var m in messages) { // Get the payload info var info = mapping.EventKeyMappings.GetOrAdd(m.Key, _ => new LocalEventKeyInfo()); // Save the min and max for this payload for later ulong localId = Save(m); // Set the topic pointer for this event key so we don't need to look it up later info.Topic = _topics[m.Key]; info.MinLocal = Math.Min(localId, info.MinLocal); info.Count++; } foreach (var eventKey in mapping.EventKeyMappings.Keys) { ScheduleEvent(eventKey); } return TaskAsyncHelper.True; }
internal static bool TryGetCommand(Message message, IJsonSerializer serializer, out SignalCommand command) { command = null; if (!message.SignalKey.EndsWith(SignalrCommand, StringComparison.OrdinalIgnoreCase)) { return false; } command = message.Value as SignalCommand; // Optimization for in memory message store if (command != null) { return true; } // Otherwise deserialize the message value string rawValue = message.Value as string; if (rawValue == null) { return false; } command = serializer.Parse<SignalCommand>(rawValue); return true; }
public Task Save(string key, object value) { var message = new Message(key, Interlocked.Increment(ref _lastMessageId), value); var list = _items.GetOrAdd(key, _ => new SafeSet<Message>()); list.Add(message); return TaskAsyncHelper.Empty; }
protected internal Task Save(Message message) { var key = message.SignalKey; var list = _items.GetOrAdd(key, _ => new SafeSet<Message>()); list.Add(message); if (message.Id > _lastMessageId) { lock (_idLocker) { if (message.Id > _lastMessageId) { _lastMessageId = message.Id; } } } return TaskAsyncHelper.Empty; }
protected internal Task Save(Message message) { var key = message.SignalKey; SafeSet<Message> list; if (!_items.TryGetValue(key, out list)) { list = new SafeSet<Message>(); _items.TryAdd(key, list); } list.Add(message); if (message.Id > _messageId) { lock (_idLocker) { if (message.Id > _messageId) { _messageId = message.Id; } } } return TaskAsyncHelper.Empty; }
public Task Save(string key, object value) { var message = new Message(key, Interlocked.Increment(ref _lastMessageId), value); return Save(message); }
public Task Send(string eventKey, object value) { var list = _cache.GetOrAdd(eventKey, _ => new LockedList<Message>()); Message message = null; try { // Take a write lock here so we ensure messages go into the list in order _cacheLock.EnterWriteLock(); // Only 1 save allowed at a time, to ensure messages are added to the list in order message = new Message(eventKey, GenerateId(), value); _trace.Source.TraceInformation("MessageBus: Saving message {0} to cache", message.Id); list.AddWithLock(message); // Send to waiting callers. // This must be done in the read lock to ensure that messages are sent to waiting // connections in the order they were saved so that they always get the correct // last message id to resubscribe with. Broadcast(eventKey, message); } finally { _cacheLock.ExitWriteLock(); } return TaskAsyncHelper.Empty; }
public static bool IsCommand(Message message) { return message.Key.EndsWith(SignalrCommand, StringComparison.OrdinalIgnoreCase); }
/// <summary> /// Publishes a new message to the specified event on the bus. /// </summary> /// <param name="source">A value representing the source of the data sent.</param> public virtual Task Publish(Message message) { Topic topic = GetTopic(message.Key); topic.Store.Add(message); _msgsTotalCounter.SafeIncrement(); _msgsPerSecCounter.SafeIncrement(); ScheduleTopic(topic); return TaskAsyncHelper.Empty; }
protected ulong Save(Message message) { Topic topic = GetTopic(message.Key); ulong id = topic.Store.Add(message); _msgsTotalCounter.SafeIncrement(); _msgsPerSecCounter.SafeIncrement(); return id; }
/// <summary> /// Publishes a new message to the specified event on the bus. /// </summary> /// <param name="source">A value representing the source of the data sent.</param> public virtual Task Publish(Message message) { Topic topic = GetTopic(message.Key); topic.Store.Add(message); _counters.MessageBusMessagesPublishedTotal.Increment(); _counters.MessageBusMessagesPublishedPerSec.Increment(); ScheduleTopic(topic); return TaskAsyncHelper.Empty; }
/// <summary> /// Sends messages to the backplane /// </summary> /// <param name="messages"></param> /// <returns></returns> protected abstract Task Send(Message[] messages);
public override Task Publish(Message message) { // TODO: Buffer messages here and make it configurable return Send(new[] { message }); }
private bool ExcludeMessage(Message message) { if (String.IsNullOrEmpty(message.Filter)) { return false; } string[] exclude = message.Filter.Split('|'); return exclude.Any(signal => Identity.Equals(signal, StringComparison.OrdinalIgnoreCase) || _signals.Contains(signal) || _groups.Contains(signal)); }
private Message CreateMessage(string key, object value) { var command = value as Command; var message = new Message(_connectionId, key, _serializer.Stringify(value)); if (command != null) { // Set the command id message.CommandId = command.Id; message.WaitForAck = command.WaitForAck; } return message; }
protected ulong Save(Message message) { Topic topic = GetTopic(message.Key); ulong id = topic.Store.Add(message); _counters.MessageBusMessagesPublishedTotal.Increment(); _counters.MessageBusMessagesPublishedPerSec.Increment(); return id; }