private void BenchmarkTcp(int parallel)
        {
            string topicName = "test_benchmark_" + DateTime.Now.UnixNano();

            try
            {
                const int benchmarkNum = 30000;

                byte[] body = new byte[512];

                var p = new Producer("127.0.0.1:4150");
                p.Connect();

                var startCh = new Chan <bool>();
                var wg      = new WaitGroup();

                for (int j = 0; j < parallel; j++)
                {
                    wg.Add(1);
                    GoFunc.Run(() =>
                    {
                        startCh.Receive();
                        for (int i = 0; i < benchmarkNum / parallel; i++)
                        {
                            p.Publish(topicName, body);
                        }
                        wg.Done();
                    }, "ProducerBenchmarkTcpTest: sendLoop");
                }

                var stopwatch = Stopwatch.StartNew();
                startCh.Close();

                var done = new Chan <bool>();
                GoFunc.Run(() => { wg.Wait(); done.Send(true); }, "waiter and done sender");

                bool finished = false;
                Select
                .CaseReceive(done, b => finished = b)
                .CaseReceive(Time.After(TimeSpan.FromSeconds(10)), b => finished = false)
                .NoDefault();

                stopwatch.Stop();

                if (!finished)
                {
                    Assert.Fail("timeout");
                }

                Console.WriteLine(string.Format("{0:#,0} sent in {1:mm\\:ss\\.fff}; Avg: {2:#,0} msgs/s; Threads: {3}",
                                                benchmarkNum, stopwatch.Elapsed, benchmarkNum / stopwatch.Elapsed.TotalSeconds, parallel));

                p.Stop();
            }
            finally
            {
                _nsqdHttpClient.DeleteTopic(topicName);
                _nsqLookupdHttpClient.DeleteTopic(topicName);
            }
        }
示例#2
0
        public void ClosedChannelsWithDataShouldNotReportClosedUntilDrained()
        {
            for (var i = 0; i < 10000; i++)
            {
                var chan = new Chan <int>();

                var wait = new AutoResetEvent(false);

                GoFunc.Run(() =>
                {
                    chan.Send(1);
                    chan.Close();
                }, "send");

                bool ok = false, ok2 = false;
                int  actual = -1, actual2 = -1;

                GoFunc.Run(() =>
                {
                    actual  = chan.ReceiveOk(out ok);
                    actual2 = chan.ReceiveOk(out ok2);
                    wait.Set();
                }, "receive");

                wait.WaitOne();

                Assert.AreEqual(true, ok, string.Format("ok iteration {0}", i));
                Assert.AreEqual(1, actual, string.Format("actual iteration {0}", i));
                Assert.AreEqual(false, ok2, string.Format("ok2 iteration {0}", i));
                Assert.AreEqual(default(int), actual2, string.Format("actual2 iteration {0}", i));
            }
        }
示例#3
0
        private void listen()
        {
            tcpListener = new TcpListener(ipAddr, listenPort);
            tcpAddr     = tcpListener.LocalEndpoint.ToString();
            tcpListener.Start();

            Console.WriteLine("[{0}] TCP: listening on {1}", DateTime.Now.Formatted(), tcpListener.LocalEndpoint);

            while (true)
            {
                TcpClient conn;
                try
                {
                    conn = tcpListener.AcceptTcpClient();
                }
                catch
                {
                    break;
                }
                var remoteEndPoint = conn.Client.RemoteEndPoint;
                GoFunc.Run(() => handle(conn, remoteEndPoint), "mockNSQD:handle");
            }

            Console.WriteLine("[{0}] TCP: closing {1}", DateTime.Now.Formatted(), tcpListener.LocalEndpoint);
            exitChan.Close();
        }
示例#4
0
        public void TwoSelectsSendAndReceiveCanTalk()
        {
            var c = new Chan <int>();

            var actual = 0;

            var wg = new WaitGroup();

            wg.Add(2);

            GoFunc.Run(() =>
            {
                Select
                .CaseSend(c, 7)
                .NoDefault();

                wg.Done();
            }, "sender");

            GoFunc.Run(() =>
            {
                Select
                .CaseReceive(c, o => actual = o)
                .NoDefault();

                wg.Done();
            }, "receiver");

            wg.Wait();

            Assert.AreEqual(7, actual);
        }
示例#5
0
 public MockProducerConn(IConnDelegate connDelegate)
 {
     _connDelegate = connDelegate;
     _closeCh      = new Chan <bool>();
     _pubCh        = new Chan <bool>();
     GoFunc.Run(router, "ProducerTest:router");
 }
示例#6
0
        public void Stop()
        {
            Trace.WriteLine("Stopping...");

            // Stop all Consumers

            var wg = new WaitGroup();

            foreach (var topicChannelHandler in _topicChannelHandlers)
            {
                foreach (var item in topicChannelHandler.Value)
                {
                    var consumer = item.Consumer;
                    if (consumer != null)
                    {
                        wg.Add(1);
                        GoFunc.Run(() =>
                        {
                            consumer.Stop();
                            wg.Done();
                        }, "NsqBus consumer shutdown");
                    }
                }
            }

            wg.Wait();

            _nsqdPublisher.Stop();

            Trace.WriteLine("Stopped.");
        }
