public static Option <Tuple <RemoteMessageDTO, Message> > GetNextMessage(ICluster cluster, ProcessId self, string key)
        {
            if (cluster == null)
            {
                return(None);
            }
            Message          msg = null;
            RemoteMessageDTO dto = null;

            dto = null;
            do
            {
                dto = cluster.Peek <RemoteMessageDTO>(key);
                if (dto == null)
                {
                    // Queue is empty
                    return(None);
                }
                if (dto.Tag == 0 && dto.Type == 0)
                {
                    // Message is bad
                    cluster.Dequeue <RemoteMessageDTO>(key);
                    tell(ActorContext.System(self).DeadLetters, DeadLetter.create(dto.Sender, self, null, "Failed to deserialise message: ", dto));
                    if (cluster.QueueLength(key) == 0)
                    {
                        return(None);
                    }
                }
            }while (dto == null || dto.Tag == 0 || dto.Type == 0);

            try
            {
                msg = MessageSerialiser.DeserialiseMsg(dto, self);
            }
            catch (Exception e)
            {
                // Message can't be deserialised
                cluster.Dequeue <RemoteMessageDTO>(key);
                tell(ActorContext.System(self).DeadLetters, DeadLetter.create(dto.Sender, self, e, "Failed to deserialise message: ", msg));
                return(None);
            }

            return(Some(Tuple(dto, msg)));
        }
        void CheckRemoteInbox(string key, bool pausable)
        {
            var inbox = this;
            var count = cluster.QueueLength(key);

            while (count > 0 && (!pausable || !IsPaused))
            {
                var directive = InboxDirective.Default;

                ActorInboxCommon.GetNextMessage(cluster, actor.Id, key).IfSome(
                    x => iter(x, (dto, msg) =>
                {
                    try
                    {
                        switch (msg.MessageType)
                        {
                        case Message.Type.User:        directive = ActorInboxCommon.UserMessageInbox(actor, inbox, (UserControlMessage)msg, parent); break;

                        case Message.Type.UserControl: directive = ActorInboxCommon.UserMessageInbox(actor, inbox, (UserControlMessage)msg, parent); break;
                        }
                    }
                    catch (Exception e)
                    {
                        ActorContext.WithContext(new ActorItem(actor, inbox, actor.Flags), parent, dto.Sender, msg as ActorRequest, msg, msg.SessionId, () => replyErrorIfAsked(e));
                        tell(ActorContext.DeadLetters, DeadLetter.create(dto.Sender, actor.Id, e, "Remote message inbox.", msg));
                        logSysErr(e);
                    }
                    finally
                    {
                        if (directive == InboxDirective.Default)
                        {
                            cluster.Dequeue <RemoteMessageDTO>(key);
                        }
                    }
                }));

                if (directive == InboxDirective.Default)
                {
                    count--;
                }
            }
        }
Ejemplo n.º 3
0
 public static object Invoke4(ProcessId pid, string method, Type rettyp, object arg1, object arg2, object arg3, object arg4)
 {
     return(ActorContext.Ask(pid, new ProxyMsg
     {
         Method = method,
         Args = new string[] {
             JsonConvert.SerializeObject(arg1),
             JsonConvert.SerializeObject(arg2),
             JsonConvert.SerializeObject(arg3),
             JsonConvert.SerializeObject(arg4),
         },
         ArgTypes = new string[] {
             arg1.GetType().GetTypeInfo().FullName,
             arg2.GetType().GetTypeInfo().FullName,
             arg3.GetType().GetTypeInfo().FullName,
             arg4.GetType().GetTypeInfo().FullName
         },
         ReturnType = rettyp.GetTypeInfo().FullName
     }));
 }
Ejemplo n.º 4
0
        public Actor(ProcessId parent, ProcessName name, Func <S, T, S> actor, Func <S> setup)
        {
            if (setup == null)
            {
                throw new ArgumentNullException(nameof(setup));
            }
            if (actor == null)
            {
                throw new ArgumentNullException(nameof(actor));
            }

            actorFn = actor;
            setupFn = setup;
            Parent  = parent;
            Name    = name;
            Id      = new ProcessId(parent.Value + "/" + name);

            StartMailboxes();

            ActorContext.AddToStore(Id, this);
        }
