예제 #1
0
        public static Func <Task> Create(out SyncPoint syncPoint)
        {
            var handler = Create(1, out var syncPoints);

            syncPoint = syncPoints[0];
            return(handler);
        }
예제 #2
0
        /// <summary>
        /// Creates a re-entrant function that waits for sync points in sequence.
        /// </summary>
        /// <param name="count">The number of sync points to expect</param>
        /// <param name="syncPoints">The <see cref="SyncPoint"/> objects that can be used to coordinate the sync point</param>
        /// <returns></returns>
        public static Func <Task> Create(int count, out SyncPoint[] syncPoints)
        {
            // Need to use a local so the closure can capture it. You can't use out vars in a closure.
            var localSyncPoints = new SyncPoint[count];

            for (var i = 0; i < count; i += 1)
            {
                localSyncPoints[i] = new SyncPoint();
            }

            syncPoints = localSyncPoints;

            var counter = 0;

            return(() =>
            {
                if (counter >= localSyncPoints.Length)
                {
                    return Task.CompletedTask;
                }
                else
                {
                    var syncPoint = localSyncPoints[counter];

                    counter += 1;
                    return syncPoint.WaitToContinue();
                }
            });
        }
예제 #3
0
        public async Task GlobalFiltersRunBeforeHubSpecificFilters()
        {
            using (StartVerifiableLog())
            {
                var syncPoint1      = SyncPoint.Create(3, out var syncPoints1);
                var syncPoint2      = SyncPoint.Create(3, out var syncPoints2);
                var serviceProvider = HubConnectionHandlerTestUtils.CreateServiceProvider(services =>
                {
                    services.AddSignalR(options =>
                    {
                        options.AddFilter(new SyncPointFilter(syncPoints1));
                    })
                    .AddHubOptions <MethodHub>(options =>
                    {
                        options.AddFilter(new SyncPointFilter(syncPoints2));
                    });
                }, LoggerFactory);

                var connectionHandler = serviceProvider.GetService <HubConnectionHandler <MethodHub> >();

                using (var client = new TestClient())
                {
                    var connectionHandlerTask = await client.ConnectAsync(connectionHandler);

                    await syncPoints1[0].WaitForSyncPoint().OrTimeout();
                    // Second filter wont run yet because first filter is waiting on SyncPoint
                    Assert.False(syncPoints2[0].WaitForSyncPoint().IsCompleted);
                    syncPoints1[0].Continue();

                    await syncPoints2[0].WaitForSyncPoint().OrTimeout();
                    syncPoints2[0].Continue();
                    await client.Connected.OrTimeout();

                    var invokeTask = client.InvokeAsync(nameof(MethodHub.Echo), "Hello world!");

                    await syncPoints1[1].WaitForSyncPoint().OrTimeout();
                    // Second filter wont run yet because first filter is waiting on SyncPoint
                    Assert.False(syncPoints2[1].WaitForSyncPoint().IsCompleted);
                    syncPoints1[1].Continue();

                    await syncPoints2[1].WaitForSyncPoint().OrTimeout();
                    syncPoints2[1].Continue();
                    var message = await invokeTask.OrTimeout();

                    Assert.Null(message.Error);

                    client.Dispose();

                    await syncPoints1[2].WaitForSyncPoint().OrTimeout();
                    // Second filter wont run yet because first filter is waiting on SyncPoint
                    Assert.False(syncPoints2[2].WaitForSyncPoint().IsCompleted);
                    syncPoints1[2].Continue();

                    await syncPoints2[2].WaitForSyncPoint().OrTimeout();
                    syncPoints2[2].Continue();

                    await connectionHandlerTask.OrTimeout();
                }
            }
        }
예제 #4
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());
            });
        }