示例#7
0
        public void TestTcpConnWriteAfterClose()
        {
            var tcpListener = new TcpListener(IPAddress.Loopback, 4193);

            tcpListener.Start();

            var wg = new WaitGroup();

            wg.Add(1);

            GoFunc.Run(() =>
            {
                var tcpClient = tcpListener.AcceptTcpClientAsync().Result;

                using (var rdr = new BinaryReader(tcpClient.GetStream()))
                    using (var connw = new BinaryWriter(tcpClient.GetStream()))
                    {
                        while (true)
                        {
                            var readMsg = ReadBytes(rdr, (byte)'\n');
                            if (readMsg.SequenceEqual(Encoding.UTF8.GetBytes("QUIT\n")))
                            {
                                break;
                            }
                            connw.Write(readMsg);
                        }
                    }

                tcpClient.Dispose();
                wg.Done();
            }, "TcpConnTest read loop");

            var tcpConn = new TcpConn(IPAddress.Loopback.ToString(), 4193);

            var helloMsg = Encoding.UTF8.GetBytes("Hello\n");

            tcpConn.Write(helloMsg, 0, helloMsg.Length);

            var recv = new byte[helloMsg.Length];

            tcpConn.Read(recv);
            Console.WriteLine(Encoding.UTF8.GetString(recv));

            var quitMsg = Encoding.UTF8.GetBytes("QUIT\n");

            tcpConn.Write(quitMsg, 0, quitMsg.Length);

            recv = new byte[quitMsg.Length];
            tcpConn.Read(recv);
            Console.WriteLine(Encoding.UTF8.GetString(recv));

            wg.Wait();

            tcpConn.Close();

            AssertHelper.Throws <ConnectionClosedException>(() => tcpConn.Write(quitMsg, 0, quitMsg.Length));
        }
示例#8
0
        public void TestTickerLoopWithNemesisChan()
        {
            var start  = DateTime.Now;
            var ticker = new Ticker(TimeSpan.FromSeconds(1));

            var listOfTimes        = new List <TimeSpan>();
            var exitChan           = new Chan <bool>();
            var lookupdRecheckChan = new Chan <bool>();
            var doLoop             = true;

            using (var select =
                       Select
                       .CaseReceive(ticker.C,
                                    o =>
            {
                Console.WriteLine("Received tick");
                listOfTimes.Add(DateTime.Now - start);

                if (listOfTimes.Count == 5)
                {
                    GoFunc.Run(() => lookupdRecheckChan.Send(true), "lookupd recheck sender");
                }
            })
                       .CaseReceive(lookupdRecheckChan,
                                    o =>
            {
                Console.WriteLine("Nemesis");
                Thread.Sleep(5000);
            })
                       .CaseReceive(exitChan, o => doLoop = false)
                       .NoDefault(true))
            {
                // ReSharper disable once LoopVariableIsNeverChangedInsideLoop
                while (doLoop)
                {
                    select.Execute();
                    if (listOfTimes.Count >= 10)
                    {
                        GoFunc.Run(() => exitChan.Send(true), "exit notifier");
                    }
                }
            }

            ticker.Stop();

            var duration = DateTime.Now - start;

            Console.WriteLine("Duration: {0}", duration);
            foreach (var time in listOfTimes)
            {
                Console.WriteLine("Tick: {0}", time);
            }

            Assert.AreEqual(10, listOfTimes.Count, "listOfTimes.Count");
            AssertHelper.GreaterOrEqual(duration, TimeSpan.FromSeconds(14) - AcceptableError, "duration");
            AssertHelper.Less(duration, TimeSpan.FromSeconds(17));
        }
示例#9
0
 public mockNSQD(instruction[] script, IPAddress addr, int port)
 {
     this.script = script;
     exitChan    = new Chan <int>();
     got         = new List <byte[]>();
     gotTime     = new List <DateTime>();
     ipAddr      = addr;
     listenPort  = port;
     GoFunc.Run(listen, "mockNSQD:listen");
 }
示例#10
0
        public mockNSQD(instruction[] script, IPAddress addr, int port = 0)
        {
            this.script = script;
            exitChan    = new Chan <int>();
            got         = new List <byte[]>();
            gotTime     = new List <DateTime>();
            ipAddr      = addr;
            tcpListener = new TcpListener(ipAddr, port);
            tcpListener.Start();
            tcpAddr    = tcpListener.LocalEndpoint.ToString();
            listenPort = ((IPEndPoint)tcpListener.LocalEndpoint).Port;

            GoFunc.Run(listen, "mockNSQD:listen");
        }
