public ActorItem ActorCreate <T>(ActorItem parent, ProcessName name, Action <T> actorFn, Func <Unit, ProcessId, Unit> termFn, ProcessFlags flags, int maxMailboxSize = -1) { return(ActorCreate <Unit, T>(parent, name, (s, t) => { actorFn(t); return unit; }, () => unit, termFn, flags, maxMailboxSize)); }
public Unit Startup(IActor pid, ActorItem parent, Option <ICluster> cluster, int maxMailboxSize) => unit;
public Unit LinkChild(ActorItem item) => unit;
public ProcessId ActorCreate <S, T>( ActorItem parent, ProcessName name, Func <S, T, S> actorFn, Func <IActor, S> setupFn, Func <S, ProcessId, S> termFn, State <StrategyContext, Unit> strategy, ProcessFlags flags, int maxMailboxSize, bool lazy) { var actor = new Actor <S, T>(cluster, parent, name, actorFn, setupFn, termFn, strategy, flags, ActorContext.System(parent.Actor.Id).Settings, this); IActorInbox inbox = null; if ((actor.Flags & ProcessFlags.ListenRemoteAndLocal) == ProcessFlags.ListenRemoteAndLocal && cluster.IsSome) { inbox = new ActorInboxDual <S, T>(); } else if ((actor.Flags & ProcessFlags.PersistInbox) == ProcessFlags.PersistInbox && cluster.IsSome) { inbox = new ActorInboxRemote <S, T>(); } else { inbox = new ActorInboxLocal <S, T>(); } var item = new ActorItem(actor, inbox, actor.Flags); parent.Actor.LinkChild(item); // Auto register if there are config settings and we // have the variable name it was assigned to. ActorContext.System(actor.Id).Settings.GetProcessRegisteredName(actor.Id).Iter(regName => { // Also check if 'dispatch' is specified in the config, if so we will // register the Process as a role dispatcher PID instead of just its // PID. ActorContext.System(actor.Id).Settings.GetProcessDispatch(actor.Id) .Match( Some: disp => Process.register(regName, Disp[$"role-{disp}"][Role.Current].Append(actor.Id.Skip(1))), None: () => Process.register(regName, actor.Id) ); }); try { inbox.Startup(actor, parent, cluster, maxMailboxSize); if (!lazy) { TellSystem(actor.Id, SystemMessage.StartupProcess(false)); } } catch { item?.Actor?.ShutdownProcess(false); throw; } return(item.Actor.Id); }
public Unit WithContext(ActorItem self, ActorItem parent, ProcessId sender, ActorRequest request, object msg, Option <SessionId> sessionId, Action f) => WithContext(self, parent, sender, request, msg, sessionId, fun(f));
public static InboxDirective SystemMessageInbox <S, T>(Actor <S, T> actor, IActorInbox inbox, SystemMessage msg, ActorItem parent) { var session = msg.SessionId == null ? None : Some(new SessionId(msg.SessionId)); return(ActorContext.System(actor.Id).WithContext(new ActorItem(actor, inbox, actor.Flags), parent, ProcessId.NoSender, null, msg, session, () => { switch (msg.Tag) { case Message.TagSpec.Restart: actor.Restart(inbox.IsPaused); break; case Message.TagSpec.LinkChild: var lc = msg as SystemLinkChildMessage; actor.LinkChild(lc.Child); break; case Message.TagSpec.UnlinkChild: var ulc = (msg as SystemUnLinkChildMessage).SetSystem(actor.Id.System); actor.UnlinkChild(ulc.Child); break; case Message.TagSpec.ChildFaulted: var cf = (msg as SystemChildFaultedMessage).SetSystem(actor.Id.System); return actor.ChildFaulted(cf.Child, cf.Sender, cf.Exception, cf.Message); case Message.TagSpec.StartupProcess: var startupProcess = msg as StartupProcessMessage; var inboxDirective = actor.Startup(); // get feedback whether startup will somehow trigger Unpause itself (i.e. error => strategy => restart) if (startupProcess.UnpauseAfterStartup && !inboxDirective.HasFlag(InboxDirective.Pause)) { inbox.Unpause(); } break; case Message.TagSpec.ShutdownProcess: var shutdownProcess = msg as ShutdownProcessMessage; actor.ShutdownProcess(shutdownProcess.MaintainState); break; case Message.TagSpec.Unpause: inbox.Unpause(); break; case Message.TagSpec.Pause: inbox.Pause(); break; // do not return InboxDirective.Pause because system queue should never pause case Message.TagSpec.Watch: var awm = msg as SystemAddWatcherMessage; actor.AddWatcher(awm.Id); break; case Message.TagSpec.UnWatch: var rwm = msg as SystemRemoveWatcherMessage; actor.RemoveWatcher(rwm.Id); break; case Message.TagSpec.DispatchWatch: var dwm = msg as SystemDispatchWatchMessage; actor.DispatchWatch(dwm.Id); break; case Message.TagSpec.DispatchUnWatch: var duwm = msg as SystemDispatchUnWatchMessage; actor.DispatchUnWatch(duwm.Id); break; } return InboxDirective.Default; })); }
public ActorSystem(SystemName systemName, Option <ICluster> cluster, AppProfile appProfile, ProcessSystemConfig settings) { var name = GetRootProcessName(cluster); 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."); } SystemName = systemName; this.appProfile = appProfile; this.settings = settings; this.cluster = cluster; Ping = new Ping(this); startupTimestamp = DateTime.UtcNow.Ticks; sessionManager = new SessionManager(cluster, SystemName, appProfile.NodeName, VectorConflictStrategy.Branch); watchers = Map <ProcessId, Set <ProcessId> >(); watchings = Map <ProcessId, Set <ProcessId> >(); startupSubscription = NotifyCluster(cluster, startupTimestamp); Dispatch.init(); Role.init(cluster.Map(r => r.Role).IfNone("local")); Reg.init(); var root = ProcessId.Top.Child(GetRootProcessName(cluster)); var rootInbox = new ActorInboxLocal <ActorSystemBootstrap, Unit>(); var parent = new ActorItem(new NullProcess(SystemName), new NullInbox(), ProcessFlags.Default); var state = new ActorSystemBootstrap( this, cluster, root, null, rootInbox, cluster.Map(x => x.NodeName).IfNone(ActorSystemConfig.Default.RootProcessName), ActorSystemConfig.Default, Settings, sessionManager.Sync ); var rootProcess = state.RootProcess; state.Startup(); rootItem = new ActorItem(rootProcess, rootInbox, ProcessFlags.Default); Root = rootItem.Actor.Id; RootJS = Root["js"]; System = Root[ActorSystemConfig.Default.SystemProcessName]; User = Root[ActorSystemConfig.Default.UserProcessName]; Errors = System[ActorSystemConfig.Default.ErrorsProcessName]; DeadLetters = System[ActorSystemConfig.Default.DeadLettersProcessName]; NodeName = cluster.Map(c => c.NodeName).IfNone("user"); AskId = System[ActorSystemConfig.Default.AskProcessName]; Disp = ProcessId.Top["disp"].SetSystem(SystemName); Scheduler = System[ActorSystemConfig.Default.SchedulerName]; userContext = new ActorRequestContext( this, rootProcess.Children["user"], ProcessId.NoSender, rootItem, null, null, ProcessFlags.Default, null); rootInbox.Startup(rootProcess, parent, cluster, settings.GetProcessMailboxSize(rootProcess.Id)); }
public static InboxDirective UserMessageInbox <S, T>(Actor <S, T> actor, IActorInbox inbox, UserControlMessage msg, ActorItem parent) { var session = msg.SessionId == null ? None : Some(new SessionId(msg.SessionId)); switch (msg.Tag) { case Message.TagSpec.UserAsk: var rmsg = ((ActorRequest)msg).SetSystem(actor.Id.System); return(ActorContext.System(actor.Id).WithContext(new ActorItem(actor, inbox, actor.Flags), parent, rmsg.ReplyTo, rmsg, msg, session, () => actor.ProcessAsk(rmsg))); case Message.TagSpec.UserReply: var urmsg = ((ActorResponse)msg).SetSystem(actor.Id.System); ActorContext.System(actor.Id).WithContext(new ActorItem(actor, inbox, actor.Flags), parent, urmsg.ReplyFrom, null, msg, session, () => actor.ProcessResponse(urmsg)); break; case Message.TagSpec.UserTerminated: var utmsg = ((TerminatedMessage)msg).SetSystem(actor.Id.System); return(ActorContext.System(actor.Id).WithContext(new ActorItem(actor, inbox, actor.Flags), parent, utmsg.Id, null, msg, session, () => actor.ProcessTerminated(utmsg.Id))); case Message.TagSpec.User: var umsg = ((UserMessage)msg).SetSystem(actor.Id.System); return(ActorContext.System(actor.Id).WithContext(new ActorItem(actor, inbox, actor.Flags), parent, umsg.Sender, null, msg, session, () => actor.ProcessMessage(umsg.Content))); case Message.TagSpec.ShutdownProcess: kill(actor.Id); break; } return(InboxDirective.Default); }
public static InboxDirective SystemMessageInbox <S, T>(Actor <S, T> actor, IActorInbox inbox, SystemMessage msg, ActorItem parent) { var session = msg.SessionId == null ? None : Some(new SessionId(msg.SessionId)); return(ActorContext.System(actor.Id).WithContext(new ActorItem(actor, inbox, actor.Flags), parent, ProcessId.NoSender, null, msg, session, () => { switch (msg.Tag) { case Message.TagSpec.Restart: if (inbox.IsPaused) { inbox.Unpause(); } actor.Restart(); break; case Message.TagSpec.LinkChild: var lc = msg as SystemLinkChildMessage; actor.LinkChild(lc.Child); break; case Message.TagSpec.UnlinkChild: var ulc = (msg as SystemUnLinkChildMessage).SetSystem(actor.Id.System); actor.UnlinkChild(ulc.Child); break; case Message.TagSpec.ChildFaulted: var cf = (msg as SystemChildFaultedMessage).SetSystem(actor.Id.System); return actor.ChildFaulted(cf.Child, cf.Sender, cf.Exception, cf.Message); case Message.TagSpec.StartupProcess: actor.Startup(); break; case Message.TagSpec.ShutdownProcess: var sp = msg as ShutdownProcessMessage; actor.ShutdownProcess(sp.MaintainState); break; case Message.TagSpec.Unpause: inbox.Unpause(); break; case Message.TagSpec.Pause: inbox.Pause(); return InboxDirective.Pause; case Message.TagSpec.Watch: var awm = msg as SystemAddWatcherMessage; actor.AddWatcher(awm.Id); break; case Message.TagSpec.UnWatch: var rwm = msg as SystemRemoveWatcherMessage; actor.RemoveWatcher(rwm.Id); break; case Message.TagSpec.DispatchWatch: var dwm = msg as SystemDispatchWatchMessage; actor.DispatchWatch(dwm.Id); break; case Message.TagSpec.DispatchUnWatch: var duwm = msg as SystemDispatchUnWatchMessage; actor.DispatchUnWatch(duwm.Id); break; } return InboxDirective.Default; })); }
/// <summary> /// Gains a child process /// </summary> public Unit LinkChild(ActorItem item) { children.Swap(c => c.AddOrUpdate(item.Actor.Id.Name.Value, item)); return(unit); }
public SystemLinkChildMessage(ActorItem child) { Child = child; }
public static SystemMessage LinkChild(ActorItem item) => new SystemLinkChildMessage(item);