Ejemplo n.º 5
0
 FSharpMailboxProcessor <TMsg> StartMailbox <TMsg>(Actor <S, T> actor, string key, CancellationToken cancelToken, Func <Actor <S, T>, IActorInbox, TMsg, ActorItem, InboxDirective> handler, bool pausable)
     where TMsg : Message =>
 ActorInboxCommon.Mailbox <TMsg>(cancelToken, msg =>
 {
     try
     {
         var directive = handler(actor, this, msg, parent);
         // TODO: Push msg to front of queue if directive requests it
     }
     catch (Exception e)
     {
         replyErrorIfAsked(e);
         tell(ActorContext.System(actor.Id).DeadLetters, DeadLetter.create(ActorContext.Request.Sender, actor.Id, e, "Remote message inbox.", msg));
         logSysErr(e);
     }
     finally
     {
         // Remove from queue, then see if there are any more to process.
         CheckRemoteInbox(key, cluster, actor.Id, sysInbox, userInbox, pausable);
     }
 });
        /// <summary>
        /// TODO: This is a combination of code in ActorCommon.GetNextMessage and
        ///       CheckRemoteInbox.  Some factoring is needed.
        /// </summary>
        void SysInbox(RemoteMessageDTO dto)
        {
            try
            {
                if (dto == null)
                {
                    // Failed to deserialise properly
                    return;
                }
                if (dto.Tag == 0 && dto.Type == 0)
                {
                    // Message is bad
                    tell(ActorContext.System(actor.Id).DeadLetters, DeadLetter.create(dto.Sender, actor.Id, null, "Failed to deserialise message: ", dto));
                    return;
                }
                var msg = MessageSerialiser.DeserialiseMsg(dto, actor.Id);

                try
                {
                    lock (sync)
                    {
                        ActorInboxCommon.SystemMessageInbox(actor, this, (SystemMessage)msg, parent);
                    }
                }
                catch (Exception e)
                {
                    var session = msg.SessionId == null
                        ? None
                        : Some(new SessionId(msg.SessionId));

                    ActorContext.System(actor.Id).WithContext(new ActorItem(actor, this, actor.Flags), parent, dto.Sender, msg as ActorRequest, msg, session, () => replyErrorIfAsked(e));
                    tell(ActorContext.System(actor.Id).DeadLetters, DeadLetter.create(dto.Sender, actor.Id, e, "Remote message inbox.", msg));
                    logSysErr(e);
                }
            }
            catch (Exception e)
            {
                logSysErr(e);
            }
        }
Ejemplo n.º 7
0
        public R ProcessRequest <R>(ProcessId pid, object message)
        {
            try
            {
                if (request != null)
                {
                    throw new Exception("async ask not allowed");
                }

                response = null;
                request  = new AutoResetEvent(false);
                ActorContext.Ask(pid, new ActorRequest(message, pid, Self, 0), Self);
                request.WaitOne(ActorConfig.Default.Timeout);

                if (response == null)
                {
                    throw new TimeoutException("Request timed out");
                }
                else
                {
                    if (response.IsFaulted)
                    {
                        var ex = (Exception)response.Message;
                        throw new ProcessException("Process issue: " + ex.Message, pid.Path, Self.Path, ex);
                    }
                    else
                    {
                        return((R)response.Message);
                    }
                }
            }
            finally
            {
                if (request != null)
                {
                    request.Dispose();
                    request = null;
                }
            }
        }
Ejemplo n.º 8
0
        public static void SystemMessageInbox <S, T>(Actor <S, T> actor, IActorInbox inbox, SystemMessage msg, ActorItem parent)
        {
            ActorContext.WithContext(new ActorItem(actor, inbox, actor.Flags), parent, ProcessId.NoSender, null, msg, () =>
            {
                switch (msg.Tag)
                {
                case Message.TagSpec.Restart:
                    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;
                    actor.UnlinkChild(ulc.Child);
                    break;
                }
            });
        }