示例#11
0
        public void BufferedChannelsSelectSendAndReceiveInGoroutine()
        {
            var c = new Chan <int>(10);

            var list = new List <int>();
            var wg   = new WaitGroup();

            wg.Add(2);

            GoFunc.Run(() =>
            {
                var doLoop = true;
                while (doLoop)
                {
                    Select
                    .CaseReceiveOk(c, (i, ok) =>
                    {
                        if (ok)
                        {
                            list.Add(i);
                        }
                        else
                        {
                            doLoop = false;
                        }
                    })
                    .NoDefault();
                }

                wg.Done();
            }, "bufferChannelsTest:receiveLoop");

            GoFunc.Run(() =>
            {
                for (var i = 0; i < 10; i++)
                {
                    Select
                    .CaseSend(c, i)
                    .NoDefault();
                }

                c.Close();
                wg.Done();
            }, "bufferedChannelsTest:sendLoop");

            wg.Wait();

            AssertHelper.AreEqual(new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, list);
        }
示例#12
0
        public void BufferedChannelsSelectSendInGoroutine()
        {
            var c = new Chan <int>(10);

            var list = new List <int>();
            var wg   = new WaitGroup();

            wg.Add(1);

            GoFunc.Run(() =>
            {
                for (int i = 0; i < 10; i++)
                {
                    Select
                    .CaseSend(c, i)
                    .NoDefault();
                }

                c.Close();
                wg.Done();
            }, "bufferedChannelsTest:sendLoop");

            wg.Wait();

            bool doLoop = true;

            // ReSharper disable once LoopVariableIsNeverChangedInsideLoop
            while (doLoop)
            {
                Select
                .CaseReceiveOk(c, (i, ok) =>
                {
                    if (ok)
                    {
                        list.Add(i);
                    }
                    else
                    {
                        doLoop = false;
                    }
                })
                .NoDefault();
            }

            Assert.AreEqual(new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, list.ToArray());
        }
示例#13
0
        private void sendCommandAsync(Command cmd, Chan <ProducerResponse> doneChan, params object[] args)
        {
            ProducerResponse t = null;

            try
            {
                if (_state != (int)State.Connected)
                {
                    Connect();
                }

                // keep track of how many outstanding producers we're dealing with
                // in order to later ensure that we clean them all up...
                Interlocked.Increment(ref _concurrentProducers);

                t = new ProducerResponse
                {
                    _cmd      = cmd,
                    _doneChan = doneChan,
                    Args      = args
                };

                Select
                .CaseSend(_transactionChan, t)
                .CaseReceive(_exitChan, _throwErrStoppedAction)
                .NoDefault();

                Interlocked.Decrement(ref _concurrentProducers);
            }
            catch (Exception ex)
            {
                if (t != null)
                {
                    Interlocked.Decrement(ref _concurrentProducers);
                    t.Error = ex;
                    GoFunc.Run(() => t.finish(), "Producer: t.finish()");
                }
                else
                {
                    Thread.Sleep(1000); // slow down hammering Connect
                    throw;
                }
            }
        }
示例#14
0
        /// <summary>
        ///     Connects to nsqd. Calling this method is optional; otherwise, Connect will be lazy invoked when Publish is
        ///     called.
        /// </summary>
        /// <exception cref="ErrStopped">Thrown if the Producer has been stopped.</exception>
        /// <exception cref="ErrNotConnected">Thrown if the Producer is currently waiting to close and reconnect.</exception>
        public void Connect()
        {
            lock (_guard)
            {
                if (_stopFlag == 1)
                {
                    throw new ErrStopped();
                }

                switch (_state)
                {
                case (int)State.Init:
                    break;

                case (int)State.Connected:
                    return;

                default:
                    throw new ErrNotConnected();
                }

                log(LogLevel.Info, string.Format("{0} connecting to nsqd", _addr));

                _conn = _connFactory(this);
                _conn.SetLogger(_logger, string.Format("P{0} ({{0}})", _id));
                try
                {
                    _conn.Connect();
                }
                catch (Exception ex)
                {
                    log(LogLevel.Error, string.Format("({0}) error connecting to nsqd - {1}", _addr, ex.Message));
                    _conn.Close();
                    throw;
                }

                _state     = (int)State.Connected;
                _closeChan = new Chan <int>();
                _wg.Add(1);
                log(LogLevel.Info, string.Format("{0} connected to nsqd", _addr));
                GoFunc.Run(router, string.Format("Producer:router P{0}", _id));
            }
        }
示例#15
0
        public void BufferedChannelsReceiveSelectInGoroutineSendOnMainThread()
        {
            var c = new Chan <int>(10);

            var list = new List <int>();
            var wg   = new WaitGroup();

            wg.Add(1);

            GoFunc.Run(() =>
            {
                bool doLoop = true;
                while (doLoop)
                {
                    Select
                    .CaseReceiveOk(c, (i, ok) =>
                    {
                        if (ok)
                        {
                            list.Add(i);
                        }
                        else
                        {
                            doLoop = false;
                        }
                    })
                    .NoDefault();
                }

                wg.Done();
            }, "bufferChannelsTest:receiveLoop");

            for (int i = 0; i < 10; i++)
            {
                c.Send(i);
            }

            c.Close();

            wg.Wait();

            Assert.AreEqual(new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }, list.ToArray());
        }
