public void ctor_ValidParameter_ShouldReturnWorker() { var session = new MDPWorker ("tcp://127.0.0.1:5555", "test"); Assert.That (session, Is.Not.Null); Assert.That (session.HeartbeatDelay, Is.EqualTo (TimeSpan.FromMilliseconds (2500))); Assert.That (session.ReconnectDelay, Is.EqualTo (TimeSpan.FromMilliseconds (2500))); }
public void ReceiveImplicitConnect_ValidScenario_ShouldReturnRequest() { const string hostAddress = "tcp://localhost:5557"; var loggingMessages = new List<string> (); // setup the counter socket for communication using (var context = NetMQContext.Create ()) using (var broker = context.CreateRouterSocket ()) using (var poller = new Poller ()) using (var session = new MDPWorker (hostAddress, "test", new[] { (byte) '1' })) { broker.Bind (hostAddress); // we need to pick up any message in order to avoid errors broker.ReceiveReady += (s, e) => { var msg = e.Socket.ReceiveMultipartMessage (); // we expect to receive a 5 Frame message // [WORKER ADR][EMPTY]["MDPW01"]["READY"]["test"] if (msg.FrameCount != 5) Assert.Fail ("Message with wrong count of frames {0}", msg.FrameCount); // make sure the frames are as expected Assert.That (msg[1], Is.EqualTo (NetMQFrame.Empty)); Assert.That (msg[2].ConvertToString (), Is.EqualTo ("MDPW01")); Assert.That (msg[3].BufferSize, Is.EqualTo (1)); Assert.That (msg[3].Buffer[0], Is.EqualTo ((byte) MDPCommand.Ready)); Assert.That (msg[4].ConvertToString (), Is.EqualTo ("test")); // tell worker to stop gracefully var reply = new NetMQMessage (); reply.Push (new[] { (byte) MDPCommand.Kill }); // push MDP Version reply.Push (msg[2]); // push separator reply.Push (NetMQFrame.Empty); // push worker address reply.Push (msg[0]); // send reply which is a request for the worker e.Socket.SendMessage (reply); }; poller.AddSocket (broker); Task.Factory.StartNew (poller.PollTillCancelled); // set the event handler to receive the logging messages session.LogInfoReady += (s, e) => loggingMessages.Add (e.Info); // initialise the worker - broker protocol session.Receive (null); poller.CancelAndJoin (); poller.RemoveSocket (broker); Assert.That (loggingMessages.Count, Is.EqualTo (5)); Assert.That (loggingMessages[0], Is.EqualTo ("[WORKER] connected to broker at tcp://localhost:5557")); Assert.That (loggingMessages[1].Contains ("[WORKER] sending"), Is.True); Assert.That (loggingMessages[2].Contains ("[WORKER] received")); Assert.That (loggingMessages[4].Contains ("abandoning")); } }
/// <summary> /// Implements a MDPWorker API usage /// </summary> /// <remarks> /// Usage: MDPWorkerExample [-v] /// </remarks> private static void Main (string[] args) { var verbose = args.Length == 1 && args[0] == "-v"; var exit = false; const string service_name = "echo"; // trapping Ctrl+C as exit signal! Console.CancelKeyPress += (s, e) => { e.Cancel = true; exit = true; }; var id = new[] { (byte) 'W', (byte) '1' }; Console.WriteLine ("Starting the MDP Worker offering service <{0}>", service_name); Console.WriteLine ("To exit CTRL-C!"); try { // create worker offering the service 'echo' using (var session = new MDPWorker ("tcp://localhost:5555", service_name, id)) { session.HeartbeatDelay = TimeSpan.FromMilliseconds (10000); // logging info to be displayed on screen if (verbose) session.LogInfoReady += (s, e) => Console.WriteLine ("{0}", e.Info); // there is no initial reply NetMQMessage reply = null; while (!exit) { // send the reply and wait for a request var request = session.Receive (reply); if (verbose) Console.WriteLine ("Received: {0}", request); // was the worker interrupted if (ReferenceEquals (request, null)) break; // echo the request reply = request; } } } catch (Exception ex) { Console.WriteLine ("ERROR:"); Console.WriteLine ("{0}", ex.Message); Console.WriteLine ("{0}", ex.StackTrace); Console.WriteLine ("exit - any key"); Console.ReadKey (); } }
/// <summary> /// usage: TitanicWorkerExample [-v] /// /// implements a MDPWorker API usage /// </summary> private static void Main (string[] args) { const string service_name = "echo"; var verbose = args.Length == 1 && args[0] == "-v"; var exit = false; // trapping Ctrl+C as exit signal! Console.CancelKeyPress += (s, e) => { e.Cancel = true; exit = true; }; var id = new[] { (byte) 'W', (byte) '1' }; Console.WriteLine ("Starting the Titanic Worker - offering service {0}", service_name); Console.WriteLine ("to exit - CTR-C\n"); try { // create worker offering the service 'echo' using (var session = new MDPWorker ("tcp://localhost:5555", service_name, id)) { // there is no inital reply NetMQMessage reply = null; while (!exit) { // send the reply and wait for a request var request = session.Receive (reply); if (verbose) Console.WriteLine ("[TITANIC WORKER] Received: {0}", request); // was the worker interrupted if (ReferenceEquals (request, null)) break; // echo the request reply = request; if (verbose) Console.WriteLine ("[TITANIC WORKER] Reply: {0}", request); } } } catch (Exception ex) { Console.WriteLine ("[TITANIC WORKER] ERROR:"); Console.WriteLine ("{0}", ex.Message); Console.WriteLine ("{0}", ex.StackTrace); Console.WriteLine ("exit - any key"); Console.ReadKey (); } }
public async void Run_ReceiveREADYMessageFromWorker_LogSuccessfulRegistration() { const string endPoint = "tcp://localhost:5555"; var log = new List<string>(); using (var cts = new CancellationTokenSource()) using (var workerSession = new MDPWorker(endPoint, "echo")) using (var broker = new MDPBroker(endPoint)) { broker.Bind(); // collect all logging information from broker broker.LogInfoReady += (s, e) => log.Add(e.Info); // start broker session broker.Run(cts.Token); // start echo task Task.Run(() => EchoWorker(workerSession), cts.Token); // wait for everything to happen await Task.Delay(500); // cancel the tasks cts.Cancel(); // check on the logging Assert.That(log.Count, Is.EqualTo(3)); Assert.That(log[2], Is.StringContaining("added to service echo")); } }
public async void Run_ProcessMultipleRequestsClientStopsAndReconnectsWithMultipleWorker_ShouldCorrectlyRouteReplies() { const string endPoint = "tcp://localhost:5555"; var log = new List<string>(); var idW01 = new[] { (byte)'W', (byte)'1' }; var idW02 = new[] { (byte)'W', (byte)'2' }; const int longHeartbeatInterval = 10000; // 10s heartbeat -> stay out of my testing for now using (var broker = new MDPBroker(endPoint, longHeartbeatInterval)) using (var cts = new CancellationTokenSource()) using (var worker1 = new MDPWorker(endPoint, "echo", idW01)) using (var worker2 = new MDPWorker(endPoint, "echo", idW02)) { broker.Bind(); // collect all logging information from broker broker.LogInfoReady += (s, e) => log.Add(e.Info); // follow more details //broker.DebugInfoReady += (s, e) => debugLog.Add (e.Info); // start broker session broker.Run(cts.Token); // wait a little for broker to get started await Task.Delay(250); // get the task for simulating the worker & start it Task.Run(() => MultipleRequestWorker(worker1, heartbeatinterval: longHeartbeatInterval), cts.Token); Task.Run(() => MultipleRequestWorker(worker2, heartbeatinterval: longHeartbeatInterval), cts.Token); // wait a little for worker to get started & registered await Task.Delay(250); // create and run await Task.Run(() => MultipleRequestClient("echo", endPoint)); // recreate and run await Task.Run(() => MultipleRequestClient("echo", endPoint)); // cancel the broker & worker cts.Cancel(); } }
public async void Run_ReceiveREPLYMessageFromThreeDifferentWorker_ShouldLogAndReturnCorrectReplies() { const string endPoint = "tcp://localhost:5555"; var log = new List<string>(); var idW01 = new[] { (byte)'W', (byte)'1' }; var idW02 = new[] { (byte)'W', (byte)'2' }; var idW03 = new[] { (byte)'W', (byte)'3' }; var idC01 = new[] { (byte)'C', (byte)'1' }; var idC02 = new[] { (byte)'C', (byte)'2' }; var idC03 = new[] { (byte)'C', (byte)'3' }; const int longHeartbeatInterval = 10000; // 10s heartbeat -> stay out of my testing for now using (var broker = new MDPBroker(endPoint, longHeartbeatInterval)) using (var cts = new CancellationTokenSource()) using (var client01 = new MDPClient(endPoint, idC01)) using (var client02 = new MDPClient(endPoint, idC02)) using (var client03 = new MDPClient(endPoint, idC03)) using (var worker01 = new MDPWorker(endPoint, "echo", idW01)) using (var worker02 = new MDPWorker(endPoint, "double echo", idW02)) using (var worker03 = new MDPWorker(endPoint, "add hello", idW03)) { broker.Bind(); // collect all logging information from broker broker.LogInfoReady += (s, e) => log.Add(e.Info); // follow more details //broker.DebugInfoReady += (s, e) => debugLog.Add (e.Info); // start broker session broker.Run(cts.Token); // wait a little for broker to get started await Task.Delay(250); // get the task for simulating the worker & start it Task.Run(() => EchoWorker(worker01, longHeartbeatInterval), cts.Token); Task.Run(() => DoubleEchoWorker(worker02, longHeartbeatInterval), cts.Token); Task.Run(() => AddHelloWorker(worker03, longHeartbeatInterval), cts.Token); // wait a little for worker to get started & registered await Task.Delay(250); // get the task for simulating the client var client01Task = new Task(() => EchoClient(client01, "echo")); var client02Task = new Task(() => DoubleEchoClient(client02, "double echo")); var client03Task = new Task(() => AddHelloClient(client03, "add hello")); // start and wait for completion of client client01Task.Start(); client02Task.Start(); client03Task.Start(); // the task completes when the message exchange is done Task.WaitAll(client01Task, client02Task, client03Task); // cancel the broker cts.Cancel(); Assert.That(log.Count, Is.EqualTo(19)); Assert.That(log.Count(s => s.Contains("READY")), Is.EqualTo(3)); Assert.That(log.Count(s => s.Contains("REPLY")), Is.EqualTo(3)); Assert.That(log.Count(s => s.Contains("Dispatching")), Is.EqualTo(3)); } }
public async void Run_ReceiveREPLYMessageFromWorker_ShouldLogCorrectReply() { const string endPoint = "tcp://localhost:5555"; var log = new List<string>(); var idW01 = new[] { (byte)'W', (byte)'1' }; var idC01 = new[] { (byte)'C', (byte)'1' }; const int longHeartbeatInterval = 10000; // 10s heartbeat -> stay out of my testing for now using (var broker = new MDPBroker(endPoint, longHeartbeatInterval)) using (var cts = new CancellationTokenSource()) using (var echoClient = new MDPClient(endPoint, idC01)) using (var echoWorker = new MDPWorker(endPoint, "echo", idW01)) { broker.Bind(); // collect all logging information from broker broker.LogInfoReady += (s, e) => log.Add(e.Info); // follow more details //broker.DebugInfoReady += (s, e) => debugLog.Add (e.Info); // start broker session broker.Run(cts.Token); // wait a little for broker to get started await Task.Delay(250); // get the task for simulating the worker & start it Task.Run(() => EchoWorker(echoWorker, longHeartbeatInterval), cts.Token); // wait a little for worker to get started & registered await Task.Delay(250); // get the task for simulating the client var echoClientTask = new Task(() => EchoClient(echoClient, "echo")); // start and wait for completion of client echoClientTask.Start(); // the task completes when the message exchange is done await echoClientTask; // cancel the broker cts.Cancel(); Assert.That(log.Count, Is.EqualTo(7)); Assert.That(log.Count(s => s.Contains("READY processed. Worker W1 added to service echo")), Is.EqualTo(1)); Assert.That(log.Count(s => s.Contains("Received")), Is.EqualTo(3)); Assert.That(log[4], Is.EqualTo("[BROKER] Dispatching request -> NetMQMessage[C1,,Helo World!]")); Assert.That(log[6], Is.EqualTo("[BROKER] REPLY from W1 received and send to C1 -> NetMQMessage[MDPC01,echo,Helo World!]")); } }
public async void Run_ReceiveREADYMessageFromThreeWorkersDifferentServices_LogSuccessfulRegistration() { const string endPoint = "tcp://localhost:5555"; var log = new List<string>(); var id01 = Encoding.ASCII.GetBytes("Worker01"); var id02 = Encoding.ASCII.GetBytes("Worker02"); var id03 = Encoding.ASCII.GetBytes("Worker03"); using (var cts = new CancellationTokenSource()) using (var worker1 = new MDPWorker(endPoint, "echo", id01)) using (var worker2 = new MDPWorker(endPoint, "double echo", id02)) using (var worker3 = new MDPWorker(endPoint, "add hello", id03)) using (var broker = new MDPBroker(endPoint)) { broker.Bind(); // collect all logging information from broker broker.LogInfoReady += (s, e) => log.Add(e.Info); // start broker session broker.Run(cts.Token); // start echo task Task.Run(() => EchoWorker(worker1), cts.Token); Task.Run(() => DoubleEchoWorker(worker2), cts.Token); Task.Run(() => AddHelloWorker(worker3), cts.Token); // wait for everything to happen await Task.Delay(1000); // cancel the tasks cts.Cancel(); // check on the logging Assert.That(log.Count, Is.EqualTo(7)); Assert.That(log.Count(s => s.Contains("service echo")), Is.EqualTo(1)); Assert.That(log.Count(s => s.Contains("service double echo")), Is.EqualTo(1)); Assert.That(log.Count(s => s.Contains("service add hello")), Is.EqualTo(1)); Assert.That(log.Count(s => s.Contains("READY processed")), Is.EqualTo(3)); } }
public void Receive_RequestWithWrongMDPComand_ShouldLogCorrectMessage() { const string hostAddress = "tcp://localhost:5555"; var loggingMessages = new List<string> (); var first = true; // setup the counter socket for communication using (var context = NetMQContext.Create ()) using (var broker = context.CreateRouterSocket ()) using (var poller = new Poller ()) using (var session = new MDPWorker (hostAddress, "test", Encoding.ASCII.GetBytes ("Worker"), 2)) { broker.Bind (hostAddress); // we need to pick up any message in order to avoid errors broker.ReceiveReady += (s, e) => { var msg = e.Socket.ReceiveMultipartMessage (); // we expect to receive a 5 Frame message // [WORKER ADR][EMPTY]["MDPW01"]["READY"]["test"] if (msg.FrameCount != 5) return; // it is a HEARTBEAT // make sure the frames are as expected Assert.That (msg[1], Is.EqualTo (NetMQFrame.Empty)); Assert.That (msg[2].ConvertToString (), Is.EqualTo ("MDPW01")); Assert.That (msg[3].BufferSize, Is.EqualTo (1)); Assert.That (msg[3].Buffer[0], Is.EqualTo ((byte) MDPCommand.Ready)); Assert.That (msg[4].ConvertToString (), Is.EqualTo ("test")); // tell worker to stop gracefully var reply = new NetMQMessage (); if (first) { reply.Push (new[] { (byte) 0xff }); first = false; } else reply.Push (new[] { (byte) MDPCommand.Kill }); // push MDP Version reply.Push ("MDPW01"); // push separator reply.Push (NetMQFrame.Empty); // push worker address reply.Push (msg[0]); // send reply which is a request for the worker e.Socket.SendMessage (reply); }; // set the event handler to receive the logging messages session.LogInfoReady += (s, e) => loggingMessages.Add (e.Info); poller.AddSocket (broker); Task.Factory.StartNew (poller.PollTillCancelled); session.HeartbeatDelay = TimeSpan.FromMilliseconds (250); session.ReconnectDelay = TimeSpan.FromMilliseconds (250); // initialise the worker - broker protocol session.Receive (null); Assert.That (loggingMessages.Count (m => m.Contains ("[WORKER ERROR] invalid command received")), Is.EqualTo (1)); Assert.That (loggingMessages.Count (m => m.Contains ("abandoning")), Is.EqualTo (1)); poller.CancelAndJoin (); poller.RemoveSocket (broker); } }
public void Receive_RequestWithWrongFirstFrame_ShouldThrowApplicationException() { const string hostAddress = "tcp://localhost:5555"; // setup the counter socket for communication using (var context = NetMQContext.Create ()) using (var broker = context.CreateRouterSocket ()) using (var poller = new Poller ()) using (var session = new MDPWorker (hostAddress, "test")) { broker.Bind (hostAddress); // we need to pick up any message in order to avoid errors broker.ReceiveReady += (s, e) => { var msg = e.Socket.ReceiveMultipartMessage (); // we expect to receive a 5 Frame message // [WORKER ADR][EMPTY]["MDPW01"]["READY"]["test"] if (msg.FrameCount != 5) Assert.Fail ("Message with wrong count of frames {0}", msg.FrameCount); // make sure the frames are as expected Assert.That (msg[1], Is.EqualTo (NetMQFrame.Empty)); Assert.That (msg[2].ConvertToString (), Is.EqualTo ("MDPW01")); Assert.That (msg[3].BufferSize, Is.EqualTo (1)); Assert.That (msg[3].Buffer[0], Is.EqualTo ((byte) MDPCommand.Ready)); Assert.That (msg[4].ConvertToString (), Is.EqualTo ("test")); // tell worker to stop gracefully var reply = new NetMQMessage (); reply.Push (new[] { (byte) MDPCommand.Kill }); // push MDP Version reply.Push ("MDPW01"); // push separator reply.Push ("Should be empty"); // push worker address reply.Push (msg[0]); // send reply which is a request for the worker e.Socket.SendMessage (reply); }; poller.AddSocket (broker); Task.Factory.StartNew (poller.PollTillCancelled); try { session.Receive (null); } catch (ApplicationException ex) { Assert.That (ex.Message, Is.EqualTo ("First frame must be an empty frame!")); } poller.CancelAndJoin (); poller.RemoveSocket (broker); } }
public void Receive_REPLYtoREQUEST_ShouldSendCorrectReply() { const string hostAddress = "tcp://localhost:5557"; var loggingMessages = new List<string> (); // setup the counter socket for communication using (var context = NetMQContext.Create ()) using (var broker = context.CreateRouterSocket ()) using (var poller = new Poller ()) using (var session = new MDPWorker (hostAddress, "test", new[] { (byte) 'W', (byte) '1' })) { broker.Bind (hostAddress); // we need to pick up any message in order to avoid errors broker.ReceiveReady += (s, e) => { var msg = e.Socket.ReceiveMultipartMessage (); if (msg[3].Buffer[0] == (byte) MDPCommand.Ready) { // this is a READY message and we // send REQUEST message var request = new NetMQMessage (); request.Push ("echo test"); // [request] request.Push (NetMQFrame.Empty); // [e][request] request.Push ("C1"); // [client adr][e][request] request.Push (new[] { (byte) MDPCommand.Request }); // [command][client adr][e][request] request.Push (msg[2]); // [header][command][client adr][e][request] request.Push (NetMQFrame.Empty); // [e][header][command][client adr][e][request] request.Push (msg[0]); // [worker adr][e][header][command][client adr][e][request] // send reply which is a request for the worker e.Socket.SendMessage (request); } if (msg[3].Buffer[0] == (byte) MDPCommand.Reply) { // we expect to receive // [WORKER ADR][e]["MDPW01"][REPLY][CLIENT ADR][e][request == "echo test"] // make sure the frames are as expected Assert.That (msg[0].ConvertToString (), Is.EqualTo ("W1")); Assert.That (msg[1], Is.EqualTo (NetMQFrame.Empty)); Assert.That (msg[2].ConvertToString (), Is.EqualTo ("MDPW01")); Assert.That (msg[3].BufferSize, Is.EqualTo (1)); Assert.That (msg[3].Buffer[0], Is.EqualTo ((byte) MDPCommand.Reply)); Assert.That (msg[4].ConvertToString (), Is.EqualTo ("C1")); Assert.That (msg[5], Is.EqualTo (NetMQFrame.Empty)); Assert.That (msg[6].ConvertToString (), Is.EqualTo ("echo test")); // tell worker to stop gracefully var reply = new NetMQMessage (); reply.Push (new[] { (byte) MDPCommand.Kill }); // push MDP Version reply.Push (msg[2]); // push separator reply.Push (NetMQFrame.Empty); // push worker address reply.Push (msg[0]); // send reply which is a request for the worker e.Socket.SendMessage (reply); } }; poller.AddSocket (broker); Task.Factory.StartNew (poller.PollTillCancelled); // set the event handler to receive the logging messages session.LogInfoReady += (s, e) => loggingMessages.Add (e.Info); // initialise the worker - broker protocol // and get initial request var workerRequest = session.Receive (null); // just echo the request session.Receive (workerRequest); poller.CancelAndJoin (); poller.RemoveSocket (broker); Assert.That (loggingMessages.Count, Is.EqualTo (8)); Assert.That (loggingMessages[0], Is.EqualTo ("[WORKER] connected to broker at tcp://localhost:5557")); Assert.That (loggingMessages[1].Contains ("Ready")); Assert.That (loggingMessages[2].Contains ("[WORKER] received")); Assert.That (loggingMessages[3].Contains ("Request")); Assert.That (loggingMessages[4].Contains ("Reply")); Assert.That (loggingMessages[6].Contains ("Kill")); Assert.That (loggingMessages[7].Contains ("abandoning")); } }
public void Receive_BrokerDisconnectedWithLogging_ShouldReturnRequest() { const string hostAddress = "tcp://localhost:5555"; var loggingMessages = new List<string> (); // setup the counter socket for communication using (var context = NetMQContext.Create ()) using (var broker = context.CreateRouterSocket ()) using (var poller = new Poller ()) using (var session = new MDPWorker (hostAddress, "test")) { broker.Bind (hostAddress); // we need to pick up any message in order to avoid errors but don't answer broker.ReceiveReady += (s, e) => e.Socket.ReceiveMultipartMessage (); poller.AddSocket (broker); Task.Factory.StartNew (poller.PollTillCancelled); // speed up the test session.HeartbeatDelay = TimeSpan.FromMilliseconds (250); session.ReconnectDelay = TimeSpan.FromMilliseconds (250); // set the event handler to receive the logging messages session.LogInfoReady += (s, e) => loggingMessages.Add (e.Info); // initialise the worker - broker protocol session.Receive (null); poller.CancelAndJoin (); poller.RemoveSocket (broker); Assert.That (loggingMessages.Count (m => m.Contains ("retrying")), Is.EqualTo (3)); // 3 times retrying and 1 time initial connecting Assert.That (loggingMessages.Count (m => m.Contains ("localhost")), Is.EqualTo (4)); Assert.That (loggingMessages.Last ().Contains ("abandoning")); } }