Esempio n. 1
0
        /// <summary>
        /// Spawns a new process with that routes each message to the Workers
        /// randomly.
        /// </summary>
        /// <typeparam name="S">State type</typeparam>
        /// <typeparam name="T">Message type</typeparam>
        /// <param name="Name">Delegator process name</param>
        /// <param name="Count">Number of worker processes</param>
        /// <param name="Inbox">Worker message handler</param>
        /// <param name="Flags">Process flags</param>
        /// <param name="Strategy">Failure supervision strategy</param>
        /// <returns>Process ID of the delegator process</returns>
        public static ProcessId random <T>(
            ProcessName Name,
            IEnumerable <ProcessId> Workers,
            RouterOption Options = RouterOption.Default,
            ProcessFlags Flags   = ProcessFlags.Default,
            int MaxMailboxSize   = ProcessSetting.DefaultMailboxSize
            )
        {
            if (Workers == null)
            {
                throw new ArgumentNullException(nameof(Workers));
            }
            var workers = Workers.ToArray();

            if (workers.Length < 1)
            {
                throw new ArgumentException($"{nameof(Workers)} should have a length of at least 1");
            }
            var router = spawn <T>(
                Name,
                msg => fwd(workers[Prelude.random(workers.Length)]),
                Flags,
                DefaultStrategy,
                MaxMailboxSize,
                Terminated: pid => workers = workers.Where(x => x != pid).ToArray()
                );

            return(WatchWorkers(router, workers, Options));
        }
Esempio n. 2
0
        /// <summary>
        /// Spawns a new process with that routes each message to the Workers
        /// in a round robin fashion.
        /// </summary>
        /// <typeparam name="S">State type</typeparam>
        /// <typeparam name="T">Message type</typeparam>
        /// <param name="Name">Delegator process name</param>
        /// <param name="Flags">Process flags</param>
        /// <returns>Process ID of the delegator process</returns>
        public static ProcessId broadcast <T>(
            ProcessName Name,
            IEnumerable <ProcessId> Workers,
            RouterOption Options = RouterOption.Default,
            ProcessFlags Flags   = ProcessFlags.Default,
            int MaxMailboxSize   = ProcessSetting.DefaultMailboxSize
            )
        {
            if (Workers == null)
            {
                throw new ArgumentNullException(nameof(Workers));
            }
            var workers = toSet(Workers);

            if (workers.Count < 1)
            {
                throw new ArgumentException($"{nameof(Workers)} should have a length of at least 1");
            }

            var router = spawn <T>(
                Name,
                msg => workers.Iter(pid => fwd(pid)),
                Flags,
                DefaultStrategy,
                MaxMailboxSize,
                Terminated: pid => workers = workers.Remove(pid)
                );

            return(WatchWorkers(router, workers, Options));
        }
        /// <summary>
        /// Spawns a new process with that routes each message to the Workers
        /// in a round robin fashion.
        /// </summary>
        /// <typeparam name="S">State type</typeparam>
        /// <typeparam name="T">Message type</typeparam>
        /// <param name="Name">Delegator process name</param>
        /// <param name="Count">Number of worker processes</param>
        /// <param name="Inbox">Worker message handler</param>
        /// <param name="Flags">Process flags</param>
        /// <param name="Strategy">Failure supervision strategy</param>
        /// <returns>Process ID of the delegator process</returns>
        public static ProcessId roundRobin <T>(
            ProcessName Name,
            IEnumerable <ProcessId> Workers,
            RouterOption Options = RouterOption.Default,
            ProcessFlags Flags   = ProcessFlags.Default,
            int MaxMailboxSize   = ProcessSetting.DefaultMailboxSize
            )
        {
            if (Workers == null)
            {
                throw new ArgumentNullException(nameof(Workers));
            }
            var workers = Workers.ToArray();

            if (workers.Length < 1)
            {
                throw new ArgumentException($"{nameof(Workers)} should have a length of at least 1");
            }
            var router = spawn <int, T>(
                Name,
                () => 0,
                (index, msg) =>
            {
                index = index % workers.Length;
                fwd(workers[index]);
                return(index + 1);
            },
                Flags,
                DefaultStrategy,
                MaxMailboxSize,
                Terminated: (index, pid) => { workers = workers.Where(x => x != pid).ToArray(); return(index); }
                );

            return(WatchWorkers(router, workers, Options));
        }
