Пример #1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="InteractionHandshakeConductor"/> class.
        /// </summary>
        /// <param name="localEndpoint">The endpoint ID of the local endpoint.</param>
        /// <param name="endpointInformationStorage">The object that stores information about the known endpoints.</param>
        /// <param name="interactionSubjects">The collection that contains all the registered subjects and their commands and notifications.</param>
        /// <param name="commandProxyHub">The object that stores the command proxy objects.</param>
        /// <param name="notificationProxyHub">The object that stores the notification proxy objects.</param>
        /// <param name="sendMessage">The action that is used to send a message to a remote endpoint.</param>
        /// <param name="sendMessageAndWaitForResponse">
        /// The function that sends out a message to the given endpoint and returns a task that will, eventually, hold the return message.
        /// </param>
        /// <param name="sendTimeout">The maximum amount of time the instance will wait for a response message to be returned.</param>
        /// <param name="diagnostics">The object that provides the diagnostics methods for the application.</param>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="localEndpoint"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="endpointInformationStorage"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="interactionSubjects"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="commandProxyHub"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="notificationProxyHub"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="sendMessage"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="sendMessageAndWaitForResponse"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="diagnostics"/> is <see langword="null" />.
        /// </exception>
        public InteractionHandshakeConductor(
            EndpointId localEndpoint,
            IStoreInformationAboutEndpoints endpointInformationStorage,
            IStoreInteractionSubjects interactionSubjects,
            IStoreRemoteCommandProxies commandProxyHub,
            IStoreRemoteNotificationProxies notificationProxyHub,
            SendMessage sendMessage,
            SendMessageAndWaitForResponse sendMessageAndWaitForResponse,
            TimeSpan sendTimeout,
            SystemDiagnostics diagnostics)
        {
            {
                Lokad.Enforce.Argument(() => localEndpoint);
                Lokad.Enforce.Argument(() => endpointInformationStorage);
                Lokad.Enforce.Argument(() => interactionSubjects);
                Lokad.Enforce.Argument(() => commandProxyHub);
                Lokad.Enforce.Argument(() => notificationProxyHub);
                Lokad.Enforce.Argument(() => sendMessage);
                Lokad.Enforce.Argument(() => sendMessageAndWaitForResponse);
                Lokad.Enforce.Argument(() => diagnostics);
            }

            m_Current = localEndpoint;
            m_EndpointInformationStorage = endpointInformationStorage;
            m_EndpointInformationStorage.OnEndpointConnected += HandleEndpointSignIn;

            m_InteractionSubjects           = interactionSubjects;
            m_CommandProxyHub               = commandProxyHub;
            m_NotificationProxyHub          = notificationProxyHub;
            m_SendMessage                   = sendMessage;
            m_SendMessageAndWaitForResponse = sendMessageAndWaitForResponse;
            m_Diagnostics                   = diagnostics;

            m_SendTimeout = sendTimeout;
        }
        public void HandleEndpointSignOut()
        {
            var localEndpoint = new EndpointId("local");
            var notifier      = new Mock <IStoreInformationAboutEndpoints>();
            var configuration = new Mock <IConfiguration>();
            {
                configuration.Setup(c => c.HasValueFor(It.IsAny <ConfigurationKey>()))
                .Returns(false);
            }

            var systemDiagnostics = new SystemDiagnostics((p, s) => { }, null);
            SendMessageAndWaitForResponse sender =
                (e, m, r, t) => Task <ICommunicationMessage> .Factory.StartNew(
                    () => new SuccessMessage(localEndpoint, new MessageId()),
                    new CancellationToken(),
                    TaskCreationOptions.None,
                    new CurrentThreadTaskScheduler());

            var hub = new RemoteCommandHub(
                notifier.Object,
                new CommandProxyBuilder(
                    localEndpoint,
                    sender,
                    configuration.Object,
                    systemDiagnostics),
                systemDiagnostics);

            var endpoint = new EndpointId("other");
            var types    = new List <OfflineTypeInformation>
            {
                new OfflineTypeInformation(
                    typeof(InteractionExtensionsTest.IMockCommandSetWithTaskReturn).FullName,
                    typeof(InteractionExtensionsTest.IMockCommandSetWithTaskReturn).Assembly.GetName())
            };

            var eventWasTriggered = false;

            hub.OnEndpointConnected += (s, e) =>
            {
                eventWasTriggered = true;
                Assert.AreEqual(endpoint, e.Endpoint);
                Assert.IsTrue(hub.HasCommandFor(e.Endpoint, typeof(InteractionExtensionsTest.IMockCommandSetWithTaskReturn)));
            };
            hub.OnEndpointDisconnected += (s, e) =>
            {
                eventWasTriggered = true;
                Assert.AreEqual(endpoint, e.Endpoint);
                Assert.IsFalse(hub.HasCommandFor(e.Endpoint, typeof(InteractionExtensionsTest.IMockCommandSetWithTaskReturn)));
            };

            hub.OnReceiptOfEndpointCommands(endpoint, types);
            Assert.IsTrue(eventWasTriggered);

            eventWasTriggered = false;
            notifier.Raise(l => l.OnEndpointDisconnected += null, new EndpointEventArgs(endpoint));
            Assert.IsTrue(eventWasTriggered);
        }
        public void ProxyConnectingToMethodWithRetryCount()
        {
            var remoteEndpoint = new EndpointId("other");

            var local      = new EndpointId("local");
            var retryCount = -1;
            var timeout    = TimeSpan.MinValue;
            CommandInvokedMessage         intermediateMsg = null;
            SendMessageAndWaitForResponse sender          = (e, m, r, t) =>
            {
                retryCount = r;
                timeout    = t;

                intermediateMsg = m as CommandInvokedMessage;
                return(Task <ICommunicationMessage> .Factory.StartNew(
                           () => new SuccessMessage(remoteEndpoint, new MessageId()),
                           new CancellationToken(),
                           TaskCreationOptions.None,
                           new CurrentThreadTaskScheduler()));
            };

            var configuration = new Mock <IConfiguration>();
            {
                configuration.Setup(c => c.HasValueFor(It.IsAny <ConfigurationKey>()))
                .Returns(false);
            }

            var systemDiagnostics = new SystemDiagnostics((p, s) => { }, null);

            var builder = new CommandProxyBuilder(local, sender, configuration.Object, systemDiagnostics);
            var proxy   = builder.ProxyConnectingTo <InteractionExtensionsTest.IMockCommandSetWithTaskReturn>(remoteEndpoint);

            var result = proxy.MyRetryMethod(10);

            result.Wait();

            Assert.IsTrue(result.IsCompleted);
            Assert.IsFalse(result.IsCanceled);
            Assert.IsFalse(result.IsFaulted);

            Assert.AreEqual(
                CommandId.Create(typeof(InteractionExtensionsTest.IMockCommandSetWithTaskReturn).GetMethod("MyRetryMethod")),
                intermediateMsg.Invocation.Command);
            Assert.AreEqual(0, intermediateMsg.Invocation.Parameters.Length);
            Assert.AreEqual(10, retryCount);
            Assert.AreEqual(TimeSpan.FromMilliseconds(CommunicationConstants.DefaultWaitForResponseTimeoutInMilliSeconds), timeout);
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="CommandProxyBuilder"/> class.
        /// </summary>
        /// <param name="localEndpoint">The ID number of the local endpoint.</param>
        /// <param name="sendWithResponse">
        ///     The function that sends out a message to the given endpoint and returns a task that will, eventually, hold the return message.
        /// </param>
        /// <param name="configuration">The object that stores the configuration for the application.</param>
        /// <param name="systemDiagnostics">The object that provides the diagnostics methods for the system.</param>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="localEndpoint"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="sendWithResponse"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="configuration"/> is <see langword="null" />.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        ///     Thrown if <paramref name="systemDiagnostics"/> is <see langword="null" />.
        /// </exception>
        public CommandProxyBuilder(
            EndpointId localEndpoint,
            SendMessageAndWaitForResponse sendWithResponse,
            IConfiguration configuration,
            SystemDiagnostics systemDiagnostics)
        {
            {
                Lokad.Enforce.Argument(() => localEndpoint);
                Lokad.Enforce.Argument(() => sendWithResponse);
                Lokad.Enforce.Argument(() => configuration);
                Lokad.Enforce.Argument(() => systemDiagnostics);
            }

            m_Local            = localEndpoint;
            m_SendWithResponse = sendWithResponse;
            m_Configuration    = configuration;
            m_Diagnostics      = systemDiagnostics;
        }
        public void ProxyConnectingToMethodWithTypedTaskReturnWithFailedExecution()
        {
            var remoteEndpoint = new EndpointId("other");

            var local = new EndpointId("local");
            CommandInvokedMessage         intermediateMsg = null;
            SendMessageAndWaitForResponse sender          = (e, m, r, t) =>
            {
                intermediateMsg = m as CommandInvokedMessage;
                return(Task <ICommunicationMessage> .Factory.StartNew(
                           () => new FailureMessage(remoteEndpoint, new MessageId()),
                           new CancellationToken(),
                           TaskCreationOptions.None,
                           new CurrentThreadTaskScheduler()));
            };

            var configuration = new Mock <IConfiguration>();
            {
                configuration.Setup(c => c.HasValueFor(It.IsAny <ConfigurationKey>()))
                .Returns(false);
            }

            var systemDiagnostics = new SystemDiagnostics((p, s) => { }, null);

            var builder = new CommandProxyBuilder(local, sender, configuration.Object, systemDiagnostics);
            var proxy   = builder.ProxyConnectingTo <InteractionExtensionsTest.IMockCommandSetWithTypedTaskReturn>(remoteEndpoint);

            var result = proxy.MyMethod(10);

            Assert.Throws <AggregateException>(result.Wait);

            Assert.IsTrue(result.IsCompleted);
            Assert.IsFalse(result.IsCanceled);
            Assert.IsTrue(result.IsFaulted);
            Assert.IsAssignableFrom(typeof(CommandInvocationFailedException), result.Exception.InnerExceptions[0]);

            Assert.AreEqual(
                CommandId.Create(typeof(InteractionExtensionsTest.IMockCommandSetWithTypedTaskReturn).GetMethod("MyMethod")),
                intermediateMsg.Invocation.Command);
            Assert.AreEqual(1, intermediateMsg.Invocation.Parameters.Length);
            Assert.AreEqual(typeof(int), intermediateMsg.Invocation.Parameters[0].Parameter.Type);
            Assert.AreEqual("input", intermediateMsg.Invocation.Parameters[0].Parameter.Name);
            Assert.AreEqual(10, intermediateMsg.Invocation.Parameters[0].Value);
        }
Пример #6
0
        private static void RegisterSendMessageFunctions(ContainerBuilder builder)
        {
            builder.Register(
                c =>
            {
                var layer          = c.Resolve <IProtocolLayer>();
                SendMessage result = layer.SendMessageTo;
                return(result);
            })
            .As <SendMessage>()
            .SingleInstance();

            builder.Register(
                c =>
            {
                var layer = c.Resolve <IProtocolLayer>();
                SendMessageAndWaitForResponse result = layer.SendMessageAndWaitForResponse;
                return(result);
            })
            .As <SendMessageAndWaitForResponse>()
            .SingleInstance();
        }
        public void HandshakeWithLocalRejection()
        {
            var id              = new EndpointId("a:10");
            var remoteEndpoint  = new EndpointId("b:10");
            var endpointStorage = new Mock <IStoreInformationAboutEndpoints>();
            {
                endpointStorage.Setup(e => e.TryRemoveEndpoint(It.IsAny <EndpointId>()))
                .Returns(true)
                .Verifiable();
            }

            var providedSubjects = new Dictionary <CommunicationSubject, CommunicationSubjectGroup>
            {
                {
                    new CommunicationSubject("a"),
                    new CommunicationSubjectGroup(
                        new CommunicationSubject("a"),
                        new[]
                    {
                        new VersionedTypeFallback(
                            new Tuple <OfflineTypeInformation, Version>(
                                new OfflineTypeInformation(typeof(int).FullName, typeof(int).Assembly.GetName()),
                                new Version(1, 0))),
                    },
                        new VersionedTypeFallback[0])
                }
            };
            var requiredSubjects = new Dictionary <CommunicationSubject, CommunicationSubjectGroup>
            {
                {
                    new CommunicationSubject("b"),
                    new CommunicationSubjectGroup(
                        new CommunicationSubject("b"),
                        new VersionedTypeFallback[0],
                        new[]
                    {
                        new VersionedTypeFallback(
                            new Tuple <OfflineTypeInformation, Version>(
                                new OfflineTypeInformation(typeof(double).FullName, typeof(double).Assembly.GetName()),
                                new Version(1, 0))),
                    })
                }
            };
            var interactionSubjects = new Mock <IStoreInteractionSubjects>();
            {
                interactionSubjects.Setup(i => i.ProvidedSubjects())
                .Returns(providedSubjects.Keys);
                interactionSubjects.Setup(i => i.RequiredSubjects())
                .Returns(requiredSubjects.Keys);
                interactionSubjects.Setup(i => i.ContainsGroupProvisionsForSubject(It.IsAny <CommunicationSubject>()))
                .Returns <CommunicationSubject>(providedSubjects.ContainsKey);
                interactionSubjects.Setup(i => i.GroupProvisionsFor(It.IsAny <CommunicationSubject>()))
                .Returns <CommunicationSubject>(c => providedSubjects[c]);
                interactionSubjects.Setup(i => i.ContainsGroupRequirementsForSubject(It.IsAny <CommunicationSubject>()))
                .Returns <CommunicationSubject>(requiredSubjects.ContainsKey);
                interactionSubjects.Setup(i => i.GroupRequirementsFor(It.IsAny <CommunicationSubject>()))
                .Returns <CommunicationSubject>(c => requiredSubjects[c]);
            }

            var commandProxies = new Mock <IStoreRemoteCommandProxies>();
            {
                commandProxies.Setup(
                    c => c.OnReceiptOfEndpointCommands(It.IsAny <EndpointId>(), It.IsAny <IEnumerable <OfflineTypeInformation> >()))
                .Verifiable();
            }

            var notificationProxies = new Mock <IStoreRemoteNotificationProxies>();
            {
                notificationProxies.Setup(
                    n => n.OnReceiptOfEndpointNotifications(It.IsAny <EndpointId>(), It.IsAny <IEnumerable <OfflineTypeInformation> >()))
                .Verifiable();
            }

            var         wasMessageSend = false;
            SendMessage sendMessage    = (endpoint, message, retries) =>
            {
                wasMessageSend = true;

                var msg = message as EndpointInteractionInformationResponseMessage;
                Assert.IsNotNull(msg);
                Assert.AreEqual(InteractionConnectionState.Neutral, msg.State);
            };

            var wasMessageSendAndWaitedForResponse = false;
            SendMessageAndWaitForResponse sendMessageAndWaitForResponse = (endpoint, message, retries, timeout) =>
            {
                wasMessageSendAndWaitedForResponse = true;

                return(Task <ICommunicationMessage> .Factory.StartNew(
                           () => new EndpointInteractionInformationResponseMessage(remoteEndpoint, new MessageId(), InteractionConnectionState.Neutral),
                           new CancellationTokenSource().Token,
                           TaskCreationOptions.None,
                           new CurrentThreadTaskScheduler()));
            };

            var configuration = new Mock <IConfiguration>();
            {
                configuration.Setup(c => c.HasValueFor(It.IsAny <ConfigurationKey>()))
                .Returns(false);
            }

            var diagnostics = new SystemDiagnostics((l, m) => { }, null);
            var conductor   = new InteractionHandshakeConductor(
                id,
                endpointStorage.Object,
                interactionSubjects.Object,
                commandProxies.Object,
                notificationProxies.Object,
                sendMessage,
                sendMessageAndWaitForResponse,
                TimeSpan.FromMinutes(1),
                diagnostics);

            endpointStorage.Raise(e => e.OnEndpointConnected += null, new EndpointEventArgs(remoteEndpoint));
            Assert.IsTrue(wasMessageSendAndWaitedForResponse);
            Assert.IsFalse(wasMessageSend);
            commandProxies.Verify(
                c => c.OnReceiptOfEndpointCommands(It.IsAny <EndpointId>(), It.IsAny <IEnumerable <OfflineTypeInformation> >()),
                Times.Never());
            notificationProxies.Verify(
                c => c.OnReceiptOfEndpointNotifications(It.IsAny <EndpointId>(), It.IsAny <IEnumerable <OfflineTypeInformation> >()),
                Times.Never());

            conductor.ContinueHandshakeWith(
                remoteEndpoint,
                new[]
            {
                new CommunicationSubjectGroup(new CommunicationSubject("b"), new VersionedTypeFallback[0], new VersionedTypeFallback[0]),
            },
                new MessageId());
            Assert.IsTrue(wasMessageSend);
            commandProxies.Verify(
                c => c.OnReceiptOfEndpointCommands(It.IsAny <EndpointId>(), It.IsAny <IEnumerable <OfflineTypeInformation> >()),
                Times.Never());
            notificationProxies.Verify(
                c => c.OnReceiptOfEndpointNotifications(It.IsAny <EndpointId>(), It.IsAny <IEnumerable <OfflineTypeInformation> >()),
                Times.Never());
            endpointStorage.Verify(e => e.TryRemoveEndpoint(It.IsAny <EndpointId>()), Times.Once());
        }