private async Task Handler() { while (this.IsRunning) { try { bool isListening = false; var connectionString = this.FrontendEndpoint.ToConnectionString(); using (var frontendSocket = new RouterSocket()) using (this.FrontendBuffer = new NetMQQueue <TransportMessage>()) using (var poller = new NetMQPoller() { frontendSocket, this.FrontendBuffer }) using (var monitor = new NetMQ.Monitoring.NetMQMonitor(frontendSocket, $"inproc://monitor.forwarderdevice.{Guid.NewGuid().ToString()}", SocketEvents.Listening | SocketEvents.Accepted | SocketEvents.Disconnected | SocketEvents.Closed)) { frontendSocket.ReceiveReady += (sender, e) => { try { var netmqMessage = new NetMQMessage(); while (e.Socket.TryReceiveMultipartMessage(ref netmqMessage)) { var message = netmqMessage.ToMessage(out var envelope); string serviceIdentifier = message.Metadata.TryGetLast("serviceIdentifier", out var encodedService) ? Encoding.UTF8.GetString(encodedService) : null; try { var cancellationSource = new CancellationTokenSource(5000); var registeredBackend = this.ResolveBackend(serviceIdentifier, cancellationSource.Token); //var registeredBackend = this.InprocTransportScope.GetNextServerTransport(serviceIdentifier, cancellationSource.Token); message.Metadata.Add($"envelope[{this.Identity}]", envelope); //registeredBackend.ReceiveBuffer.QueueMessage(message); registeredBackend.Send(message).ContinueWith(task => { this.OnDiagnosticMessage($"Failed to forward to backend [{task.Exception.InnerException.Message}]"); }, TaskContinuationOptions.OnlyOnFaulted); } catch (OperationCanceledException) { this.OnDiagnosticMessage($"No backends available for {serviceIdentifier}!!!"); var nmqm = MessageHelpers.CreateNetMQErrorMessage(envelope, "No backends found", message.Metadata); e.Socket.SendMultipartMessage(nmqm); } } } catch (Exception ex) { this.OnDiagnosticMessage(ex.Message + ": " + ex.StackTrace); } }; this.FrontendBuffer.ReceiveReady += (sender, e) => { try { while (this.FrontendBuffer.TryDequeue(out TransportMessage message, TimeSpan.Zero)) { if (!message.Metadata.TryPluckLast($"envelope[{this.Identity}]", out var envelope)) { throw new Exception("Message envelope not found"); } if (!frontendSocket.TrySendMultipartMessage(TimeSpan.FromSeconds(1), message.ToNetMQMessage(envelope))) { this.OnDiagnosticMessage("Failed to forward to frontend"); } } } catch (Exception ex) { this.OnDiagnosticMessage(ex.Message + ": " + ex.StackTrace); } }; monitor.Listening += (sender, e) => { this.OnDiagnosticMessage($"Frontend router socket listening at {connectionString}"); isListening = true; }; monitor.Closed += (sender, e) => { this.OnDiagnosticMessage($"Frontend router socket closed on {connectionString}"); isListening = false; }; monitor.Accepted += (sender, e) => { this.OnDiagnosticMessage($"Frontend router socket connection accepted at {connectionString}"); }; monitor.Disconnected += (sender, e) => { this.OnDiagnosticMessage($"Frontend router socket disconnected at {connectionString}"); }; this.OnDiagnosticMessage($"Attempting to bind frontend socket to {connectionString}"); monitor.StartAsync(); monitor.AttachToPoller(poller); var pollerTask = new Task(poller.Run); pollerTask.ContinueWith(task => { var ex = task.Exception; this.OnDiagnosticMessage(ex.Message + ": " + ex.StackTrace); isListening = false; }, TaskContinuationOptions.OnlyOnFaulted); pollerTask.Start(); frontendSocket.Bind(connectionString); var start = DateTime.Now; while (!isListening) { if ((DateTime.Now - start).TotalMilliseconds > 5000) { throw new Exception($"Frontend socket bind timeout ({connectionString})"); } await Task.Delay(1000); } while (this.IsRunning && isListening) { await Task.Delay(1000); } poller.StopAsync(); frontendSocket.Disconnect(connectionString); monitor.DetachFromPoller(); monitor.Stop(); } } catch (Exception ex) { this.OnDiagnosticMessage(ex.Message + ": " + ex.StackTrace); } } }
private async Task FrontendHandler() { while (this.IsRunning) { try { bool isListening = false; var connectionString = this.FrontendEndpoint.ToConnectionString(); using (var frontendSocket = new RouterSocket()) using (this.AltFrontendBuffer = new NetMQQueue <TransportMessage>()) using (var poller = new NetMQPoller() { frontendSocket, this.AltFrontendBuffer }) using (var monitor = new NetMQ.Monitoring.NetMQMonitor(frontendSocket, $"inproc://monitor.routerdevice.frontend.{Guid.NewGuid().ToString()}", SocketEvents.Listening | SocketEvents.Accepted | SocketEvents.Disconnected | SocketEvents.Closed)) { frontendSocket.ReceiveReady += (sender, e) => { try { var netmqMessage = new NetMQMessage(); while (e.Socket.TryReceiveMultipartMessage(ref netmqMessage)) { //Console.WriteLine("Frontend message received"); var message = netmqMessage.ToMessage(out var envelope); this.OnFrontendReceived(message); //this.receiveCount++; //Console.WriteLine("RECEIVED " + this.receiveCount); //var sourceEnvelope = message.Envelope; RegisteredBackend registeredBackend = null; var forwardStart = DateTime.UtcNow; while (this.IsRunning && registeredBackend == null) { while (this.RegisteredBackendIdentifiers.TryDequeue(out string backendIdentifier)) { registeredBackend = this.RegisteredBackends[backendIdentifier]; if ((DateTime.UtcNow - registeredBackend.RegsiteredDate).TotalMilliseconds < 2000) { this.RegisteredBackendIdentifiers.Enqueue(backendIdentifier); break; } else { if (this.RegisteredBackends.TryRemove(backendIdentifier, out RegisteredBackend expiredBackend)) { Console.WriteLine($"Backend {backendIdentifier} expired"); } } } if (registeredBackend != null || (DateTime.Now - forwardStart).TotalMilliseconds > 30000) { break; } System.Threading.Thread.Sleep(100); } if (registeredBackend != null) { //Console.WriteLine($"Forwarding to [ {BitConverter.ToString(registeredBackend.Envelope)} ]"); message.Metadata.Add($"envelope[{this.Identity}]", envelope); message.Metadata.Add($"backendEnvelope[{this.Identity}]", registeredBackend.Envelope); this.AltBackendBuffer.Enqueue(message); ////this.BackendSocket.SendMultipartMessage(message.ToNetMQMessage(true)); //if (!this.BackendSocket.TrySendMultipartMessage(TimeSpan.FromSeconds(1), message.ToNetMQMessage(true))) //{ // Console.WriteLine("Failed to forward to backend"); // var forwardedMessage = new Message(1, message.Frames, System.Text.Encoding.UTF8.GetBytes("Failed to forward to backend"), sourceEnvelope); // this.FrontendSocket.SendMultipartMessage(forwardedMessage.ToNetMQMessage(true)); //} } else { Console.WriteLine("No backends available!!!"); var nmqm = MessageHelpers.CreateNetMQErrorMessage(envelope, "No backends found", message.Metadata); e.Socket.SendMultipartMessage(nmqm); } } } catch (Exception ex) { Console.WriteLine(ex.Message + ": " + ex.StackTrace); } }; //var lastFlushed = DateTime.UtcNow; //frontendSocket.SendReady += (sender, e) => //{ // try // { // if (!this.BackendBuffer.IsEmpty) // { // while (this.BackendBuffer.TryDequeue(out Message message)) // { // Console.WriteLine("Backend forwarding"); // if (!e.Socket.TrySendMultipartMessage(TimeSpan.FromSeconds(1), message.ToNetMQMessage(true))) // { // Console.WriteLine("Failed to forward to frontend"); // //var forwardedMessage = new Message(1, message.Frames, System.Text.Encoding.UTF8.GetBytes("Failed to forward to backend"), sourceEnvelope); // //this.FrontendSocket.SendMultipartMessage(forwardedMessage.ToNetMQMessage(true)); // } // } // lastFlushed = DateTime.UtcNow; // } // if ((DateTime.UtcNow - lastFlushed).TotalSeconds > 1) // Task.Delay(1).Wait(); // } // catch (Exception ex) // { // Console.WriteLine(ex.Message + ": " + ex.StackTrace); // } //}; this.AltFrontendBuffer.ReceiveReady += (sender, e) => { try { while (this.AltFrontendBuffer.TryDequeue(out TransportMessage message, TimeSpan.Zero)) { if (!message.Metadata.TryPluck($"envelope[{this.Identity}]", out var envelope)) { throw new Exception("Message envelope not found"); } this.OnBackendForwarded(message); if (!frontendSocket.TrySendMultipartMessage(TimeSpan.FromSeconds(1), message.ToNetMQMessage(envelope))) { Console.WriteLine("Failed to forward to frontend"); } } } catch (Exception ex) { Console.WriteLine(ex.Message + ": " + ex.StackTrace); } }; monitor.Listening += (sender, e) => { Console.WriteLine($"Frontend router socket listening at {connectionString}"); isListening = true; }; monitor.Closed += (sender, e) => { Console.WriteLine($"Frontend router socket closed on {connectionString}"); isListening = false; }; monitor.Accepted += (sender, e) => { Console.WriteLine($"Frontend router socket connection accepted at {connectionString}"); }; monitor.Disconnected += (sender, e) => { Console.WriteLine($"Frontend router socket disconnected at {connectionString}"); }; Console.WriteLine($"Attempting to bind frontend socket to {connectionString}"); monitor.StartAsync(); monitor.AttachToPoller(poller); var pollerTask = new Task(poller.Run); pollerTask.ContinueWith((Task task) => { var ex = task.Exception; Console.WriteLine(ex.Message + ": " + ex.StackTrace); isListening = false; }, TaskContinuationOptions.OnlyOnFaulted); pollerTask.Start(); frontendSocket.Bind(connectionString); var start = DateTime.Now; while (!isListening) { if ((DateTime.Now - start).TotalMilliseconds > 5000) { throw new Exception($"Frontend socket bind timeout ({connectionString})"); } await Task.Delay(1000); } while (this.IsRunning && isListening) { if (this.FrontendAnnouncer != null) { //Console.WriteLine("Registering frontend"); await this.FrontendAnnouncer.Register(this.FrontendEndpoint); } await Task.Delay(1000); } poller.StopAsync(); frontendSocket.Disconnect(connectionString); monitor.DetachFromPoller(); monitor.Stop(); } } catch (Exception ex) { Console.WriteLine(ex.Message + ": " + ex.StackTrace); } } }