private bool TryHandleMessage(object message)
        {
            var messageType = message.GetType();
            var handlerItem = _handler.MessageDispatcher.GetHandler(messageType);

            if (handlerItem == null)
            {
                // if generic argument, try to instantiate a generic handler by the given payload type.

                if (messageType.IsGenericType)
                {
                    var genericHandlerItem = _handler.MessageDispatcher.GetHandler(messageType.GetGenericTypeDefinition());
                    if (genericHandlerItem != null)
                    {
                        handlerItem = genericHandlerItem.GenericHandlerBuilder(messageType);
                        _handler.MessageDispatcher.AddHandler(messageType, handlerItem);
                    }
                }

                if (handlerItem == null)
                {
                    return(false);
                }
            }

            if (handlerItem.AsyncHandler != null)
            {
                var context = new MessageHandleContext {
                    Self = Self, Sender = base.Sender, CancellationToken = CancellationToken
                };
                if (handlerItem.IsReentrant)
                {
                    _activeReentrantCount += 1;
                }
                else
                {
                    BecomeStacked(OnReceiveInAtomicTask);
                    _currentAtomicContext = context;
                }

                using (new SynchronizationContextSwitcher(new ActorSynchronizationContext(context)))
                {
                    handlerItem.AsyncHandler(this, message)
                    .ContinueWith(t => OnTaskCompleted(t.Exception, handlerItem.IsReentrant),
                                  TaskContinuationOptions.ExecuteSynchronously);
                }
            }
            else
            {
                handlerItem.Handler(this, message);
            }
            return(true);
        }
        private void InitializeActorState()
        {
            _cancellationTokenSource        = new CancellationTokenSource();
            _activeReentrantCount           = 0;
            _activeReentrantAsyncRequestSet = null;
            _currentAtomicContext           = null;
            _requestWaiter = null;

            if (_handler.PerInstanceFilterCreators.Count > 0)
            {
                _perInstanceFilterList = new InterfacedActorPerInstanceFilterList(this, _handler.PerInstanceFilterCreators);
            }
        }
Exemple #3
0
        public async Task SaveConsumeAsync(MessageHandleContext context)
        {
            var consumedMessage = new MessageConsumed(context.Topic,
                                                      context.Message.ToString(),
                                                      context.ConsumeTime);

            MessageConsumed.Add(consumedMessage);
            foreach (var result in context.HandleResults)
            {
                MessageHandles.Add(new MessageHandle(result.MessageHandler.Name,
                                                     result.ProcessError?.ToString(),
                                                     consumedMessage.Id));
            }

            await SaveChangesAsync();
        }
        private void InvokeOnStart(bool restarted)
        {
            var context = new MessageHandleContext {
                Self = Self, Sender = base.Sender, CancellationToken = CancellationToken
            };

            BecomeStacked(OnReceiveInAtomicTask);
            _currentAtomicContext = context;

            using (new SynchronizationContextSwitcher(new ActorSynchronizationContext(context)))
            {
                OnStart(restarted).ContinueWith(
                    t => OnTaskCompleted(t.Exception, false),
                    TaskContinuationOptions.ExecuteSynchronously);
            }
        }
        private void InvokeOnGracefulStop()
        {
            var context = new MessageHandleContext {
                Self = Self, CancellationToken = CancellationToken
            };

            BecomeStacked(OnReceiveInAtomicTask);
            _currentAtomicContext = context;

            using (new SynchronizationContextSwitcher(new ActorSynchronizationContext(context)))
            {
                OnGracefulStop().ContinueWith(
                    t => OnTaskCompleted(t.Exception, false, stopOnCompleted: true),
                    TaskContinuationOptions.ExecuteSynchronously);
            }
        }