Ejemplo n.º 9
0
        internal static IDisposable safedelay(Action f, TimeSpan delayFor)
        {
            var savedContext = ActorContext.Request;
            var savedSession = ActorContext.SessionId;

            return((IDisposable)Task.Delay(delayFor).ContinueWith(_ =>
            {
                try
                {
                    if (savedContext == null)
                    {
                        f();
                    }
                    else
                    {
                        ActorContext.System(savedContext.Self.Actor.Id).WithContext(
                            savedContext.Self,
                            savedContext.Parent,
                            savedContext.Sender,
                            savedContext.CurrentRequest,
                            savedContext.CurrentMsg,
                            savedSession,
                            () =>
                        {
                            f();

                            // Run the operations that affect the settings and sending of tells
                            // in the order which they occured in the actor
                            ActorContext.Request.Ops.Run();
                        });
                    }
                }
                catch (Exception e)
                {
                    logErr(e);
                }
            }));
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Spawn a router using the settings in the config
        /// </summary>
        /// <example>
        /// <para>
        ///     router broadcast1:
        ///         pid:			/root/user/broadcast1
        ///         route:	        broadcast
        ///         worker-count:	10
        /// </para>
        /// <para>
        ///     router broadcast2:
        ///         pid:			/root/user/broadcast2
        ///         route:	        broadcast
        ///         workers:		[hello, world]
        /// </para>
        /// <para>
        ///     router least:
        ///         pid:			/role/user/least
        ///         route:	        least-busy
        ///         workers:		[one, two, three]
        /// </para>
        /// </example>
        /// <typeparam name="T"></typeparam>
        /// <param name="name">Name of the child process that will be the router</param>
        /// <returns>ProcessId of the router</returns>
        public static ProcessId fromConfig <T>(ProcessName name)
        {
            var id      = Self[name];
            var type    = ActorContext.System(id).Settings.GetRouterDispatch(id);
            var workers = ActorContext.System(id).Settings.GetRouterWorkers(id)
                          .Map(p => p.ProcessId.IfNone(ProcessId.None))
                          .Filter(pid => pid != ProcessId.None);

            var flags = ActorContext.System(id).Settings.GetProcessFlags(id);
            var mbs   = ActorContext.System(id).Settings.GetProcessMailboxSize(id);

            return(type.Map(t =>
            {
                // TODO: Consider the best approach to generalise this, so that bespoke router
                //       types can make use of the config system too.
                switch (t)
                {
                case "broadcast":
                    return broadcast <T>(name, workers, RouterOption.Default, flags, mbs);

                case "hash":
                    return hash <T>(name, workers, null, RouterOption.Default, flags, mbs);

                case "least-busy":
                    return leastBusy <T>(name, workers, RouterOption.Default, flags, mbs);

                case "random":
                    return random <T>(name, workers, RouterOption.Default, flags, mbs);

                case "round-robin":
                    return roundRobin <T>(name, workers, RouterOption.Default, flags, mbs);

                default:
                    throw new Exception($"Unsupported router type (for config system setup): {t} ");
                }
            })
                   .IfNone(() => failwith <ProcessId>($"'route' not specified for {id}")));
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Spawn a router using the settings in the config
        /// </summary>
        /// <example>
        /// <para>
        ///     router broadcast1:
        ///         pid:			/root/user/broadcast1
        ///         route:	        broadcast
        ///         worker-count:	10
        /// </para>
        /// <para>
        ///     router broadcast2:
        ///         pid:			/root/user/broadcast2
        ///         route:	        broadcast
        ///         workers:		[hello, world]
        /// </para>
        /// <para>
        ///     router least:
        ///         pid:			/role/user/least
        ///         route:	        least-busy
        ///         workers:		[one, two, three]
        /// </para>
        /// </example>
        /// <typeparam name="T"></typeparam>
        /// <param name="name">Name of the child process that will be the router</param>
        /// <returns>ProcessId of the router</returns>
        public static ProcessId fromConfig <S, T>(ProcessName name, Func <S> Setup, Func <S, T, S> Inbox)
        {
            var id       = Self[name];
            var type     = ActorContext.System(id).Settings.GetRouterDispatch(id);
            var workers  = ActorContext.System(id).Settings.GetRouterWorkerCount(id);
            var flags    = ActorContext.System(id).Settings.GetProcessFlags(id);
            var mbs      = ActorContext.System(id).Settings.GetProcessMailboxSize(id);
            var strategy = ActorContext.System(id).Settings.GetProcessStrategy(id);
            var wrkrName = ActorContext.System(id).Settings.GetRouterWorkerName(id);

            return(type.Map(t =>
            {
                // TODO: Consider the best approach to generalise this, so that bespoke router
                //       types can make use of the config system too.
                switch (t)
                {
                case "broadcast":
                    return broadcast(name, workers.IfNone(2), Setup, Inbox, flags, strategy, mbs, wrkrName);

                case "hash":
                    return hash(name, workers.IfNone(2), Setup, Inbox, null, flags, strategy, mbs, wrkrName);

                case "least-busy":
                    return leastBusy(name, workers.IfNone(2), Setup, Inbox, flags, strategy, mbs, wrkrName);

                case "random":
                    return random(name, workers.IfNone(2), Setup, Inbox, flags, strategy, mbs, wrkrName);

                case "round-robin":
                    return roundRobin(name, workers.IfNone(2), Setup, Inbox, flags, strategy, mbs, wrkrName);

                default:
                    throw new Exception($"Unsupported router type (for config system setup): {t} ");
                }
            })
                   .IfNone(() => failwith <ProcessId>($"'route' not specified for {id}")));
        }
Ejemplo n.º 12
0
        public static void UserMessageInbox <S, T>(Actor <S, T> actor, IActorInbox inbox, UserControlMessage msg, ActorItem parent)
        {
            switch (msg.Tag)
            {
            case Message.TagSpec.UserAsk:
                var rmsg = (ActorRequest)msg;
                ActorContext.WithContext(new ActorItem(actor, inbox, actor.Flags), parent, rmsg.ReplyTo, rmsg, msg, () => actor.ProcessAsk(rmsg));
                break;

            case Message.TagSpec.UserReply:
                var urmsg = (ActorResponse)msg;
                ActorContext.WithContext(new ActorItem(actor, inbox, actor.Flags), parent, urmsg.ReplyFrom, null, msg, () => actor.ProcessResponse(urmsg));
                break;

            case Message.TagSpec.User:
                var umsg = (UserMessage)msg;
                ActorContext.WithContext(new ActorItem(actor, inbox, actor.Flags), parent, umsg.Sender, null, msg, () => actor.ProcessMessage(umsg.Content));
                break;

            case Message.TagSpec.ShutdownProcess:
                kill(actor.Id);
                break;
            }
        }
Ejemplo n.º 13
0
 public static object Invoke12(ProcessId pid, string method, Type rettyp, object arg1, object arg2, object arg3, object arg4, object arg5, object arg6, object arg7, object arg8, object arg9, object arg10, object arg11, object arg12)
 {
     return(ActorContext.Ask(pid, new ProxyMsg
     {
         Method = method,
         Args = new string[] {
             JsonConvert.SerializeObject(arg1),
             JsonConvert.SerializeObject(arg2),
             JsonConvert.SerializeObject(arg3),
             JsonConvert.SerializeObject(arg4),
             JsonConvert.SerializeObject(arg5),
             JsonConvert.SerializeObject(arg6),
             JsonConvert.SerializeObject(arg7),
             JsonConvert.SerializeObject(arg8),
             JsonConvert.SerializeObject(arg9),
             JsonConvert.SerializeObject(arg10),
             JsonConvert.SerializeObject(arg11),
             JsonConvert.SerializeObject(arg12)
         },
         ArgTypes = new string[] {
             arg1.GetType().GetTypeInfo().FullName,
             arg2.GetType().GetTypeInfo().FullName,
             arg3.GetType().GetTypeInfo().FullName,
             arg4.GetType().GetTypeInfo().FullName,
             arg5.GetType().GetTypeInfo().FullName,
             arg6.GetType().GetTypeInfo().FullName,
             arg7.GetType().GetTypeInfo().FullName,
             arg8.GetType().GetTypeInfo().FullName,
             arg9.GetType().GetTypeInfo().FullName,
             arg10.GetType().GetTypeInfo().FullName,
             arg11.GetType().GetTypeInfo().FullName,
             arg12.GetType().GetTypeInfo().FullName
         },
         ReturnType = rettyp.GetTypeInfo().FullName
     }));
 }
Ejemplo n.º 14
0
        public IEnumerable <T> AskMany <T>(IEnumerable <ProcessId> pids, object message, int take)
        {
            take = Math.Min(take, pids.Count());

            var handle = new CountdownEvent(take);

            var responses = new List <AskActorRes>();

            foreach (var pid in pids)
            {
                var req = new AskActorReq(
                    message,
                    res =>
                {
                    responses.Add(res);
                    handle.Signal();
                }, pid.SetSystem(SystemName), Self);
                tell(AskId, req);
            }

            handle.Wait(ActorContext.System(pids.Head()).Settings.Timeout);

            return(responses.Where(r => !r.IsFaulted).Map(r => (T)r.Response));
        }
        public static Option <UserControlMessage> PreProcessMessage <T>(ProcessId sender, ProcessId self, object message)
        {
            if (message == null)
            {
                var emsg = $"Message is null for tell (expected {typeof(T)})";
                tell(ActorContext.DeadLetters, DeadLetter.create(sender, self, emsg, message));
                return(None);
            }

            if (message is ActorRequest)
            {
                var req = (ActorRequest)message;
                if (!(req.Message is T) && !(req.Message is Message))
                {
                    var emsg = $"Invalid message type for ask (expected {typeof(T)})";
                    tell(ActorContext.DeadLetters, DeadLetter.create(sender, self, emsg, message));

                    ActorContext.Tell(
                        sender,
                        new ActorResponse(new Exception($"Invalid message type for ask (expected {typeof(T)})"),
                                          typeof(Exception).AssemblyQualifiedName,
                                          sender,
                                          self,
                                          req.RequestId,
                                          true
                                          ),
                        self
                        );

                    return(None);
                }
                return(Optional((UserControlMessage)message));
            }

            return(new UserMessage(message, sender, sender));
        }
Ejemplo n.º 16
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.º 17
0
        /// <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);
            }
        }
