Example #1
0
        public void ValidateDurableAbortReconnection()
        {
            IOperationDispatcher    serverDispatcher = new OperationDispatcher();
            StatelessServerEndpoint server           = new StatelessServerEndpoint(url, serverDispatcher);

            serverDispatcher.RegisterHandler <IWeakCalculator>(new WeakCalculator {
                Destroyed = () => server.Dispose()
            });
            server.Start();
            using (DurableClientConnection client = new DurableClientConnection(url))
            {
                client.ConnectionPaused = response => response.Abort = true;
                client.Open();
                IWeakCalculator calculator = client.RemoteExecutor.Create <IWeakCalculator>();
                Assert.AreEqual(4, calculator.Add(2, 2));
                calculator.Destroy();
                server = new StatelessServerEndpoint(url2, serverDispatcher);
                server.Start();
                bool exceptionThrown = false;
                try
                {
                    calculator.Add(5, 6);
                }
                catch (NotConnectedException ex)
                {
                    exceptionThrown = ex.Message == "Network connection is not opened.";
                }
                Assert.IsTrue(exceptionThrown);
                server.Dispose();
            }
        }
        /// <summary>
        /// Creates a client connection for the specified fabric address (beginning with fabric:/)
        /// </summary>
        /// <param name="fabricAddress"></param>
        /// <param name="resolver">Non-default ServicePartitionResolver</param>
        /// todo: make sure custom partitioning works (and in the process learn how custom partitioning works)
        public FabricClientConnection(Uri fabricAddress, ServicePartitionResolver resolver)
        {
            FabricAddress = fabricAddress;
            Resolver      = resolver;

            selectedEndpoint = ResolveAnyEndpoint().Result;

            clientConnection = new DurableClientConnection(selectedEndpoint.Address)
            {
                ConnectionPaused = OnConnectionPaused
            };
            clientConnection.Closed += () => Closed?.Invoke();
        }
Example #3
0
        static void Main(string[] args)
        {
            DurableConfigurator.Configure();
            // Note that using the type DurableClientConnection here is not absolutely necessary.
            // Because the transport layer provider will always provide DurableLidgrenClientChannels, the channels themselves will be durable,
            // but accessing the Durable events is a pain.
            using (var client = new DurableClientConnection("net://localhost:3133/DurableServices"))
            {
                bool stop = false;
                bool wait = false;
                client.ConnectionPaused    = response => Console.WriteLine("\tConnection lost; attempting to reconnect...");
                client.ConnectionRestored += () => Console.WriteLine("\tConnection has been restored.");
                client.ConnectionAborted  += () =>
                {
                    Console.WriteLine("\tConnection has been aborted.");
                    wait = true;
                    stop = true;
                };
                client.Closed += () => Console.WriteLine("\tConnection has been closed.");
                client.Open();
                ICalculator calculator = client.RemoteExecutor.Create <ICalculator>();

                Console.WriteLine("Sending periodic requests. Press enter to exit.");
                Task.Run(() =>
                {
                    Console.ReadLine();
                    stop = true;
                });
                while (!stop)
                {
                    int sleep = R() % 1000 + 300;
                    Task.Run(() => AsyncAdd(R() % 100, R() % 100, calculator));
                    Thread.Sleep(sleep);
                }
                if (wait)
                {
                    Console.WriteLine("\tPress enter to exit.");
                    Console.ReadLine();
                }
            }
        }
Example #4
0
        public void ValidateDurableFailoverToNewEndPoint()
        {
            IOperationDispatcher    serverDispatcher = new OperationDispatcher();
            StatelessServerEndpoint server           = new StatelessServerEndpoint(url, serverDispatcher);

            serverDispatcher.RegisterHandler <IWeakCalculator>(new WeakCalculator {
                Destroyed = () => server.Dispose()
            });
            server.Start();
            using (DurableClientConnection client = new DurableClientConnection(url))
            {
                client.ConnectionPaused = response => response.ReconnectPort = Port2;
                client.Open();
                IWeakCalculator calculator = client.RemoteExecutor.Create <IWeakCalculator>();
                Assert.AreEqual(4, calculator.Add(2, 2));
                calculator.Destroy();
                server = new StatelessServerEndpoint(url2, serverDispatcher);
                server.Start();
                Assert.AreEqual(11, calculator.Add(5, 6));
                server.Dispose();
            }
        }
