Exemplo n.º 1
0
        public RedisInvocation ReadInvocation(byte[] data)
        {
            // See WriteInvocation for format.

            using (var stream = new MemoryStream(data))
                using (var reader = new BinaryReaderWithVarInt(stream, _utf8NoBom))
                {
                    IReadOnlyList <string> excludedIds = null;

                    var idCount = reader.ReadVarInt();
                    if (idCount > 0)
                    {
                        var ids = new string[idCount];
                        for (var i = 0; i < idCount; i++)
                        {
                            ids[i] = reader.ReadString();
                        }

                        excludedIds = ids;
                    }

                    var message = SerializedHubMessage.ReadAllSerializedVersions(reader);
                    return(new RedisInvocation(message, excludedIds));
                }
        }
Exemplo n.º 2
0
        /// <inheritdoc />
        public override Task SendGroupsAsync(IReadOnlyList <string> groupNames, string methodName, object[] args, CancellationToken cancellationToken = default)
        {
            // Each task represents the list of tasks for each of the writes within a group
            List <Task>          tasks   = null;
            SerializedHubMessage message = null;

            foreach (var groupName in groupNames)
            {
                if (string.IsNullOrEmpty(groupName))
                {
                    throw new InvalidOperationException("Cannot send to an empty group name.");
                }

                var group = _groups[groupName];
                if (group != null)
                {
                    SendToGroupConnections(methodName, args, group, null, ref tasks, ref message);
                }
            }

            if (tasks != null)
            {
                return(Task.WhenAll(tasks));
            }

            return(Task.CompletedTask);
        }
Exemplo n.º 3
0
        /// <inheritdoc />
        public override Task SendGroupAsync(string groupName, string methodName, object[] args, CancellationToken cancellationToken = default)
        {
            if (groupName == null)
            {
                throw new ArgumentNullException(nameof(groupName));
            }

            var group = _groups[groupName];

            if (group != null)
            {
                // Can't optimize for sending to a single connection in a group because
                // group might be modified inbetween checking and sending
                List <Task>          tasks   = null;
                SerializedHubMessage message = null;
                SendToGroupConnections(methodName, args, group, null, ref tasks, ref message);

                if (tasks != null)
                {
                    return(Task.WhenAll(tasks));
                }
            }

            return(Task.CompletedTask);
        }
Exemplo n.º 4
0
        public byte[] WriteInvocation(string methodName, object[] args, IReadOnlyList <string> excludedIds)
        {
            // Redis Invocation Format:
            // * Variable length integer: Number of excluded Ids
            // * For each excluded Id:
            //   * Length prefixed string: ID
            // * SerializedHubMessage encoded by the format described by that type.

            using (var stream = new MemoryStream())
                using (var writer = new BinaryWriterWithVarInt(stream, _utf8NoBom))
                {
                    if (excludedIds != null)
                    {
                        writer.WriteVarInt(excludedIds.Count);
                        foreach (var id in excludedIds)
                        {
                            writer.Write(id);
                        }
                    }
                    else
                    {
                        writer.WriteVarInt(0);
                    }

                    SerializedHubMessage.WriteAllSerializedVersions(writer, new InvocationMessage(methodName, argumentBindingException: null, args), _protocols);
                    return(stream.ToArray());
                }
        }
Exemplo n.º 5
0
 public RedisInvocation(SerializedHubMessage message, IReadOnlyList <string>?excludedConnectionIds,
                        string?invocationId = null, string?returnChannel = null)
 {
     Message = message;
     ExcludedConnectionIds = excludedConnectionIds;
     ReturnChannel         = returnChannel;
     InvocationId          = invocationId;
 }