Ejemplo n.º 18
0
 /// <summary>
 /// Get the child processes of the process provided
 /// </summary>
 public static IEnumerable <ProcessId> children(ProcessId pid) =>
 ActorContext.GetProcess(pid).Children;
 private IEnumerable <IActorDispatch> GetWorkers() =>
 group.Map(pid => ActorContext.System(pid).GetDispatcher(pid));
Ejemplo n.º 20
0
 /// <summary>
 /// Send a message to a process
 /// </summary>
 /// <param name="pid">Process ID to send to</param>
 /// <param name="message">Message to send</param>
 /// <param name="sender">Optional sender override.  The sender is handled automatically if you do not provide one.</param>
 internal static Unit tellSystem <T>(ProcessId pid, T message, ProcessId sender = default(ProcessId)) =>
 ActorContext.System(pid).TellSystem(pid, message as SystemMessage);
Ejemplo n.º 21
0
 /// <summary>
 /// Send a message to a process
 /// </summary>
 /// <param name="pid">Process ID to send to</param>
 /// <param name="message">Message to send</param>
 /// <param name="sender">Optional sender override.  The sender is handled automatically if you do not provide one.</param>
 public static Unit tell <T>(ProcessId pid, T message, ProcessId sender = default(ProcessId)) =>
 message is UserControlMessage
         ? ActorContext.System(pid).TellUserControl(pid, message as UserControlMessage)
         : ActorContext.System(pid).Tell(pid, message, sender);
