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); } }
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)); } }
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(); }
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); }
public MockProducerConn(IConnDelegate connDelegate) { _connDelegate = connDelegate; _closeCh = new Chan <bool>(); _pubCh = new Chan <bool>(); GoFunc.Run(router, "ProducerTest:router"); }
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."); }
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)); }
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)); }
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"); }
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"); }
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); }
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()); }
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; } } }
/// <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)); } }
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()); }
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)); }
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); } }
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); }
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(); }
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)); }
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); }
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); } }
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); }
/// <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); }
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(); }
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)); }
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); } }
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(); }
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); } }