Exemplo n.º 6
0
    public void GetSerializedMessageSerializesUsingHubProtocolIfNoCacheAvailable()
    {
        var invocation = new InvocationMessage("Foo", new object[0]);
        var message    = new SerializedHubMessage(invocation);
        var protocol   = new DummyHubProtocol("p1");

        var serialized = message.GetSerializedMessage(protocol);

        Assert.Equal(DummyHubProtocol.DummySerialization, serialized.ToArray());
        Assert.Collection(protocol.GetWrittenMessages(),
                          actualMessage => Assert.Same(invocation, actualMessage));
    }
 public MsmqInvocation(
     IReadOnlyList <string> connections,
     IReadOnlyList <string> groups,
     IReadOnlyList <string> users,
     IReadOnlyList <string> excludedConnectionIds,
     SerializedHubMessage message)
 {
     this.Connections           = connections;
     this.Groups                = groups;
     this.Users                 = users;
     this.ExcludedConnectionIds = excludedConnectionIds;
     this.Message               = message;
 }
        public static IReadOnlyDictionary <string, byte[]> ToProtocolDictionary(this IEnumerable <IHubProtocol> protocols, string methodName, object[] args)
        {
            var serializedMessageHub = new SerializedHubMessage(new InvocationMessage(methodName, args));

            var messages = new Dictionary <string, byte[]>();

            foreach (var protocol in protocols)
            {
                ReadOnlyMemory <byte> serialized = serializedMessageHub.GetSerializedMessage(protocol);

                messages.Add(protocol.Name, serialized.ToArray());
            }

            return(messages);
        }
Exemplo n.º 9
0
        private static void WriteSerializedHubMessage(Stream stream, SerializedHubMessage message)
        {
            // Written as a MessagePack 'map' where the keys are the name of the protocol (as a MessagePack 'str')
            // and the values are the serialized blob (as a MessagePack 'bin').

            var protocol = new JsonHubProtocol();

            MessagePackBinary.WriteMapHeader(stream, 1);
            MessagePackBinary.WriteString(stream, protocol.Name);

            var serialized = message.GetSerializedMessage(protocol);

            MemoryMarshal.TryGetArray(serialized, out var array);
            MessagePackBinary.WriteBytes(stream, array.Array, array.Offset, array.Count);
        }
Exemplo n.º 10
0
        private void WriteSerializedHubMessage(Stream stream, SerializedHubMessage message)
        {
            // Written as a MessagePack 'map' where the keys are the name of the protocol (as a MessagePack 'str')
            // and the values are the serialized blob (as a MessagePack 'bin').
            MessagePackBinary.WriteMapHeader(stream, this.protocols.Count);

            foreach (var protocol in this.protocols)
            {
                MessagePackBinary.WriteString(stream, protocol.Name);

                var serialized = message.GetSerializedMessage(protocol);
                var isArray    = MemoryMarshal.TryGetArray(serialized, out var array);
                Debug.Assert(isArray, "should be array");
                MessagePackBinary.WriteBytes(stream, array.Array, array.Offset, array.Count);
            }
        }
Exemplo n.º 11
0
    public void GetSerializedMessageReturnsCachedSerializationIfAvailable()
    {
        var invocation = new InvocationMessage("Foo", new object[0]);
        var message    = new SerializedHubMessage(invocation);
        var protocol   = new DummyHubProtocol("p1");

        // This should cache it
        _ = message.GetSerializedMessage(protocol);

        // Get it again
        var serialized = message.GetSerializedMessage(protocol);

        Assert.Equal(DummyHubProtocol.DummySerialization, serialized.ToArray());

        // We should still only have written one message
        Assert.Collection(protocol.GetWrittenMessages(),
                          actualMessage => Assert.Same(invocation, actualMessage));
    }
Exemplo n.º 12
0
        public Task SendToAllLocalConnection(string methodName, object[] args, string[] excludeConnectionIds = null)
        {
            List <Task>          tasks   = null;
            SerializedHubMessage message = null;

            // foreach over HubConnectionStore avoids allocating an enumerator
            foreach (var connection in _connections)
            {
                if (excludeConnectionIds != null && excludeConnectionIds.Contains(connection.ConnectionId))
                {
                    continue;
                }

                if (message == null)
                {
                    message = CreateSerializedInvocationMessage(methodName, args);
                }

                var task = connection.WriteAsync(message);

                if (!task.IsCompletedSuccessfully)
                {
                    if (tasks == null)
                    {
                        tasks = new List <Task>();
                    }

                    tasks.Add(task.AsTask());
                }
            }

            if (tasks == null)
            {
                return(Task.CompletedTask);
            }



            // Some connections are slow
            return(Task.WhenAll(tasks));
        }