示例#16
0
        private void close()
        {
            const int newValue  = (int)State.Disconnected;
            const int comparand = (int)State.Connected;

            if (Interlocked.CompareExchange(ref _state, newValue, comparand) != comparand)
            {
                return;
            }

            _conn.Close();

            GoFunc.Run(() =>
            {
                // we need to handle this in a goroutine so we don't
                // block the caller from making progress
                _wg.Wait();
                _state = (int)State.Init;
            }, string.Format("Producer:close P{0}", _id));
        }
示例#17
0
        private void BenchmarkHttp(int parallel)
        {
            string topicName = "test_benchmark_" + DateTime.Now.UnixNano();

            try
            {
                const int benchmarkNum = 30000;

                byte[] body = new byte[512];

                var startCh = new Chan <bool>();
                var wg      = new WaitGroup();

                for (int j = 0; j < parallel; j++)
                {
                    wg.Add(1);
                    GoFunc.Run(() =>
                    {
                        startCh.Receive();
                        for (int i = 0; i < benchmarkNum / parallel; i++)
                        {
                            _nsqdHttpClient.Publish(topicName, body);
                        }
                        wg.Done();
                    }, "ProducerBenchmarkHttpTest: sendLoop");
                }

                var stopwatch = Stopwatch.StartNew();
                startCh.Close();
                wg.Wait();
                stopwatch.Stop();

                Console.WriteLine(string.Format("{0:#,0} sent in {1:mm\\:ss\\.fff}; Avg: {2:#,0} msgs/s; Threads: {3}",
                                                benchmarkNum, stopwatch.Elapsed, benchmarkNum / stopwatch.Elapsed.TotalSeconds, parallel));
            }
            finally
            {
                _nsqdHttpClient.DeleteTopic(topicName);
                _nsqLookupdHttpClient.DeleteTopic(topicName);
            }
        }
示例#18
0
        public void TestTimerStopRaceCondition()
        {
            // NOTE: This race condition was difficult to reproduce in Release but occurs
            //       almost immediately in Debug.

            var wg   = new WaitGroup();
            var rand = new Random();

            var passed = true;

            const int tries = 1000;

            wg.Add(tries);
            for (int i = 0; i < tries; i++)
            {
                GoFunc.Run(() =>
                {
                    try
                    {
                        var time  = rand.Next(1, 2500);
                        var timer = new Timer(TimeSpan.FromMilliseconds(time));
                        Time.AfterFunc(TimeSpan.FromMilliseconds(time), () => timer.Stop());
                        timer.C.Receive();
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex);
                        passed = false;
                    }
                    wg.Done();
                }, string.Format("timer {0}", i));
            }
            wg.Wait();

            Assert.IsTrue(passed);
        }
示例#19
0
        private void listen()
        {
            var addr = tcpListener.LocalEndpoint;

            Console.WriteLine("[{0}] TCP: listening on {1}", DateTime.Now.Formatted(), addr);

            while (true)
            {
                TcpClient conn;
                try
                {
                    conn = tcpListener.AcceptTcpClientAsync().Result;
                }
                catch
                {
                    break;
                }
                var remoteEndPoint = conn.Client.RemoteEndPoint;
                GoFunc.Run(() => handle(conn, remoteEndPoint), "mockNSQD:handle");
            }

            Console.WriteLine("[{0}] TCP: closing {1}", DateTime.Now.Formatted(), addr);
            exitChan.Close();
        }
示例#20
0
        public void TestTickerLoopWithExitChan()
        {
            var start  = DateTime.Now;
            var ticker = new Ticker(TimeSpan.FromSeconds(1));

            var  listOfTimes        = new List <TimeSpan>();
            var  exitChan           = new Chan <bool>();
            var  lookupdRecheckChan = new Chan <bool>();
            bool doLoop             = true;

            using (var select =
                       Select
                       .CaseReceive(ticker.C, o => listOfTimes.Add(DateTime.Now - start))
                       .CaseReceive(lookupdRecheckChan, o => listOfTimes.Add(DateTime.Now - start))
                       .CaseReceive(exitChan, o => doLoop = false)
                       .NoDefault(defer: true))
            {
                // ReSharper disable once LoopVariableIsNeverChangedInsideLoop
                while (doLoop)
                {
                    select.Execute();
                    if (listOfTimes.Count >= 10)
                    {
                        GoFunc.Run(() => exitChan.Send(true), "exit notifier");
                    }
                }
            }

            ticker.Stop();

            var duration = DateTime.Now - start;

            Assert.AreEqual(10, listOfTimes.Count, "listOfTimes.Count");
            Assert.GreaterOrEqual(duration, TimeSpan.FromSeconds(10), "duration");
            Assert.Less(duration, TimeSpan.FromSeconds(11));
        }
