Ejemplo n.º 1
0
        public InboxDirective ProcessTerminated(ProcessId pid)
        {
            if (termFn == null)
            {
                return(InboxDirective.Default);
            }

            lock (sync)
            {
                var savedReq   = ActorContext.CurrentRequest;
                var savedFlags = ActorContext.ProcessFlags;
                var savedMsg   = ActorContext.CurrentMsg;

                try
                {
                    ActorContext.CurrentRequest = null;
                    ActorContext.ProcessFlags   = flags;
                    ActorContext.CurrentMsg     = pid;

                    //ActorContext.AssertSession();

                    var stateIn  = GetState();
                    var stateOut = termFn(GetState(), pid);
                    state = stateOut;

                    try
                    {
                        if (notnull(stateOut) && !state.Equals(stateIn))
                        {
                            stateSubject.OnNext(stateOut);
                        }
                    }
                    catch (Exception ue)
                    {
                        // Not our errors, so just log and move on
                        logErr(ue);
                    }

                    strategyState = strategyState.With(
                        Failures: 0,
                        LastFailure: DateTime.MaxValue,
                        BackoffAmount: 0 * seconds
                        );

                    ActorContext.RunContextOps();
                }
                catch (Exception e)
                {
                    return(DefaultErrorHandler(pid, e));
                }
                finally
                {
                    ActorContext.CurrentRequest = savedReq;
                    ActorContext.ProcessFlags   = savedFlags;
                    ActorContext.CurrentMsg     = savedMsg;
                }
                return(InboxDirective.Default);
            }
        }
Ejemplo n.º 2
0
        S InitState()
        {
            S state;

            try
            {
                SetupRemoteSubscriptions(cluster, flags);

                if (cluster.IsSome && ((flags & ProcessFlags.PersistState) == ProcessFlags.PersistState))
                {
                    try
                    {
                        logInfo($"Restoring state: {StateKey}");

                        state = cluster.LiftUnsafe().Exists(StateKey)
                            ? cluster.LiftUnsafe().GetValue <S>(StateKey)
                            : setupFn(this);
                    }
                    catch (Exception e)
                    {
                        logSysErr(e);
                        state = setupFn(this);
                    }
                }
                else
                {
                    state = setupFn(this);
                }

                ActorContext.RunContextOps();
            }
            catch (Exception e)
            {
                throw new ProcessSetupException(Id.Path, e);
            }

            try
            {
                stateSubject.OnNext(state);
            }
            catch (Exception ue)
            {
                // Not our errors, so just log and move on
                logErr(ue);
            }
            return(state);
        }