Esempio n. 4
0
        /// <summary>
        /// Spawns a new process with that routes each message by calling GetHashCode on the
        /// message and modding by the number of workers and using that as the worker index
        /// to route to.
        /// </summary>
        /// <typeparam name="S">State type</typeparam>
        /// <typeparam name="T">Message type</typeparam>
        /// <param name="Name">Delegator process name</param>
        /// <param name="Count">Number of worker processes</param>
        /// <param name="Inbox">Worker message handler</param>
        /// <param name="Flags">Process flags</param>
        /// <param name="Strategy">Failure supervision strategy</param>
        /// <returns>Process ID of the delegator process</returns>
        public static ProcessId hash <T>(
            ProcessName Name,
            IEnumerable <ProcessId> Workers,
            Func <int, T, int> HashFunc = null,
            RouterOption Options        = RouterOption.Default,
            ProcessFlags Flags          = ProcessFlags.Default,
            int MaxMailboxSize          = ProcessSetting.DefaultMailboxSize
            )
        {
            if (Workers == null)
            {
                throw new ArgumentNullException(nameof(Workers));
            }
            var workers = Workers.ToArray();

            if (workers.Length < 1)
            {
                throw new ArgumentException($"{nameof(Workers)} should have a length of at least 1");
            }
            HashFunc = HashFunc ?? DefaultHashFunction <T>();
            var router = spawn <T>(
                Name,
                msg =>
            {
                fwd(workers[HashFunc(Children.Count, msg)]);
            },
                Flags,
                DefaultStrategy,
                MaxMailboxSize,
                Terminated: pid => { workers = workers.Where(x => x != pid).ToArray(); }
                );

            return(WatchWorkers(router, workers, Options));
        }
        public ForwardService(IRpcClient <AmpMessage> rpcCleint, IOptionsSnapshot <RouterOption> optionsAccessor)
        {
            Assert.IsNull(optionsAccessor.Value, "RouterOption not found");

            _option = optionsAccessor.Value;

            _client = new AmpCommonClient(rpcCleint);
        }
Esempio n. 6
0
 internal static ProcessId WatchWorkers(ProcessId router, IEnumerable<ProcessId> workers, RouterOption option)
 {
     if ((option & RouterOption.RemoveLocalWorkerWhenTerminated) == RouterOption.RemoveLocalWorkerWhenTerminated)
     {
         workers.Where(w => ActorContext.IsLocal(w)).Iter(w => watch(router, w));
     }
     if ((option & RouterOption.RemoveRemoteWorkerWhenTerminated) == RouterOption.RemoveRemoteWorkerWhenTerminated)
     {
         workers.Where(w => !ActorContext.IsLocal(w)).Iter(w => watch(router, w));
     }
     return router;
 }
        /// <summary>
        /// Spawns a new process with that routes each message is mapped and
        /// sent to the least busy worker
        /// </summary>
        /// <typeparam name="S">State type</typeparam>
        /// <typeparam name="T">Message type</typeparam>
        /// <param name="Name">Delegator process name</param>
        /// <param name="Count">Number of worker processes</param>
        /// <param name="Inbox">Worker message handler</param>
        /// <param name="Flags">Process flags</param>
        /// <param name="Strategy">Failure supervision strategy</param>
        /// <returns>Process ID of the delegator process</returns>
        public static ProcessId leastBusyMap <T, U>(
            ProcessName Name,
            IEnumerable <ProcessId> Workers,
            Func <T, U> Map,
            RouterOption Options = RouterOption.Default,
            ProcessFlags Flags   = ProcessFlags.Default,
            int MaxMailboxSize   = ProcessSetting.DefaultMailboxSize
            )
        {
            if (Workers == null)
            {
                throw new ArgumentNullException(nameof(Workers));
            }
            var workers = Set.createRange(Workers);

            if (workers.Count < 1)
            {
                throw new ArgumentException($"{nameof(Workers)} should have a length of at least 1");
            }
            var router = spawn <T>(
                Name,
                msg =>
            {
                var umsg  = Map(msg);
                var disps = (from child in workers.Map(c => Tuple(c, ActorContext.GetDispatcher(c)))
                             let count = child.Item2.GetInboxCount()
                                         where count >= 0
                                         orderby count
                                         select child)
                            .ToList();

                if (disps.Count == 0)
                {
                    throw new NoRouterWorkersException();
                }
                else
                {
                    fwd(disps.First().Item1, msg);
                }
            },
                Flags,
                DefaultStrategy,
                MaxMailboxSize,
                Terminated: pid => workers = workers.Remove(pid)
                );

            return(WatchWorkers(router, workers, Options));
        }
Esempio n. 8
0
 internal static ProcessId WatchWorkers(ProcessId router, IEnumerable <ProcessId> workers, RouterOption option)
 {
     if ((option & RouterOption.RemoveLocalWorkerWhenTerminated) == RouterOption.RemoveLocalWorkerWhenTerminated)
     {
         workers.Where(w => ActorContext.System(w).IsLocal(w)).Iter(w => watch(router, w));
     }
     if ((option & RouterOption.RemoveRemoteWorkerWhenTerminated) == RouterOption.RemoveRemoteWorkerWhenTerminated)
     {
         workers.Where(w => !ActorContext.System(w).IsLocal(w)).Iter(w => watch(router, w));
     }
     return(router);
 }