示例#21
0
        public void MultiThreadedSelectTestWithDefer()
        {
            var c1    = new Chan <int>();
            var c2    = new Chan <int>();
            var done  = new Chan <bool>();
            var start = new Chan <bool>();

            int c1Count = 0;
            int c2Count = 0;

            int count         = 0;
            int totalReceived = 0;

            Action receive = () =>
            {
                start.Receive();

                int  val1   = 0;
                int  val2   = 0;
                bool doLoop = true;

                var select =
                    Select
                    .CaseReceive(c1, i => val1     = i)
                    .CaseReceive(c2, i => val2     = i)
                    .CaseReceive(done, b => doLoop = false)
                    .NoDefault(defer: true);

                while (doLoop)
                {
                    val1 = 0;
                    val2 = 0;

                    select.Execute();

                    if (doLoop)
                    {
                        Assert.IsTrue(val1 == 0 || val2 == 0, "val1 == 0 || val2 == 0");
                        Assert.IsTrue(val1 == 1 || val2 == 2, "val1 == 1 || val2 == 2");
                    }

                    Interlocked.Increment(ref totalReceived);
                }
            };

            Action send = () =>
            {
                start.Receive();

                var select =
                    Select
                    .CaseSend(c1, 1, () => Interlocked.Increment(ref c1Count))
                    .CaseSend(c2, 2, () => Interlocked.Increment(ref c2Count))
                    .NoDefault(defer: true);

                while (count < 30000)
                {
                    Interlocked.Increment(ref count);
                    select.Execute();
                }

                done.Close();
            };

            for (int i = 0; i < 8; i++)
            {
                GoFunc.Run(receive, "receiver");
                GoFunc.Run(send, "sender");
            }

            start.Close();
            done.Receive();

            Assert.GreaterOrEqual(count, 30000);
            Assert.Greater(totalReceived, 29900);
        }
示例#22
0
        private void TestProducerReconnect(int publishingThreads, int millisecondsBetweenNsqdShutdown, int shutdownCount)
        {
            string topicName = string.Format("test_producerreconnect_{0}", DateTime.Now.UnixNano());

            _nsqdHttpClient.CreateTopic(topicName);
            _nsqLookupdHttpClient.CreateTopic(topicName);
            try
            {
                var payload   = new byte[512];
                var publisher = new Producer("127.0.0.1:4150", new ConsoleLogger(LogLevel.Info), new Config());

                bool running = true;

                for (int i = 0; i < publishingThreads; i++)
                {
                    GoFunc.Run(() =>
                    {
                        while (running)
                        {
                            try
                            {
                                publisher.PublishAsync(topicName, payload);
                            }
                            catch
                            {
                            }
                        }
                    }, string.Format("producer thread {0:00}/{1:00}", i + 1, publishingThreads));
                }

                string errorMessage = null;

                var wg = new WaitGroup();
                wg.Add(1);
                GoFunc.Run(() =>
                {
                    for (int i = 0; i < shutdownCount; i++)
                    {
                        Thread.Sleep(millisecondsBetweenNsqdShutdown);

                        Console.WriteLine("Stopping nsqd {0}/{1}...", i + 1, shutdownCount);
                        var p             = new ProcessStartInfo("net", "stop nsqd");
                        p.CreateNoWindow  = true;
                        p.UseShellExecute = false;
                        Process.Start(p).WaitForExit();

                        Console.WriteLine("Starting nsqd {0}/{1}...", i + 1, shutdownCount);
                        p = new ProcessStartInfo("net", "start nsqd");
                        p.CreateNoWindow  = true;
                        p.UseShellExecute = false;
                        Process.Start(p).WaitForExit();

                        Console.WriteLine("Attempting publish...");

                        // test the waters
                        int tries;
                        for (tries = 0; ; tries++)
                        {
                            try
                            {
                                publisher.Publish(topicName, payload);
                                break;
                            }
                            catch (Exception ex)
                            {
                                Console.WriteLine(ex.Message);
                                Thread.Sleep(1000);

                                if (tries == 60)
                                {
                                    errorMessage = string.Format("Producer not accepting Publish requests.\n" +
                                                                 "Producer Threads: {0}\nTime between NSQd shutdowns:{1}ms\n" +
                                                                 "Shutdown Count: {2}/{3}\nLast Exception Message: {4}", publishingThreads,
                                                                 millisecondsBetweenNsqdShutdown, i + 1, shutdownCount, ex.Message);
                                    Console.WriteLine(errorMessage);
                                    wg.Done();
                                    return;
                                }
                            }
                        }
                        Console.WriteLine("Successful publish on attempt #{0}", tries + 1);
                    }
                    wg.Done();
                }, "nsqd restart thread");

                wg.Wait();
                running = false;

                if (!string.IsNullOrEmpty(errorMessage))
                {
                    Assert.Fail(errorMessage);
                }

                Console.WriteLine("Starting test publishing of 1000 messages...");

                for (int j = 0; j < 1000; j++)
                {
                    publisher.Publish(topicName, payload);
                }

                Console.WriteLine("Done.");
            }
            finally
            {
                var p = new ProcessStartInfo("net", "start nsqd");
                p.CreateNoWindow  = true;
                p.UseShellExecute = false;
                Process.Start(p).WaitForExit();

                _nsqdHttpClient.DeleteTopic(topicName);
                _nsqLookupdHttpClient.DeleteTopic(topicName);
            }
        }
