/// <summary>
        /// Dispatches the event to all registered clients wishing to receive it.
        /// </summary>
        /// <param name="eventData">The event data.</param>
        /// <returns>The total number of clients notified of the event.</returns>
        public async Task <int> ReceiveEvent(SubscriptionEvent eventData)
        {
            if (eventData == null)
            {
                return(0);
            }

            var eventRoute = _schema.RetrieveSubscriptionFieldPath(eventData.ToSubscriptionEventName());

            if (eventRoute == null)
            {
                return(0);
            }

            // grab a reference to all clients that need the event
            var clientList = new List <ApolloClientProxy <TSchema> >();

            lock (_syncLock)
            {
                if (_subCountByName.TryGetValue(eventData.ToSubscriptionEventName(), out var clients))
                {
                    clientList.AddRange(clients);
                }
            }

            _logger?.EventReceived(eventData, clientList);
            if (clientList.Count == 0)
            {
                return(0);
            }

            var cancelSource = new CancellationTokenSource();

            // TODO: Add some timing wrappers with cancel token to ensure no spun out
            // comms.
            var allTasks = clientList.Select((client) =>
                                             this.ExecuteSubscriptionEvent(
                                                 client,
                                                 eventRoute,
                                                 eventData.Data,
                                                 cancelSource.Token)).ToList();

            await Task.WhenAll(allTasks).ConfigureAwait(false);

            // re-await any faulted tasks so tehy can unbubble any exceptions
            foreach (var task in allTasks.Where(x => x.IsFaulted))
            {
                await task.ConfigureAwait(false);
            }

            return(allTasks.Count);
        }
        public async Task SubscribedReceiveer_TwoEvents_DoesReceiveBothEventsOnce()
        {
            var receiver = new Mock <ISubscriptionEventReceiver>();

            receiver.Setup(x => x.ReceiveEvent(It.IsAny <SubscriptionEvent>())).Returns(Task.CompletedTask);

            var router = new DefaultSubscriptionEventRouter();

            var evt = new SubscriptionEvent()
            {
                SchemaTypeName = typeof(GraphSchema).FullName,
                EventName      = "bobEvent5",
                DataTypeName   = typeof(TwoPropertyObject).FullName,
                Data           = new TwoPropertyObject(),
            };

            var evt2 = new SubscriptionEvent()
            {
                SchemaTypeName = typeof(GraphSchema).FullName,
                EventName      = "bobEvent6",
                DataTypeName   = typeof(TwoPropertyObject).FullName,
                Data           = new TwoPropertyObject(),
            };

            // add two events but remove the one being raised
            // to ensure its not processed
            router.AddReceiver(evt.ToSubscriptionEventName(), receiver.Object);
            router.AddReceiver(evt2.ToSubscriptionEventName(), receiver.Object);
            await router.RaiseEvent(evt);

            await router.RaiseEvent(evt2);

            receiver.Verify(x => x.ReceiveEvent(evt), Times.Once);
            receiver.Verify(x => x.ReceiveEvent(evt2), Times.Once);
        }
        public async Task UnsubscribedAllReceiver_DoesNotReceivesRaisedEvent()
        {
            var receiver = new Mock <ISubscriptionEventReceiver>();

            receiver.Setup(x => x.ReceiveEvent(It.IsAny <SubscriptionEvent>())).Returns(Task.CompletedTask);

            var router = new DefaultSubscriptionEventRouter();

            var evt = new SubscriptionEvent()
            {
                SchemaTypeName = typeof(GraphSchema).FullName,
                EventName      = "bobEvent5",
                DataTypeName   = typeof(TwoPropertyObject).FullName,
                Data           = new TwoPropertyObject(),
            };

            var evt2 = new SubscriptionEvent()
            {
                SchemaTypeName = typeof(GraphSchema).FullName,
                EventName      = "bobEvent6",
                DataTypeName   = typeof(TwoPropertyObject).FullName,
                Data           = new TwoPropertyObject(),
            };

            // add two events and ensure both are removed when not directly named
            router.AddReceiver(evt.ToSubscriptionEventName(), receiver.Object);
            router.AddReceiver(evt2.ToSubscriptionEventName(), receiver.Object);
            router.RemoveReceiver(receiver.Object);
            await router.RaiseEvent(evt);

            await router.RaiseEvent(evt2);

            receiver.Verify(x => x.ReceiveEvent(evt), Times.Never);
            receiver.Verify(x => x.ReceiveEvent(evt2), Times.Never);
        }
        public void GeneralPropertyCheck()
        {
            var eventData = new SubscriptionEvent()
            {
                Data           = new object(),
                DataTypeName   = "dataType",
                SchemaTypeName = "schemaType",
                EventName      = "eventName",
            };

            Assert.AreEqual(new SubscriptionEventName("schemaType", "eventName"), eventData.ToSubscriptionEventName());
        }
        public async Task SubscribedReceiver_ReceivesRaisedEvent()
        {
            var receiver = new Mock <ISubscriptionEventReceiver>();

            receiver.Setup(x => x.ReceiveEvent(It.IsAny <SubscriptionEvent>())).Returns(Task.CompletedTask);

            var router = new DefaultSubscriptionEventRouter();

            var evt = new SubscriptionEvent()
            {
                SchemaTypeName = typeof(GraphSchema).FullName,
                EventName      = "bobEvent5",
                DataTypeName   = typeof(TwoPropertyObject).FullName,
                Data           = new TwoPropertyObject(),
            };

            router.AddReceiver(evt.ToSubscriptionEventName(), receiver.Object);
            await router.RaiseEvent(evt);

            receiver.Verify(x => x.ReceiveEvent(evt));
        }