Ejemplo n.º 3
0
        InboxDirective DefaultErrorHandler(object message, Exception e)
        {
            // Wipe all transactional outputs because of the error
            ActorContext.Context = ActorContext.Context.SetOps(ProcessOpTransaction.Start(Id));

            var directive = RunStrategy(
                Id,
                Parent.Actor.Id,
                Sender,
                Parent.Actor.Children.Values.Map(n => n.Actor.Id).Filter(x => x != Id),
                e,
                message,
                Parent.Actor.Strategy
                );

            if (!(e is ProcessKillException))
            {
                tell(ActorContext.Errors, e);
            }

            // Run any transactional outputs caused by the strategy computation
            ActorContext.RunContextOps();
            return(directive);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Process an inbox message
        /// </summary>
        /// <param name="message"></param>
        /// <returns></returns>
        public InboxDirective ProcessMessage(object message)
        {
            lock (sync)
            {
                var savedReq   = ActorContext.CurrentRequest;
                var savedFlags = ActorContext.ProcessFlags;
                var savedMsg   = ActorContext.CurrentMsg;

                try
                {
                    ActorContext.CurrentRequest = null;
                    ActorContext.ProcessFlags   = flags;
                    ActorContext.CurrentMsg     = message;

                    if (typeof(T) != typeof(string) && message is string)
                    {
                        state = PreProcessMessageContent(message).Match(
                            Some: tmsg =>
                        {
                            var stateIn  = GetState();
                            var stateOut = actorFn(stateIn, tmsg);
                            try
                            {
                                if (notnull(stateOut) && !stateOut.Equals(stateIn))
                                {
                                    stateSubject.OnNext(stateOut);
                                }
                            }
                            catch (Exception ue)
                            {
                                // Not our errors, so just log and move on
                                logErr(ue);
                            }
                            return(stateOut);
                        },
                            None: () => state
                            );
                    }
                    else if (message is T)
                    {
                        var stateIn  = GetState();
                        var stateOut = actorFn(GetState(), (T)message);
                        state = stateOut;
                        try
                        {
                            if (notnull(stateOut) && !state.Equals(stateIn))
                            {
                                stateSubject.OnNext(stateOut);
                            }
                        }
                        catch (Exception ue)
                        {
                            // Not our errors, so just log and move on
                            logErr(ue);
                        }
                    }
                    else if (message is Message)
                    {
                        ProcessSystemMessage((Message)message);
                    }
                    else
                    {
                        logErr($"Can't tell {Id.Path}, message is not {typeof(T).GetTypeInfo().Name} : {message}");
                        return(InboxDirective.Default);
                    }

                    strategyState = strategyState.With(
                        Failures: 0,
                        LastFailure: DateTime.MaxValue,
                        BackoffAmount: 0 * seconds
                        );

                    ActorContext.RunContextOps();
                }
                catch (Exception e)
                {
                    return(DefaultErrorHandler(message, e));
                }
                finally
                {
                    ActorContext.CurrentRequest = savedReq;
                    ActorContext.ProcessFlags   = savedFlags;
                    ActorContext.CurrentMsg     = savedMsg;
                }
                return(InboxDirective.Default);
            }
        }
Ejemplo n.º 5
0
        public InboxDirective ProcessAsk(ActorRequest request)
        {
            lock (sync)
            {
                var savedMsg   = ActorContext.CurrentMsg;
                var savedFlags = ActorContext.ProcessFlags;
                var savedReq   = ActorContext.CurrentRequest;

                try
                {
                    ActorContext.CurrentRequest = request;
                    ActorContext.ProcessFlags   = flags;
                    ActorContext.CurrentMsg     = request.Message;

                    //ActorContext.AssertSession();

                    if (typeof(T) != typeof(string) && request.Message is string)
                    {
                        state = PreProcessMessageContent(request.Message).Match(
                            Some: tmsg =>
                        {
                            var stateIn  = GetState();
                            var stateOut = actorFn(stateIn, tmsg);
                            try
                            {
                                if (notnull(stateOut) && !stateOut.Equals(stateIn))
                                {
                                    stateSubject.OnNext(stateOut);
                                }
                            }
                            catch (Exception ue)
                            {
                                // Not our errors, so just log and move on
                                logErr(ue);
                            }
                            return(stateOut);
                        },
                            None: () =>
                        {
                            replyError(new AskException($"Can't ask {Id.Path}, message is not {typeof(T).GetTypeInfo().Name} : {request.Message}"));
                            return(state);
                        }
                            );
                    }
                    else if (request.Message is T)
                    {
                        var msg      = (T)request.Message;
                        var stateIn  = GetState();
                        var stateOut = actorFn(stateIn, msg);
                        try
                        {
                            if (notnull(stateOut) && !stateOut.Equals(stateIn))
                            {
                                stateSubject.OnNext(stateOut);
                            }
                        }
                        catch (Exception ue)
                        {
                            // Not our errors, so just log and move on
                            logErr(ue);
                        }
                        state = stateOut;
                    }
                    else if (request.Message is Message)
                    {
                        ProcessSystemMessage((Message)request.Message);
                    }
                    else
                    {
                        // Failure to deserialise is not our problem, its the sender's
                        // so we don't throw here.
                        replyError(new AskException($"Can't ask {Id.Path}, message is not {typeof(T).GetTypeInfo().Name} : {request.Message}"));
                        return(InboxDirective.Default);
                    }

                    strategyState = strategyState.With(
                        Failures: 0,
                        LastFailure: DateTime.MaxValue,
                        BackoffAmount: 0 * seconds
                        );

                    ActorContext.RunContextOps();
                }
                catch (Exception e)
                {
                    replyError(e);
                    return(DefaultErrorHandler(request, e));
                }
                finally
                {
                    ActorContext.CurrentMsg     = savedMsg;
                    ActorContext.ProcessFlags   = savedFlags;
                    ActorContext.CurrentRequest = savedReq;
                }
                return(InboxDirective.Default);
            }
        }