예제 #1
0
 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);
 }
예제 #2
0
        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();
            }
        }
예제 #3
0
        //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();
            }
        }
예제 #5
0
        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();
            }
        }
예제 #6
0
        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);
        }