/// <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)); }
/// <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)); }
/// <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); }
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)); }
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); }