private bool ProcessMessages() { for (var i = 0; i < _dispatcher.Throughput; i++) { object msg; if ((msg = _systemMessages.Pop()) != null) { if (msg is SuspendMailbox) { _suspended = true; } if (msg is ResumeMailbox) { _suspended = false; } var t = _invoker.InvokeSystemMessageAsync(msg); if (t.IsFaulted) { _invoker.EscalateFailure(t.Exception, msg); continue; } if (!t.IsCompleted) { // if task didn't complete immediately, halt processing and reschedule a new run when task completes t.ContinueWith(RescheduleOnTaskComplete, msg); return(false); } continue; } if (_suspended) { break; } if ((msg = _userMailbox.Pop()) != null) { var t = _invoker.InvokeUserMessageAsync(msg); if (t.IsFaulted) { _invoker.EscalateFailure(t.Exception, msg); continue; } if (!t.IsCompleted) { // if task didn't complete immediately, halt processing and reschedule a new run when task completes t.ContinueWith(RescheduleOnTaskComplete, msg); return(false); } for (var si = 0; si < _stats.Length; si++) { _stats[si].MessageReceived(msg); } } else { break; } } return(true); }
private async Task RunAsync() { object m = null; try { var _ = _dispatcher.Throughput; //not used for batch mailbox var batch = new List <RemoteDeliver>(_batchSize); var sys = _systemMessages.Pop(); if (sys != null) { if (sys is SuspendMailbox) { _suspended = true; } if (sys is ResumeMailbox) { _suspended = false; } m = sys; await _invoker.InvokeSystemMessageAsync(sys); } if (!_suspended) { batch.Clear(); object msg; while ((msg = _userMessages.Pop()) != null) { batch.Add((RemoteDeliver)msg); if (batch.Count >= _batchSize) { break; } } if (batch.Count > 0) { m = batch; await _invoker.InvokeUserMessageAsync(batch); } } } catch (Exception x) { _invoker.EscalateFailure(x, m); } Interlocked.Exchange(ref _status, MailboxStatus.Idle); if (_userMessages.HasMessages || _systemMessages.HasMessages) { Schedule(); } }
//TODO: we can gain a good 10% perf by not having async here. //but then we need some way to deal with non completed tasks, and handle mailbox idle/busy state for those private async Task ProcessMessages() { var t = _dispatcher.Throughput; object message = null; try { for (var i = 0; i < t; i++) { var sys = _systemMessages.Pop(); message = sys; if (sys != null) { if (sys is SuspendMailbox) { _suspended = true; } if (sys is ResumeMailbox) { _suspended = false; } await _invoker.InvokeSystemMessageAsync(sys); continue; } if (_suspended) { break; } var msg = _userMailbox.Pop(); if (msg != null) { message = msg; await _invoker.InvokeUserMessageAsync(msg); for (var si = 0; si < _stats.Length; si++) { _stats[si].MessageReceived(msg); } } else { break; } } } catch (Exception x) { _invoker.EscalateFailure(x, message); } }
private async Task RunAsync() { var t = _dispatcher.Throughput; var batch = new List <RemoteDeliver>(_batchSize); var sys = _systemMessages.Pop(); if (sys != null) { if (sys is SuspendMailbox) { _suspended = true; } if (sys is ResumeMailbox) { _suspended = false; } await _invoker.InvokeSystemMessageAsync(sys); } if (!_suspended) { batch.Clear(); object msg; while ((msg = _userMessages.Pop()) != null) { batch.Add((RemoteDeliver)msg); if (batch.Count >= _batchSize) { break; } } if (batch.Count > 0) { await _invoker.InvokeUserMessageAsync(batch); } } Interlocked.Exchange(ref _status, MailboxStatus.Idle); if (_userMessages.HasMessages || _systemMessages.HasMessages) { Schedule(); } }
private async Task RunAsync() { object?m = null; try { // Logger.LogDebug( // "[EndpointWriterMailbox] Running Mailbox Loop HasSystemMessages: {HasSystemMessages} HasUserMessages: {HasUserMessages} Suspended: {Suspended}", // _systemMessages.HasMessages, _userMessages.HasMessages, _suspended // ); var _ = _dispatcher !.Throughput; //not used for batch mailbox var batch = new List <RemoteDeliver>(_batchSize); var sys = _systemMessages.Pop(); if (sys is not null) { Logger.LogDebug("[EndpointWriterMailbox] Processing System Message {@Message}", sys); _suspended = sys switch { SuspendMailbox _ => true, EndpointConnectedEvent _ => false, _ => _suspended }; m = sys; switch (m) { case EndpointErrorEvent e: if (!_suspended) // Since it's already stopped, there is no need to throw the error { await _invoker !.InvokeUserMessageAsync(sys); } break; case EndpointConnectedEvent: //endpoint connected event is not a real system message, do not pass it to the invoker break; default: await _invoker !.InvokeSystemMessageAsync(sys); break; } if (sys is Stop) { // Logger.LogWarning("Endpoint writer is stopping..."); //Dump messages from user messages queue to deadletter and inform watchers about termination object?usrMsg; var droppedRemoteDeliverCount = 0; var remoteTerminateCount = 0; while ((usrMsg = _userMessages.Pop()) is not null) { switch (usrMsg) { case RemoteWatch msg: remoteTerminateCount++; msg.Watcher.SendSystemMessage(_system, new Terminated { Why = TerminatedReason.AddressTerminated, Who = msg.Watchee } ); break; case RemoteDeliver rd: droppedRemoteDeliverCount++; if (rd.Sender != null) { _system.Root.Send(rd.Sender, new DeadLetterResponse { Target = rd.Target }); } _system.EventStream.Publish(new DeadLetterEvent(rd.Target, rd.Message, rd.Sender)); break; } } if (droppedRemoteDeliverCount > 0) { Logger.LogInformation("[EndpointWriterMailbox] Dropped {count} user Messages for {Address}", droppedRemoteDeliverCount, _address ); } if (remoteTerminateCount > 0) { Logger.LogInformation("[EndpointWriterMailbox] Sent {Count} remote terminations for {Address}", remoteTerminateCount, _address ); } } } if (!_suspended) { batch.Clear(); object?msg; while ((msg = _userMessages.Pop()) is not null) { // Logger.LogDebug("[EndpointWriterMailbox] Processing User Message {@Message}", msg); switch (msg) { case RemoteWatch _: case RemoteUnwatch _: case RemoteTerminate _: await _invoker !.InvokeUserMessageAsync(msg); continue; } batch.Add((RemoteDeliver)msg); if (batch.Count >= _batchSize) { break; } } if (batch.Count > 0) { m = batch; // Logger.LogDebug("[EndpointWriterMailbox] Calling message invoker"); await _invoker !.InvokeUserMessageAsync(batch); } } } catch (Exception x) { // if (x is RpcException rpc && rpc.Status.StatusCode == StatusCode.Unavailable) // { // Logger.LogError( "Endpoint writer failed, status unavailable"); // } // else // { // Logger.LogError(x, "Endpoint writer failed"); // } _suspended = true; _invoker !.EscalateFailure(x, m); } Interlocked.Exchange(ref _status, MailboxStatus.Idle); if (_systemMessages.HasMessages || _userMessages.HasMessages & !_suspended) { Schedule(); } }
private bool ProcessMessages() { object msg = null; try { for (var i = 0; i < _dispatcher.Throughput; i++) { if (Interlocked.Read(ref _systemMessageCount) > 0 && (msg = _systemMessages.Pop()) != null) { Interlocked.Decrement(ref _systemMessageCount); if (msg is SuspendMailbox) { _suspended = true; } else if (msg is ResumeMailbox) { _suspended = false; } var t = _invoker.InvokeSystemMessageAsync(msg); if (t.IsFaulted) { _invoker.EscalateFailure(t.Exception, msg); continue; } if (!t.IsCompleted) { // if task didn't complete immediately, halt processing and reschedule a new run when task completes t.ContinueWith(RescheduleOnTaskComplete, msg); return(false); } foreach (var t1 in _stats) { t1.MessageReceived(msg); } continue; } if (_suspended) { break; } if ((msg = _userMailbox.Pop()) != null) { var t = _invoker.InvokeUserMessageAsync(msg); if (t.IsFaulted) { _invoker.EscalateFailure(t.Exception, msg); continue; } if (!t.IsCompleted) { // if task didn't complete immediately, halt processing and reschedule a new run when task completes t.ContinueWith(RescheduleOnTaskComplete, msg); return(false); } foreach (var t1 in _stats) { t1.MessageReceived(msg); } } else { break; } } } catch (Exception e) { _invoker.EscalateFailure(e, msg); } return(true); }