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; } }
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); } }
public ActorRequestContext SetOps(ProcessOpTransaction ops) => new ActorRequestContext( Self, Sender, Parent, CurrentMsg, CurrentRequest, ProcessFlags, ops );
/// <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); }
/// <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); }
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; }
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); }
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); }
public void SetOps(ProcessOpTransaction ops) { Ops = ops; }
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); } }