Ejemplo n.º 22
0
 /// <summary>
 /// Create N child processes.
 /// The name provided will be used as a basis to generate the child names.  Each child will
 /// be named "name-index" where index starts at zero.
 /// If this is called from within a process' message loop
 /// then the new processes will be a children of the current process.  If it is called from
 /// outside of a process, then they will be made a child of the root 'user' process.
 /// </summary>
 /// <typeparam name="T">Type of messages that the child-process can accept</typeparam>
 /// <param name="count">Number of processes to spawn</param>
 /// <param name="setup">Startup and restart function</param>
 /// <param name="name">Name of the child-process</param>
 /// <param name="messageHandler">Function that is the process</param>
 /// <param name="flags">Process flags</param>
 /// <returns>ProcessId IEnumerable</returns>
 public static IEnumerable <ProcessId> spawnN <S, T>(int count, ProcessName name, Func <S> setup, Func <S, T, S> messageHandler, ProcessFlags flags = ProcessFlags.Default) =>
 List.map(Range(0, count), n => ActorContext.ActorCreate(ActorContext.SelfProcess, name + "-" + n, messageHandler, setup, flags)).ToList();
Ejemplo n.º 23
0
 /// <summary>
 /// Create a new process by name.
 /// If this is called from within a process' message loop
 /// then the new process will be a child of the current process.  If it is called from
 /// outside of a process, then it will be made a child of the root 'user' process.
 /// </summary>
 /// <typeparam name="T">Type of messages that the child-process can accept</typeparam>
 /// <param name="name">Name of the child-process</param>
 /// <param name="setup">Startup and restart function</param>
 /// <param name="messageHandler">Function that is the process</param>
 /// <param name="flags">Process flags</param>
 /// <returns>A ProcessId that identifies the child</returns>
 public static ProcessId spawn <S, T>(ProcessName name, Func <S> setup, Func <S, T, S> messageHandler, ProcessFlags flags = ProcessFlags.Default) =>
 ActorContext.ActorCreate(ActorContext.SelfProcess, name, messageHandler, setup, flags);
