コード例 #1
0
        /// <summary>
        /// Shutdown everything from this node down
        /// </summary>
        public Unit Shutdown(bool maintainState)
        {
            lock (sync)
            {
                if (maintainState == false)
                {
                    cluster.IfSome(c =>
                    {
                        // TODO: Make this transactional
                        // {
                        c.Delete(StateKey);
                        c.Delete(ActorInboxCommon.ClusterUserInboxKey(Id));
                        c.Delete(ActorInboxCommon.ClusterSystemInboxKey(Id));
                        c.Delete(ActorInboxCommon.ClusterMetaDataKey(Id));
                        ActorContext.DeregisterById(Id);
                        // }
                    });
                }

                RemoveAllSubscriptions();
                publishSubject.OnCompleted();
                stateSubject.OnCompleted();
                remoteSubsAcquired = false;
                strategyState      = StrategyState.Empty;
                DisposeState();

                ActorContext.DispatchTerminate(Id);

                return(unit);
            }
        }
コード例 #2
0
        StrategyContext(
            StrategyState global,
            Exception exception,
            object message,
            ProcessId sender,
            ProcessId failedProcess,
            ProcessId parentProcess,
            IEnumerable <ProcessId> siblings,
            IEnumerable <ProcessId> affects,
            Time pause,
            Option <Directive> directive,
            Option <MessageDirective> messageDirective
            )
        {
            bool isStop = directive == LanguageExt.Directive.Stop;

            Global           = isStop ? StrategyState.Empty : global;
            Exception        = exception;
            Message          = message;
            Sender           = sender;
            Self             = failedProcess;
            ParentProcess    = parentProcess;
            Siblings         = siblings ?? Siblings;
            Affects          = affects ?? Affects;
            Pause            = isStop ? 0 * s : pause;
            Directive        = directive;
            MessageDirective = messageDirective;
        }
コード例 #3
0
ファイル: Actor.cs プロジェクト: dhalsim/language-ext
        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);
            }
        }
コード例 #4
0
ファイル: Actor.cs プロジェクト: dhalsim/language-ext
        public InboxDirective RunStrategy(
            ProcessId pid,
            ProcessId parent,
            ProcessId sender,
            IEnumerable <ProcessId> siblings,
            Exception ex,
            object message,
            State <StrategyContext, Unit> strategy
            )
        {
            try
            {
                // Build a strategy specifically for this event
                var failureStrategy = strategy.Failure(
                    pid,
                    parent,
                    sender,
                    siblings,
                    ex,
                    message
                    );

                // Invoke the strategy with the running state
                var result   = failureStrategy(strategyState);
                var decision = result.Value;

                // Save the strategy state back to the actor
                strategyState = result.State;

                if (decision.ProcessDirective.Type != DirectiveType.Stop && decision.Pause > 0 * seconds)
                {
                    decision.Affects.Iter(p => pause(p));
                    safedelay(
                        () => RunProcessDirective(pid, sender, ex, message, decision),
                        decision.Pause
                        );
                    return(InboxDirective.Pause | RunMessageDirective(pid, sender, decision, ex, message));
                }
                else
                {
                    // Run the instruction for the Process (stop/restart/etc.)
                    RunProcessDirective(pid, sender, ex, message, decision);
                }

                // Run the instruction for the message (dead-letters/send-to-self/...)
                return(RunMessageDirective(pid, sender, decision, ex, message));
            }
            catch (Exception e)
            {
                logErr("Strategy exception in " + Id, e);
                return(InboxDirective.Default);
            }
        }
コード例 #5
0
ファイル: Actor.cs プロジェクト: dhalsim/language-ext
        /// <summary>
        /// Shutdown everything from this node down
        /// </summary>
        public Unit Shutdown(bool maintainState)
        {
            lock (sync)
            {
                if (maintainState == false && Flags != ProcessFlags.Default)
                {
                    cluster.IfSome(c =>
                    {
                        // TODO: Make this transactional
                        // {
                        c.DeleteMany(
                            StateKey,
                            ActorInboxCommon.ClusterUserInboxKey(Id),
                            ActorInboxCommon.ClusterSystemInboxKey(Id),
                            ActorInboxCommon.ClusterMetaDataKey(Id),
                            ActorInboxCommon.ClusterSettingsKey(Id));

                        ActorContext.DeregisterById(Id);
                        // }

                        ProcessConfig.Settings.ClearInMemorySettingsOverride(ActorInboxCommon.ClusterSettingsKey(Id));
                    });
                }

                RemoveAllSubscriptions();
                publishSubject.OnCompleted();
                stateSubject.OnCompleted();
                remoteSubsAcquired = false;
                strategyState      = StrategyState.Empty;
                DisposeState();

                ActorContext.DispatchTerminate(Id);

                return(unit);
            }
        }
コード例 #6
0
        public StrategyContext With(
            StrategyState Global             = null,
            Exception Exception              = null,
            object Message                   = null,
            ProcessId?Sender                 = null,
            ProcessId?FailedProcess          = null,
            ProcessId?ParentProcess          = null,
            IEnumerable <ProcessId> Siblings = null,
            IEnumerable <ProcessId> Affects  = null,
            Time?Pause = null,
            Option <Directive> Directive = default(Option <Directive>),
            Option <MessageDirective> MessageDirective = default(Option <MessageDirective>)
            ) =>
        new StrategyContext(
            Global ?? this.Global,
            Exception ?? this.Exception,
            Message ?? this.Message,
            Sender ?? this.Sender,
            FailedProcess ?? this.Self,
            ParentProcess ?? this.ParentProcess,
            Siblings ?? this.Siblings,
            Affects ?? this.Affects,
            Pause ?? this.Pause,

            // The following may look like bugs, but it's intentional that when
            // a Directive or MessageDirective is set, they stay set to their first
            // concrete value.  That means the State strategy expression that runs
            // has the equivalent of an 'early out'.  The whole expression is still
            // processed, but you can't override the earlier value.
            this.Directive.IsSome
                    ? this.Directive
                    : Directive,
            this.MessageDirective.IsSome
                    ? this.MessageDirective
                    : MessageDirective
            );
コード例 #7
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;

                    //ActorContext.AssertSession();

                    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
                        );
                }
                catch (Exception e)
                {
                    return(DefaultErrorHandler(message, e));
                }
                finally
                {
                    ActorContext.CurrentRequest = savedReq;
                    ActorContext.ProcessFlags   = savedFlags;
                    ActorContext.CurrentMsg     = savedMsg;
                }
                return(InboxDirective.Default);
            }
        }
コード例 #8
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
                        );
                }
                catch (Exception e)
                {
                    replyError(e);
                    return(DefaultErrorHandler(request, e));
                }
                finally
                {
                    ActorContext.CurrentMsg     = savedMsg;
                    ActorContext.ProcessFlags   = savedFlags;
                    ActorContext.CurrentRequest = savedReq;
                }
                return(InboxDirective.Default);
            }
        }