Example #1
0
        protected async Task OnReceiveMessageAsync(EntityActorMessage message)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            if (!isInitialized)
            {
                //Only 1 thread ever will call OnInternalReceiveMessageAsync but it prevents
                //any external initialization from happening.
                lock (SyncObj)
                {
                    if (!isInitialized)
                    {
                        if (ExtractPotentialStateMessage(message, out var initMessage))
                        {
                            InitializeState(initMessage.State);

                            //Send successful initialization message to the entity, immediately.
                            //Some entities may not care.
                            OnInitialized(new EntityActorInitializationSuccessMessage());
                        }
                        else
                        {
                            if (Logger.IsWarnEnabled)
                            {
                                Logger.Warn($"{GetType().Name} encountered MessageType: {message.GetType().Name} before INITIALIZATION.");
                            }
                        }

                        //Even if we're initialized now, it's an init message we shouldn't continue with.
                        return;
                    }
                }
            }

            //TODO: Is it safe to capture the Context message ref forever??
            //TODO: Pool or cache somehow.
            EntityActorMessageContext context = new EntityActorMessageContext(Context);

            try
            {
                if (!await HandleMessageAsync(message, context))
                {
                    if (Logger.IsWarnEnabled)
                    {
                        Logger.Warn($"EntityActor encountered unhandled MessageType: {message.GetType().Name}");
                    }
                }
            }
            catch (Exception e)
            {
                if (Logger.IsErrorEnabled)
                {
                    Logger.Error($"Actor: {Self.Path.Address} failed to handle MessageType: {message.GetType().Name} without Exception: {e.Message}\n\nStack: {e.StackTrace}");
                }
                throw;
            }
        }
Example #2
0
        private bool TrySendMessage(object message)
        {
            EntityActorMessage        castedMessage = (EntityActorMessage)message;
            EntityActorMessageContext context       = new EntityActorMessageContext(Sender, Self, Context.System.Scheduler);

            return(MessageRouter.RouteMessage(context, ActorState, castedMessage));
        }
Example #3
0
        /// <summary>
        /// Implementer can override the behavior of extracting the state from the provided initialization message.
        /// </summary>
        /// <param name="message"></param>
        /// <param name="entityActorStateInitializeMessage"></param>
        /// <returns></returns>
        protected virtual bool ExtractPotentialStateMessage(EntityActorMessage message, out EntityActorStateInitializeMessage <TActorStateType> entityActorStateInitializeMessage)
        {
            if (message is EntityActorStateInitializeMessage <TActorStateType> initMessage)
            {
                entityActorStateInitializeMessage = initMessage;
                return(true);
            }

            entityActorStateInitializeMessage = null;
            return(false);
        }
Example #4
0
        /// <summary>
        /// Implements must override this and implement domain-specific message handling logic.
        /// </summary>
        /// <param name="message">The message to handle.</param>
        /// <param name="context">The actor message context.</param>
        /// <returns>True if the message was successfully handled.</returns>
        protected Task <bool> HandleMessageAsync(EntityActorMessage message, EntityActorMessageContext context)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            return(MessageHandlerService.HandleMessageAsync(context, message, CancellationToken.None));
        }
        /// <summary>
        /// See Akka.NET's <see cref="IActorRef"/>.Tell.
        /// Sends self with <see cref="actorReference"/> as the sender.
        /// </summary>
        /// <param name="actorReference"></param>
        /// <param name="message"></param>
        public static void TellSelf(this IActorRef actorReference, EntityActorMessage message)
        {
            if (actorReference == null)
            {
                throw new ArgumentNullException(nameof(actorReference));
            }
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            actorReference.Tell((object)message, actorReference);
        }
Example #6
0
        public bool RouteMessage(EntityActorMessageContext messageContext, TEntityActorStateType state, EntityActorMessage message)
        {
            if (messageContext == null)
            {
                throw new ArgumentNullException(nameof(messageContext));
            }
            if (state == null)
            {
                throw new ArgumentNullException(nameof(state));
            }
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            if (EntityHandlerMap.ContainsKey(message.GetType()))
            {
                foreach (var handler in EntityHandlerMap[message.GetType()])
                {
                    handler.HandleMessage(messageContext, state, message);
                }

                return(true);
            }
            else
            {
                return(false);
            }
        }
Example #7
0
 public void HandleMessage(EntityActorMessageContext messageContext, TEntityStateType state, EntityActorMessage message)
 {
     //Assume caller has verified this will work
     //We downcast so the API consumed is simplier/easier.
     //We need the interface to not be specific so it can be discovered, registered and handled.
     HandleMessage(messageContext, state, (TEntityMessageType)message);
 }
Example #8
0
 public BroadcastTargeted(EntityActorMessage message, IActorRef target)
     : base(message)
 {
     Target = target ?? throw new ArgumentNullException(nameof(target));
 }
Example #9
0
 public static void TellEntityChildren(this IActorRefFactory selector, EntityActorMessage message)
 {
     selector
     .ActorSelection(MEAKKASelectionConstants.ALL_DIRECT_CHILDREN_SELECTOR)
     .TellEntitySelection(message);
 }
Example #10
0
 public static void TellEntitySelection(this ActorSelection selection, EntityActorMessage message, IEntityActorRef sender)
 {
     TellEntitySelection(selection, message, sender.Actor);
 }
Example #11
0
 public static void TellEntitySelection(this ActorSelection selection, EntityActorMessage message, IActorRef sender)
 {
     selection
     .Tell(message, sender);
 }
Example #12
0
 public static void TellEntitySelection(this ActorSelection selection, EntityActorMessage message)
 {
     selection
     .Tell(message);
 }
Example #13
0
 public static void TellEntityChildren(this IActorRefFactory selector, EntityActorMessage message, IEntityActorRef sender)
 {
     TellEntityChildren(selector, message, sender.Actor);
 }
        /// <inheritdoc />
        public async Task <bool> HandleMessageAsync(EntityActorMessageContext context, EntityActorMessage message, CancellationToken token = default)
        {
            //We don't lock here even though dictionary is publicly mutable
            //But we discourage calling it.
            if (!MessageHandlerMap.ContainsKey(message.GetType()))
            {
                return(false);
            }

            foreach (var handler in MessageHandlerMap[message.GetType()])
            {
                await handler.HandleMessageAsync(context, message, token);
            }

            return(true);
        }