Ejemplo n.º 24
0
 /// <summary>
 /// Spawns a new process with N worker processes, each message is sent to one worker
 /// process in a round robin fashion.
 /// </summary>
 /// <typeparam name="T">Message type</typeparam>
 /// <param name="name">Delegator process name</param>
 /// <param name="spec">Map of IDs and State for generating child workers</param>
 /// <param name="messageHandler">Worker message handler</param>
 /// <param name="flags">Process flags</param>
 /// <returns>Process ID of the delegator process</returns>
 public static ProcessId spawnRoundRobin <S, T>(ProcessName name, Map <int, Func <S> > spec, Func <S, T, S> messageHandler, ProcessFlags flags = ProcessFlags.Default) =>
 spawn <Unit, T>(name, () => ignore(Map.map(spec, (id, state) => ActorContext.ActorCreate(ActorContext.SelfProcess, "worker-" + id, messageHandler, state, flags))), (_, msg) => HandleNoChild(() => fwdNextChild(msg)), flags);
Ejemplo n.º 25
0
 /// <summary>
 /// Create N child processes.
 /// The name provided will be used as a basis to generate the child names.  Each child will
 /// be named "name-index" where index starts at zero.
 /// If this is called from within a process' message loop
 /// then the new processes will be a children of the current process.  If it is called from
 /// outside of a process, then they will be made a child of the root 'user' process.
 /// </summary>
 /// <typeparam name="S">State type</typeparam>
 /// <typeparam name="T">Type of messages that the child-process can accept</typeparam>
 /// <param name="spec">Map of IDs and State for generating child workers</param>
 /// <param name="name">Name of the child-process</param>
 /// <param name="messageHandler">Function that is the process</param>
 /// <param name="flags">Process flags</param>
 /// <returns>ProcessId IEnumerable</returns>
 public static IEnumerable <ProcessId> spawnN <S, T>(ProcessName name, Map <int, Func <S> > spec, Func <S, T, S> messageHandler, ProcessFlags flags = ProcessFlags.Default) =>
 Map.map(spec, (id, state) => ActorContext.ActorCreate(ActorContext.SelfProcess, name + "-" + id, messageHandler, state, flags)).Values.ToList();
        public static InboxDirective SystemMessageInbox <S, T>(Actor <S, T> actor, IActorInbox inbox, SystemMessage msg, ActorItem parent)
        {
            return(ActorContext.WithContext(new ActorItem(actor, inbox, actor.Flags), parent, ProcessId.NoSender, null, msg, msg.SessionId, () =>
            {
                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;
                    actor.UnlinkChild(ulc.Child);
                    break;

                case Message.TagSpec.ChildFaulted:
                    var cf = msg as SystemChildFaultedMessage;
                    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();
                    break;

                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;
            }));
        }
Ejemplo n.º 27
0
 /// <summary>
 /// Un-register the process associated with the name
 /// </summary>
 /// <param name="name">Name of the process to un-register</param>
 public static Unit unreg(ProcessName name) =>
 ActorContext.UnRegister(name);
Ejemplo n.º 28
0
 /// <summary>
 /// Register the name with the process
 /// </summary>
 /// <param name="name">Name to register under</param>
 /// <param name="process">Process to be registered</param>
 public static ProcessId reg(ProcessName name, ProcessId process) =>
 ActorContext.Register(name, process);
Ejemplo n.º 29
0
 /// <summary>
 /// Register self as a named process
 /// </summary>
 /// <param name="name">Name to register under</param>
 public static ProcessId reg(ProcessName name) =>
 ActorContext.Register(name, Self);
Ejemplo n.º 30
0
 /// <summary>
 /// Shutdown all processes and restart
 /// </summary>
 public static Unit shutdownAll() =>
 ActorContext.Restart();