Пример #1
0
        public static R WithContext <R>(ActorItem self, ActorItem parent, ProcessId sender, ActorRequest request, object msg, Option <string> sessionId, Func <R> f)
        {
            var savedContext = context;
            var savedSession = SessionManager.SessionId;

            try
            {
                SessionManager.SessionId = sessionId;
                context = new ActorRequestContext(
                    self,
                    sender,
                    parent,
                    msg,
                    request,
                    ProcessFlags.Default,
                    ProcessOpTransaction.Start(self.Actor.Id)
                    );
                return(f());
            }
            finally
            {
                SessionManager.SessionId = savedSession;
                context = savedContext;
            }
        }
Пример #2
0
        public R WithContext <R>(ActorItem self, ActorItem parent, ProcessId sender, ActorRequest request, object msg, Option <SessionId> sessionId, Func <R> f)
        {
            var savedContext = ActorContext.Request;
            var savedSession = ActorContext.SessionId;

            try
            {
                ActorContext.SessionId = sessionId;

                ActorContext.SetContext(new ActorRequestContext(
                                            this,
                                            self,
                                            sender,
                                            parent,
                                            msg,
                                            request,
                                            ProcessFlags.Default,
                                            ProcessOpTransaction.Start(self.Actor.Id),
                                            (from sid in sessionId
                                             from ses in ActorContext.System(self.Actor.Id).Sessions.GetSession(sid)
                                             select ses)
                                            .IfNoneUnsafe((SessionVector)null)
                                            ));
                return(f());
            }
            finally
            {
                ActorContext.SessionId = savedSession;
                ActorContext.SetContext(savedContext);
            }
        }
Пример #3
0
 public ActorRequestContext SetOps(ProcessOpTransaction ops) =>
 new ActorRequestContext(
     Self,
     Sender,
     Parent,
     CurrentMsg,
     CurrentRequest,
     ProcessFlags,
     ops
     );
Пример #4
0
 /// <summary>
 /// Run the operations that affect the settings and sending of tells
 /// in the order which they occured in the actor
 /// </summary>
 public static Unit RunContextOps()
 {
     if (Context.Ops != null)
     {
         while (Context.Ops.Ops.Count > 0)
         {
             var ops = Context.Ops;
             Context = Context.SetOps(ProcessOpTransaction.Start(Context.Self.Actor.Id));
             ops.Run();
         }
     }
     return(unit);
 }
Пример #5
0
 /// <summary>
 /// Run the operations that affect the settings and sending of tells
 /// in the order which they occured in the actor
 /// </summary>
 public Unit RunOps()
 {
     if (Ops != null)
     {
         while (Ops.Ops.Count > 0)
         {
             var ops = Ops;
             Ops = ProcessOpTransaction.Start(Ops.ProcessId);
             ops.Run();
         }
     }
     return(unit);
 }
Пример #6
0
 public ActorRequestContext(
     ActorItem self,
     ProcessId sender,
     ActorItem parent,
     object currentMsg,
     ActorRequest currentRequest,
     ProcessFlags processFlags,
     ProcessOpTransaction ops
     )
 {
     Self           = self;
     Sender         = sender;
     Parent         = parent;
     CurrentMsg     = currentMsg;
     CurrentRequest = currentRequest;
     ProcessFlags   = processFlags;
     Ops            = ops;
 }
Пример #7
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);
        }
Пример #8
0
        public static Unit Startup(Option <ICluster> cluster)
        {
            if (started)
            {
                return(unit);
            }

            ActorContext.cluster = cluster;
            var name = GetRootProcessName();

            if (name.Value == "root" && cluster.IsSome)
            {
                throw new ArgumentException("Cluster node name cannot be 'root', it's reserved for local use only.");
            }
            if (name.Value == "disp" && cluster.IsSome)
            {
                throw new ArgumentException("Cluster node name cannot be 'disp', it's reserved for internal use.");
            }
            if (name.Value == "js")
            {
                throw new ArgumentException("Node name cannot be 'js', it's reserved for ProcessJS.");
            }

            lock (sync)
            {
                if (started)
                {
                    return(unit);
                }

                startupTimestamp = DateTime.UtcNow.Ticks;
                startupSubscription?.Dispose();
                startupSubscription = NotifyCluster(cluster, startupTimestamp);

                Dispatch.init();
                Role.init(cluster.Map(r => r.Role).IfNone("local"));
                Reg.init();

                watchers  = Map.empty <ProcessId, Set <ProcessId> >();
                watchings = Map.empty <ProcessId, Set <ProcessId> >();
                var root      = ProcessId.Top.Child(name);
                var rootInbox = new ActorInboxLocal <ActorSystemState, Unit>();
                var parent    = new ActorItem(new NullProcess(), new NullInbox(), ProcessFlags.Default);

                var go    = new AutoResetEvent(false);
                var state = new ActorSystemState(
                    cluster,
                    root, null,
                    rootInbox,
                    cluster.Map(x => x.NodeName).IfNone(ActorSystemConfig.Default.RootProcessName),
                    ActorSystemConfig.Default
                    );
                var rootProcess = state.RootProcess;
                state.Startup();
                userContext = new ActorRequestContext(
                    rootProcess.Children["user"],
                    ProcessId.NoSender,
                    rootItem,
                    null,
                    null,
                    ProcessFlags.Default,
                    ProcessOpTransaction.Start(rootProcess.Children["user"].Actor.Id)
                    );
                rootInbox.Startup(rootProcess, parent, cluster, ProcessConfig.Settings.GetProcessMailboxSize(rootProcess.Id));
                rootItem = new ActorItem(rootProcess, rootInbox, ProcessFlags.Default);
                started  = true;

                SessionManager.Init(cluster);
                ClusterWatch(cluster);
            }
            return(unit);
        }
Пример #9
0
 public void SetOps(ProcessOpTransaction ops)
 {
     Ops = ops;
 }
Пример #10
0
        public InboxDirective ProcessAsk(ActorRequest request)
        {
            lock (sync)
            {
                var savedMsg   = ActorContext.Request.CurrentMsg;
                var savedFlags = ActorContext.Request.ProcessFlags;
                var savedReq   = ActorContext.Request.CurrentRequest;

                try
                {
                    ActorContext.Request.CurrentRequest = request;
                    ActorContext.Request.ProcessFlags   = flags;
                    ActorContext.Request.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.Request.RunOps();
                }
                catch (Exception e)
                {
                    ActorContext.Request.SetOps(ProcessOpTransaction.Start(Id));
                    replyError(e);
                    ActorContext.Request.RunOps();
                    return(DefaultErrorHandler(request, e));
                }
                finally
                {
                    ActorContext.Request.CurrentMsg     = savedMsg;
                    ActorContext.Request.ProcessFlags   = savedFlags;
                    ActorContext.Request.CurrentRequest = savedReq;
                }
                return(InboxDirective.Default);
            }
        }