Exemplo n.º 13
0
    public async Task SerializingTwoMessagesFromTheSameProtocolSimultaneouslyResultsInOneCachedItemAsync(int numberOfSerializationsToPreCache)
    {
        var invocation = new InvocationMessage("Foo", new object[0]);
        var message    = new SerializedHubMessage(invocation);

        // "Pre-cache" the requested number of serializations (so we can test scenarios involving each of the fields and the fallback list)
        for (var i = 0; i < numberOfSerializationsToPreCache; i++)
        {
            _ = message.GetSerializedMessage(new DummyHubProtocol($"p{i}"));
        }

        var onWrite  = SyncPoint.Create(2, out var syncPoints);
        var protocol = new DummyHubProtocol("test", () => onWrite().Wait());

        // Serialize once, but hold at the Hub Protocol
        var   firstSerialization = Task.Run(() => message.GetSerializedMessage(protocol));
        await syncPoints[0].WaitForSyncPoint();

        // Serialize again, which should hit the lock
        var secondSerialization = Task.Run(() => message.GetSerializedMessage(protocol));

        Assert.False(secondSerialization.IsCompleted);

        // Release both instances of the syncpoint
        syncPoints[0].Continue();
        syncPoints[1].Continue();

        // Everything should finish and only one serialization should be written
        await firstSerialization.DefaultTimeout();

        await secondSerialization.DefaultTimeout();

        Assert.Collection(message.GetAllSerializations().Skip(numberOfSerializationsToPreCache).ToArray(),
                          serializedMessage =>
        {
            Assert.Equal("test", serializedMessage.ProtocolName);
            Assert.Equal(DummyHubProtocol.DummySerialization, serializedMessage.Serialized.ToArray());
        });
    }
Exemplo n.º 14
0
        /// <inheritdoc />
        public override Task SendGroupExceptAsync(string groupName, string methodName, object[] args, IReadOnlyList <string> excludedConnectionIds, CancellationToken cancellationToken = default)
        {
            if (groupName == null)
            {
                throw new ArgumentNullException(nameof(groupName));
            }

            var group = _groups[groupName];

            if (group != null)
            {
                List <Task>          tasks   = null;
                SerializedHubMessage message = null;

                SendToGroupConnections(methodName, args, group, connection => !excludedConnectionIds.Contains(connection.ConnectionId), ref tasks, ref message);

                if (tasks != null)
                {
                    return(Task.WhenAll(tasks));
                }
            }

            return(Task.CompletedTask);
        }
 public RabbitMQInvocation(SerializedHubMessage message, IReadOnlyList <string> excludedConnectionIds)
 {
     this.Message = message;
     this.ExcludedConnectionIds = excludedConnectionIds;
 }
Exemplo n.º 16
0
        // Tasks and message are passed by ref so they can be lazily created inside the method post-filtering,
        // while still being re-usable when sending to multiple groups
        private void SendToGroupConnections(string methodName, object[] args, ConcurrentDictionary <string, HubConnectionContext> connections, Func <HubConnectionContext, bool> include, ref List <Task> tasks, ref SerializedHubMessage message)
        {
            // foreach over ConcurrentDictionary avoids allocating an enumerator
            foreach (var connection in connections)
            {
                if (include != null && !include(connection.Value))
                {
                    continue;
                }

                if (message == null)
                {
                    message = CreateSerializedInvocationMessage(methodName, args);
                }

                var task = connection.Value.WriteAsync(message);

                if (!task.IsCompletedSuccessfully)
                {
                    if (tasks == null)
                    {
                        tasks = new List <Task>();
                    }

                    tasks.Add(task.AsTask());
                }
            }
        }
Exemplo n.º 17
0
 public PostgreSqlInvocation(SerializedHubMessage message, IReadOnlyList <string> excludedConnectionIds)
 {
     Message = message;
     ExcludedConnectionIds = excludedConnectionIds;
 }
Exemplo n.º 18
0
 public RedisInvocation(SerializedHubMessage message, IReadOnlyList <string> excludedIds)
 {
     Message     = message;
     ExcludedIds = excludedIds;
 }
Exemplo n.º 19
0
 public async Task SendMessage(SerializedHubMessage message) =>
 await Clients.All.SendAsync("recieveMessage", message);