示例#23
0
        public void MultiThreadedSelectTestWithoutDefer()
        {
            var c1    = new Chan <int>();
            var c2    = new Chan <int>();
            var done  = new Chan <bool>();
            var start = new Chan <bool>();

            var c1Count = 0;
            var c2Count = 0;

            var count         = 0;
            var totalReceived = 0;

            Action receive = () =>
            {
                start.Receive();

                var val1   = 0;
                var val2   = 0;
                var doLoop = true;

                while (doLoop)
                {
                    val1 = 0;
                    val2 = 0;

                    Select
                    .CaseReceive(c1, i => val1     = i)
                    .CaseReceive(c2, i => val2     = i)
                    .CaseReceive(done, b => doLoop = false)
                    .NoDefault();

                    if (doLoop)
                    {
                        Assert.IsTrue(val1 == 0 || val2 == 0, "val1 == 0 || val2 == 0");
                        Assert.IsTrue(val1 == 1 || val2 == 2, "val1 == 1 || val2 == 2");
                    }

                    Interlocked.Increment(ref totalReceived);
                }
            };

            Action send = () =>
            {
                start.Receive();

                while (count < 10000)
                {
                    Interlocked.Increment(ref count);

                    Select
                    .CaseSend(c1, 1, () => Interlocked.Increment(ref c1Count))
                    .CaseSend(c2, 2, () => Interlocked.Increment(ref c2Count))
                    .NoDefault();

                    Select
                    .CaseSend(c2, 2, () => Interlocked.Increment(ref c2Count))
                    .CaseSend(c1, 1, () => Interlocked.Increment(ref c1Count))
                    .NoDefault();
                }

                done.Close();
            };

            for (var i = 0; i < 8; i++)
            {
                GoFunc.Run(receive, "receiver");
                GoFunc.Run(send, "sender");
            }

            start.Close();
            done.Receive();

            Assert.IsTrue(count >= 10000);
            Assert.IsTrue(totalReceived > 19900);
        }
示例#24
0
        /// <summary>
        /// Connect dials and bootstraps the nsqd connection
        /// (including IDENTIFY) and returns the IdentifyResponse
        /// </summary>
        public IdentifyResponse Connect()
        {
            var conn = Net.DialTimeout("tcp", _addr, _config.DialTimeout);

            _conn = (ITcpConn)conn;
            if (_conn == null)
            {
                throw new Exception("Net.DialTimeout returned null");
            }
            _r = conn;
            _w = conn;

            _conn.ReadTimeout  = _config.ReadTimeout;
            _conn.WriteTimeout = _config.WriteTimeout;

            try
            {
                Write(Protocol.MagicV2, 0, Protocol.MagicV2.Length);
            }
            catch (Exception ex)
            {
                _conn.Close();
                throw new Exception(string.Format("[{0}] failed to write magic - {1}", _addr, ex.Message), ex);
            }

            IdentifyResponse resp;

            try
            {
                resp = identify();
            }
            catch (ErrIdentify ex)
            {
                if (_addr.Contains(":4151"))
                {
                    throw new ErrIdentify("Error connecting to nsqd. It looks like you tried to connect to the HTTP port " +
                                          "(4151), use the TCP port (4150) instead.", ex);
                }
                else if (_addr.Contains(":4160") || _addr.Contains(":4161"))
                {
                    throw new ErrIdentify("Error connecting to nsqd. It looks like you tried to connect to nsqlookupd. " +
                                          "Producers must connect to nsqd over TCP (4150). Consumers can connect to nsqd over TCP (4150) using " +
                                          "Consumer.ConnectToNsqd or to nsqlookupd (4161) using Consumer.ConnectToNsqLookupd.", ex);
                }
                throw;
            }

            if (resp != null && resp.AuthRequired)
            {
                if (string.IsNullOrEmpty(_config.AuthSecret))
                {
                    log(LogLevel.Error, "Auth Required");
                    throw new Exception("Auth Required");
                }
                auth(_config.AuthSecret);
            }

            _wg.Add(2);
            _readLoopRunning = 1;
            GoFunc.Run(readLoop, "Conn:readLoop");
            GoFunc.Run(writeLoop, "Conn:writeLoop");
            return(resp);
        }