Exemple #6
0
        private void StartConsume()
        {
            Task.Factory.StartNew(async() =>
            {
                while (await MessageChannel.Reader.WaitToReadAsync())
                {
                    if (!MessageChannel.Reader.TryRead(out var message))
                    {
                        continue;
                    }
                    var context = new MessageHandleContext(message.Topic, message.Message);
                    if (!Topics.Contains(message.Topic))
                    {
                        continue;
                    }

                    await HandleMessageAsync(() => context);
                }
            });
        }
        private void OnTaskCompleted(Exception exception, bool isReentrant, bool stopOnCompleted = false)
        {
            if (isReentrant)
            {
                _activeReentrantCount -= 1;
            }
            else
            {
                _currentAtomicContext = null;
                UnbecomeStacked();
                Stash.UnstashAll();
            }

            if (exception != null)
            {
                ((ActorCell)Context).InvokeFailure(exception);
            }
            else if (stopOnCompleted)
            {
                Context.Stop(Self);
            }
        }
        private void OnTaskRunMessage(TaskRunMessage taskRunMessage)
        {
            var context = new MessageHandleContext {
                Self = Self, Sender = base.Sender, CancellationToken = CancellationToken
            };

            if (taskRunMessage.IsReentrant)
            {
                _activeReentrantCount += 1;
            }
            else
            {
                BecomeStacked(OnReceiveInAtomicTask);
                _currentAtomicContext = context;
            }

            using (new SynchronizationContextSwitcher(new ActorSynchronizationContext(context)))
            {
                taskRunMessage.Function()
                .ContinueWith(t => OnTaskCompleted(t.Exception, taskRunMessage.IsReentrant),
                              TaskContinuationOptions.ExecuteSynchronously);
            }
        }
        private void OnNotificationMessage(NotificationMessage notification)
        {
            object observerContext = null;

            if (notification.ObserverId != 0)
            {
                observerContext = EnsureObserverMap().GetContext(notification.ObserverId);
                if (observerContext == null)
                {
                    // because it could be a removed observer, doesn't log anything.
                    return;
                }
            }

            if (notification.InvokePayload == null)
            {
                Context.System.EventStream.Publish(new Event.Warning(
                                                       Self.Path.ToString(), GetType(),
                                                       $"Receives a bad notification with no payload from {Sender}"));
                return;
            }

            var payloadType = notification.InvokePayload.GetType();
            var handlerItem = _handler.NotificationDispatcher.GetHandler(payloadType);

            if (handlerItem == null)
            {
                // if generic argument, try to instantiate a generic handler by the given payload type.

                if (payloadType.IsGenericType)
                {
                    var genericHandlerItem = _handler.NotificationDispatcher.GetHandler(payloadType.GetGenericTypeDefinition());
                    if (genericHandlerItem != null)
                    {
                        handlerItem = genericHandlerItem.GenericHandlerBuilder(payloadType);
                        _handler.NotificationDispatcher.AddHandler(payloadType, handlerItem);
                    }
                }

                // oops, no handler.

                if (handlerItem == null)
                {
                    Context.System.EventStream.Publish(new Event.Warning(
                                                           Self.Path.ToString(), GetType(),
                                                           $"Cannot find a handler for notification {notification.InvokePayload.GetType()} from {Sender}"));
                    return;
                }
            }

            if (handlerItem.Handler != null)
            {
                // sync handle

                try
                {
                    _observerContext = observerContext;
                    handlerItem.Handler(this, notification);
                }
                finally
                {
                    _observerContext = null;
                }
            }
            else
            {
                // async handle

                var context = new MessageHandleContext {
                    Self = Self, Sender = base.Sender, CancellationToken = CancellationToken, ObserverContext = observerContext
                };
                if (handlerItem.IsReentrant)
                {
                    _activeReentrantCount += 1;
                }
                else
                {
                    BecomeStacked(OnReceiveInAtomicTask);
                    _currentAtomicContext = context;
                }

                using (new SynchronizationContextSwitcher(new ActorSynchronizationContext(context)))
                {
                    handlerItem.AsyncHandler(this, notification)
                    .ContinueWith(t => OnTaskCompleted(t.Exception, handlerItem.IsReentrant),
                                  TaskContinuationOptions.ExecuteSynchronously);
                }
            }
        }
        private void OnRequestMessage(RequestMessage request)
        {
            var sender = base.Sender;

            if (request.InvokePayload == null)
            {
                sender.Tell(new ResponseMessage
                {
                    RequestId = request.RequestId,
                    Exception = new RequestMessageException("Empty payload")
                });
                Context.System.EventStream.Publish(new Event.Warning(
                                                       Self.Path.ToString(), GetType(),
                                                       $"Receives a bad request without payload from {Sender}"));
                return;
            }

            var payloadType = request.InvokePayload.GetType();
            var handlerItem = _handler.RequestDispatcher.GetHandler(payloadType);

            if (handlerItem == null)
            {
                // if generic argument, try to instantiate a generic handler by the given payload type.

                if (payloadType.IsGenericType)
                {
                    var genericHandlerItem = _handler.RequestDispatcher.GetHandler(payloadType.GetGenericTypeDefinition());
                    if (genericHandlerItem != null)
                    {
                        handlerItem = genericHandlerItem.GenericHandlerBuilder(payloadType);
                        _handler.RequestDispatcher.AddHandler(payloadType, handlerItem);
                    }
                }

                // oops, no handler.

                if (handlerItem == null)
                {
                    sender.Tell(new ResponseMessage
                    {
                        RequestId = request.RequestId,
                        Exception = new RequestHandlerNotFoundException()
                    });
                    Context.System.EventStream.Publish(new Event.Warning(
                                                           Self.Path.ToString(), GetType(),
                                                           $"Cannot find a handler for request {payloadType} from {Sender}"));
                    return;
                }
            }

            if (handlerItem.Handler != null)
            {
                // sync handle

                handlerItem.Handler(this, request, (response, exception) =>
                {
                    if (request.RequestId != 0)
                    {
                        sender.Tell(response);
                    }

                    if (exception != null)
                    {
                        ((ActorCell)Context).InvokeFailure(exception);
                    }
                });
            }
            else
            {
                // async handle

                var context = new MessageHandleContext {
                    Self = Self, Sender = base.Sender, CancellationToken = CancellationToken, RequestId = request.RequestId
                };
                if (handlerItem.IsReentrant)
                {
                    _activeReentrantCount += 1;
                    if (request.RequestId != 0)
                    {
                        if (_activeReentrantAsyncRequestSet == null)
                        {
                            _activeReentrantAsyncRequestSet = new HashSet <MessageHandleContext>();
                        }

                        _activeReentrantAsyncRequestSet.Add(context);
                    }
                }
                else
                {
                    BecomeStacked(OnReceiveInAtomicTask);
                    _currentAtomicContext = context;
                }

                using (new SynchronizationContextSwitcher(new ActorSynchronizationContext(context)))
                {
                    var requestId   = request.RequestId;
                    var isReentrant = handlerItem.IsReentrant;
                    handlerItem.AsyncHandler(this, request, (response, exception) =>
                    {
                        if (requestId != 0)
                        {
                            if (isReentrant)
                            {
                                _activeReentrantAsyncRequestSet.Remove(context);
                            }

                            sender.Tell(response);
                        }

                        OnTaskCompleted(exception, isReentrant);
                    });
                }
            }
        }