Example #5
0
        static void Main(string[] args)
        {
            // todo: durable
            DurableConfigurator.Configure();
            // note that at most one process can use a single UDP port on a machine.
            // Because of this, the service fabric services exposed to the client via this port cannot be replicated
            // on local.1node
            // If you deploy to an actual service fabric cluster, then the service can be replicated on several machines
            // and reached via the load balancer. This means that if a service has a high spin up cost, your reconnection
            // time is just a combination of the timeout and the load balancer's health ping.
            // Note that you will want to have the load balancer hash on client IP (hashing on client port is not required)
            //
            // However, the ServiceFabric.Stateless executable is only reachable via the naming service, so it doesn't
            // require a dedicated port. This means that when using local.5node, there will be 5 stateless executables.
            // Thus replacing this internal client is virtually free, since it just takes talking to the naming service.
            using (var strongCalculator = new DurableClientConnection("net://localhost:3232/StrongCalculatorApplicationId"))
                using (var weakCounter = new DurableClientConnection("net://localhost:3233/WeakCounterApplicationId"))
                {
                    //strongCalculator.Open();
                    weakCounter.Open();
                    strongCalculator.ConnectionAborted     += () => Console.WriteLine("\tStrong calculator connection aborted.");
                    strongCalculator.ConnectionInterrupted += () => Console.WriteLine("\tStrong calculator connection interrupted.");
                    strongCalculator.ConnectionRestored    += () => Console.WriteLine("\tStrong calculator connection restored.");
                    weakCounter.ConnectionAborted          += () => Console.WriteLine("\tWeak counter connection aborted.");
                    weakCounter.ConnectionInterrupted      += () => Console.WriteLine("\tWeak counter connection interrupted.");
                    weakCounter.ConnectionRestored         += () => Console.WriteLine("\tWeak counter connection restored.");
                    //var calculator = strongCalculator.RemoteExecutor.Create<IWeakCalculator>();
                    var counter = weakCounter.RemoteExecutor.Create <IWeakCounter>();
                    Console.WriteLine("Connected to StrongCalculator and WeakCounter.");

                    //Console.WriteLine("4 + 5 = " + calculator.Add(4, 5));
                    //Console.WriteLine("Crashing calculator");
                    //calculator.Crash();
                    //Console.WriteLine("9 + 5 = " + calculator.Add(9, 5));
                    Console.WriteLine("Incrementing...");
                    counter.Increment();
                    Console.WriteLine("Incrementing...");
                    counter.Increment();
                    Console.WriteLine("Incrementing...");
                    counter.Increment();
                    Console.WriteLine("Incrementing...");
                    counter.Increment();
                    Console.WriteLine("Count: " + counter.GetCount());
                    Console.WriteLine("Crashing counter...");
                    counter.Crash();
                    // Wait a short while to ensure crash
                    Console.WriteLine("Sleeping to ensure service crashes before next call");
                    Thread.Sleep(1500);
                    //Console.WriteLine("3 + 2 = " + calculator.Add(3, 2));
                    Console.WriteLine("Incrementing...");
                    try
                    {
                        counter.Increment();
                        Console.WriteLine("Count: " + counter.GetCount());
                    }
                    catch (ConnectionOpenException)
                    {
                        Console.WriteLine("Connection was not re-established soon enough.");
                        Console.WriteLine("Consider increasing timeout, retry attempts, or ");
                        Console.WriteLine("decreasing time until the service comes back online.");
                        Console.WriteLine("Done. Press enter to exit.");
                        Console.ReadLine();
                        return;
                    }

                    Console.WriteLine("Count was not persisted because example service does not use persistence.");
                    Console.WriteLine("Should persistence be applied (ReliableCollections) or otherwise,");
                    Console.WriteLine("then the client would not see any issues.");

                    Console.WriteLine("Done. Press enter to exit.");
                    Console.ReadLine();
                }
        }