示例#25
0
        private void handle(TcpClient conn, EndPoint remoteEndPoint)
        {
            int idx = 0;

            Console.WriteLine("[{0}] TCP: new client({1})", DateTime.Now.Formatted(), remoteEndPoint);

            using (var rdr = new BinaryReader(conn.GetStream()))
                using (var connw = new BinaryWriter(conn.GetStream()))
                {
                    rdr.ReadBytes(4);

                    var readChan     = new Chan <byte[]>();
                    var readDoneChan = new Chan <int>();
                    var scriptTime   = Time.After(script[0].delay);

                    GoFunc.Run(() =>
                    {
                        while (true)
                        {
                            try
                            {
                                var line = ReadBytes(rdr, (byte)'\n');
                                // trim the '\n'
                                line = line.Take(line.Length - 1).ToArray();
                                readChan.Send(line);
                                readDoneChan.Receive();
                            }
                            catch
                            {
                                return;
                            }
                        }
                    }, "mockNSQD:ReadBytes");

                    int  rdyCount = 0;
                    bool doLoop   = true;

                    while (doLoop && idx < script.Length)
                    {
                        Select
                        .CaseReceive(readChan, line =>
                        {
                            string strLine = Encoding.UTF8.GetString(line);
                            Console.WriteLine("[{0}] mock: '{1}'", DateTime.Now.Formatted(), strLine);
                            got.Add(line);
                            gotTime.Add(DateTime.Now);
                            var args = strLine.Split(' ');
                            switch (args[0])
                            {
                            case "IDENTIFY":
                                try
                                {
                                    byte[] l = rdr.ReadBytes(4);
                                    int size = Binary.BigEndian.Int32(l);
                                    byte[] b = rdr.ReadBytes(size);

                                    Console.WriteLine(string.Format("[{0}] {1}",
                                                                    DateTime.Now.Formatted(), Encoding.UTF8.GetString(b)));
                                }
                                catch (Exception ex)
                                {
                                    Console.WriteLine(ex.ToString());
                                    doLoop = false;
                                    throw;
                                }
                                break;

                            case "RDY":
                                int rdy  = int.Parse(args[1]);
                                rdyCount = rdy;
                                break;
                            }
                            readDoneChan.Send(1);
                        })
                        .CaseReceive(scriptTime, o =>
                        {
                            bool doWrite = true;
                            var inst     = script[idx];
                            if (inst.body.SequenceEqual(Encoding.UTF8.GetBytes("exit")))
                            {
                                doLoop  = false;
                                doWrite = false;
                            }
                            if (inst.frameType == (int)FrameType.Message)
                            {
                                if (rdyCount == 0)
                                {
                                    Console.WriteLine("[{0}] !!! RDY == 0", DateTime.Now.Formatted());
                                    scriptTime = Time.After(script[idx + 1].delay);
                                    doWrite    = false;
                                }
                                else
                                {
                                    rdyCount--;
                                }
                            }

                            if (doWrite)
                            {
                                try
                                {
                                    connw.Write(framedResponse(inst.frameType, inst.body));
                                    scriptTime = Time.After(script[idx + 1].delay);
                                    idx++;
                                }
                                catch (Exception ex)
                                {
                                    Console.WriteLine(ex.ToString());
                                    doLoop = false;
                                }
                            }
                        })
                        .NoDefault();
                    }
                }

            tcpListener.Stop();
            conn.Close();
        }
示例#26
0
        public void TestTickerLoopWithNemesisBufferedChan()
        {
            var start  = DateTime.Now;
            var ticker = new Ticker(TimeSpan.FromSeconds(1));

            int  x                  = 0;
            var  listOfTimes        = new List <TimeSpan>();
            var  exitChan           = new Chan <bool>();
            var  lookupdRecheckChan = new Chan <bool>(bufferSize: 1);
            bool doLoop             = true;

            using (var select =
                       Select
                       .CaseReceive(ticker.C,
                                    o =>
            {
                Console.WriteLine("Received tick");
                listOfTimes.Add(DateTime.Now - start);

                if (listOfTimes.Count == 5)
                {
                    Select
                    .CaseSend(lookupdRecheckChan, true)
                    .NoDefault(defer: false);
                }
            })
                       .CaseReceive(lookupdRecheckChan,
                                    o =>
            {
                Console.WriteLine("Nemesis");
                for (int i = 0; i < 5; i++)
                {
                    Thread.Sleep(1000);
                    Console.Write(".");
                }
                Console.WriteLine();
            })
                       .CaseReceive(exitChan, o => doLoop = false)
                       .NoDefault(defer: true))
            {
                // ReSharper disable once LoopVariableIsNeverChangedInsideLoop
                while (doLoop)
                {
                    Console.WriteLine("start {0}", x);
                    if (x == 7)
                    {
                        Console.WriteLine("pause");
                    }
                    select.Execute();
                    Console.WriteLine("finish {0}", x);
                    x++;
                    if (listOfTimes.Count >= 10)
                    {
                        GoFunc.Run(() => exitChan.Send(true), "exit notifier");
                    }
                }
            }

            ticker.Stop();

            var duration = DateTime.Now - start;

            Console.WriteLine(duration);
            Assert.AreEqual(10, listOfTimes.Count, "listOfTimes.Count");
            Assert.GreaterOrEqual(duration, TimeSpan.FromSeconds(14), "duration");
            Assert.Less(duration, TimeSpan.FromSeconds(17));
        }
示例#27
0
        public void TestBusShutdown()
        {
            string       topicName   = string.Format("test_busshutdown_{0}", DateTime.Now.UnixNano());
            const string channelName = "test_busshutdown";

            var container = new Container();

            _nsqdHttpClient.CreateTopic(topicName);
            _nsqLookupdHttpClient.CreateTopic(topicName);

            try
            {
                BusService.Start(new BusConfiguration(
                                     new StructureMapObjectBuilder(container),
                                     new NewtonsoftJsonSerializer(typeof(JsonConverter).Assembly),
                                     new MessageAuditorStub(),
                                     new MessageTypeToTopicDictionary(new Dictionary <Type, string> {
                    { typeof(TestMessage), topicName }
                }),
                                     new HandlerTypeToChannelDictionary(new Dictionary <Type, string> {
                    { typeof(TestMessageHandler), channelName }
                }),
                                     defaultNsqLookupdHttpEndpoints: new[] { "127.0.0.1:4161" },
                                     defaultThreadsPerHandler: 1,
                                     nsqConfig: new Config
                {
                    LookupdPollJitter   = 0,
                    LookupdPollInterval = TimeSpan.FromSeconds(1)
                }
                                     ));

                var bus = container.GetInstance <IBus>();

                _wg.Add(1);
                bus.Send(new TestMessage());
                _wg.Wait();

                var stoppedChan = new Chan <bool>(1);
                GoFunc.Run(() =>
                {
                    var start = DateTime.Now;
                    BusService.Stop();
                    Console.WriteLine(string.Format("Shutdown occurred in {0}", DateTime.Now - start));
                    stoppedChan.Send(true);
                }, "bus stopper and stopped notifier");

                bool timeout = false;
                Select
                .CaseReceive(stoppedChan, o => { })
                .CaseReceive(Time.After(TimeSpan.FromMilliseconds(90000)), o => { timeout = true; })
                .NoDefault();

                Assert.IsFalse(timeout, "timeout");
                Assert.IsFalse(_handlerFinished, "handlerFinished");
            }
            finally
            {
                _nsqdHttpClient.DeleteTopic(topicName);
                _nsqLookupdHttpClient.DeleteTopic(topicName);
            }
        }
示例#28
0
        private void transactionCleanup()
        {
            // clean up transactions we can easily account for
            var wg = new WaitGroup();

            wg.Add(_transactions.Count);
            foreach (var t in _transactions)
            {
                var t1 = t;
                GoFunc.Run(() =>
                {
                    t1.Error = new ErrNotConnected();
                    t1.finish();
                    wg.Done();
                }, "transactionCleanup: drain _transactions");
            }
            _transactions.Clear();

            // spin and free up any writes that might have raced
            // with the cleanup process (blocked on writing
            // to transactionChan)

            // give the runtime a chance to schedule other racing goroutines
            var  ticker = new Ticker(TimeSpan.FromMilliseconds(100));
            bool doLoop = true;

            using (var select =
                       Select
                       .CaseReceive(_transactionChan, t =>
            {
                wg.Add(1);
                GoFunc.Run(() =>
                {
                    t.Error = new ErrNotConnected();
                    t.finish();
                    wg.Done();
                }, "transactionCleanup: finish transaction from _transactionChan");
            })
                       .CaseReceive(ticker.C, _ =>
            {
                // keep spinning until there are 0 concurrent producers
                if (_concurrentProducers == 0)
                {
                    doLoop = false;
                    return;
                }
                log(LogLevel.Warning, string.Format(
                        "waiting for {0} concurrent producers to finish", _concurrentProducers));
            })
                       .NoDefault(defer: true)
                   )
            {
                while (doLoop)
                {
                    select.Execute();
                }
            }
            ticker.Close();

            wg.Wait();
        }
示例#29
0
        public void StartBus()
        {
            // TODO: Needs to move to NsqBus. See below comment about async bus start.
            // TODO: This also makes an assumption nsqd is running locally on port 4151. Convenient for testing and sample
            // TODO: apps, probably shouldn't be used in PROD. This needs to be thought through.
            if (_preCreateTopicsAndChannels)
            {
                const string nsqdHttpAddress = "127.0.0.1:4151";
                var          nsqdHttpClient  = new NsqdHttpClient(nsqdHttpAddress, TimeSpan.FromSeconds(5));

                var wg = new WaitGroup();
                foreach (var tch in GetHandledTopics())
                {
                    foreach (var channel in tch.Channels)
                    {
                        string localTopic   = tch.Topic;
                        string localChannel = channel;

                        wg.Add(1);
                        GoFunc.Run(() =>
                        {
                            try
                            {
                                nsqdHttpClient.CreateTopic(localTopic);
                                nsqdHttpClient.CreateChannel(localTopic, localChannel);
                            }
                            catch (Exception ex)
                            {
                                _nsqLogger.Output(LogLevel.Error,
                                                  string.Format("error creating topic/channel on {0} - {1}", nsqdHttpAddress, ex));
                            }

                            wg.Done();
                        }, "BusConfiguration pre-create topics/channels");
                    }
                }

                wg.Wait();
            }

            if (_busStateChangedHandler != null)
            {
                _busStateChangedHandler.OnBusStarting(this);
            }

            _bus = new NsqBus(
                _topicChannelHandlers,
                _dependencyInjectionContainer,
                _messageTypeToTopicProvider,
                _defaultMessageSerializer,
                _nsqLogger,
                _messageMutator,
                _messageTopicRouter,
                _nsqdPublisher
                );

            _bus.Start();

            // TODO: BusConfiguration should not be responsible for these callbacks. With an async _bus.Start
            // TODO: this will need to be moved to NsqBus.
            if (_busStateChangedHandler != null)
            {
                _busStateChangedHandler.OnBusStarted(this, _bus);
            }
        }