コード例 #1
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="Inbox">Function that is the process</param>
        /// <param name="Flags">Process flags</param>
        /// <param name="Strategy">Failure supervision strategy</param>
        /// <param name="Terminated">Message function to call when a Process [that this Process
        /// watches] terminates</param>
        /// <returns>A ProcessId that identifies the child</returns>
        public static ProcessId spawn <S, T>(
            ProcessName Name,
            Func <S> Setup,
            Func <S, T, S> Inbox,
            ProcessFlags Flags = ProcessFlags.Default,
            State <StrategyContext, Unit> Strategy = null,
            int MaxMailboxSize = ProcessSetting.DefaultMailboxSize,
            Func <S, ProcessId, S> Terminated = null,
            SystemName System = default(SystemName)
            )
        {
            if (System.IsValid && ActorContext.Request != null)
            {
                throw new ProcessException("When spawning you can only specify a System from outside of a Process", ActorContext.Self[Name].Path, "");
            }

            var sys = System.IsValid
                ? ActorContext.System(System)
                : ActorContext.DefaultSystem;

            var parent = System.IsValid
                ? sys.UserContext.Self
                : ActorContext.SelfProcess;

            return(sys.ActorCreate(parent, Name, Inbox, Setup, Terminated, Strategy, Flags, MaxMailboxSize, false));
        }
コード例 #2
0
        public ActorSystemBootstrap(IActorSystem system, Option <ICluster> cluster, ProcessId rootId, IActor rootProcess, IActorInbox rootInbox, ProcessName rootProcessName, ActorSystemConfig config, ProcessSystemConfig settings, SessionSync sync)
        {
            System = system;
            Sync   = sync;

            var parent = new ActorItem(new NullProcess(system.Name), new NullInbox(), ProcessFlags.Default);

            rootProcess = new Actor <ActorSystemBootstrap, Unit>(
                cluster,
                parent,
                rootProcessName,
                SystemInbox,
                _ => this,
                null,
                Process.DefaultStrategy,
                ProcessFlags.Default,
                settings,
                system
                );

            root            = new ActorItem(rootProcess, rootInbox, rootProcess.Flags);
            Config          = config;
            Settings        = settings;
            Cluster         = cluster;
            RootProcess     = rootProcess;
            RootInbox       = rootInbox;
            RootProcessName = rootProcessName;
        }
コード例 #3
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 = 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 => workers.Iter(pid => fwd(pid)),
                Flags,
                DefaultStrategy,
                MaxMailboxSize,
                Terminated: pid => workers = workers.Remove(pid)
                );

            return(WatchWorkers(router, workers, Options));
        }
コード例 #4
0
ファイル: ActorContext.cs プロジェクト: dhalsim/language-ext
        public static Unit DeregisterByName(ProcessName name)
        {
            Cluster.Match(
                Some: c =>
            {
                RemoveLocalRegisteredByName(name);
                var regpath = (ProcessId.Top["__registered"][name]).Path;

                // TODO - Make this transactional
                // {
                var pids = c.GetSet <string>(regpath);
                pids.Iter(pid =>
                {
                    c.SetRemove(pid + "-registered", name.Value);
                });
                c.Delete(regpath);
                // }
            },
                None: () =>
            {
                RemoveLocalRegisteredByName(name);
            }
                );
            return(unit);
        }
コード例 #5
0
ファイル: ActorContext.cs プロジェクト: dhalsim/language-ext
        public static ProcessId Register(ProcessName name, ProcessId pid)
        {
            if (!pid.IsValid)
            {
                throw new InvalidProcessIdException();
            }

            Cluster.Match(
                Some: c =>
            {
                if (IsLocal(pid) && GetDispatcher(pid).IsLocal)
                {
                    AddLocalRegistered(name, pid);
                }
                else
                {
                    // TODO - Make this transactional
                    // {
                    c.SetAddOrUpdate(ProcessId.Top["__registered"][name].Path, pid.Path);
                    c.SetAddOrUpdate(pid.Path + "-registered", name.Value);
                    // }
                }
            },
                None: () => AddLocalRegistered(name, pid)
                );
            return(Disp["reg"][name]);
        }
コード例 #6
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));
        }
コード例 #7
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));
        }
コード例 #8
0
        internal Actor(
            Option <ICluster> cluster,
            ActorItem parent,
            ProcessName name,
            Func <S, T, S> actor,
            Func <IActor, S> setup,
            Func <S, ProcessId, S> term,
            State <StrategyContext, Unit> strategy,
            ProcessFlags flags
            )
        {
            if (setup == null)
            {
                throw new ArgumentNullException(nameof(setup));
            }
            if (actor == null)
            {
                throw new ArgumentNullException(nameof(actor));
            }

            this.cluster = cluster;
            this.flags   = flags;
            actorFn      = actor;
            termFn       = term;
            setupFn      = setup;
            Parent       = parent;
            Name         = name;
            Strategy     = strategy ?? Process.DefaultStrategy;
            Id           = parent.Actor.Id[name];
            SetupRemoteSubscriptions(cluster, flags);
        }
コード例 #9
0
 ProcessId(ProcessName[] parts, SystemName system, ProcessName name, string path)
 {
     this.parts  = parts;
     this.name   = name;
     this.Path   = path;
     this.System = system;
 }
コード例 #10
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="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));
        }
コード例 #11
0
        /// <summary>
        /// Initialise without a config file or text
        /// </summary>
        /// <param name="systemName">Name of the system - this is most useful</param>
        /// <param name="roleName"></param>
        /// <param name="nodeName"></param>
        /// <param name="providerName"></param>
        /// <param name="connectionString"></param>
        /// <param name="catalogueName"></param>
        /// <returns></returns>
        public static Unit initialise(
            SystemName systemName,
            ProcessName roleName,
            ProcessName nodeName,
            string connectionString,
            string catalogueName,
            string providerName = "redis"
            )
        {
            lock (sync)
            {
                var types = new Types();

                StartFromConfig(new ProcessSystemConfig(
                                    systemName,
                                    nodeName.Value,
                                    Map.empty <string, ValueToken>(),
                                    Map.empty <ProcessId, ProcessToken>(),
                                    Map.empty <string, State <StrategyContext, Unit> >(),
                                    new ClusterToken(
                                        None,
                                        List.create(
                                            new NamedValueToken("node-name", new ValueToken(types.String, nodeName.Value), None),
                                            new NamedValueToken("role", new ValueToken(types.String, roleName.Value), None),
                                            new NamedValueToken("env", new ValueToken(types.String, systemName.Value), None),
                                            new NamedValueToken("connection", new ValueToken(types.String, connectionString), None),
                                            new NamedValueToken("database", new ValueToken(types.String, catalogueName), None),
                                            new NamedValueToken("provider", new ValueToken(types.String, providerName), None))),
                                    types
                                    ));
            }
            return(unit);
        }
コード例 #12
0
        public ProcessId(string path)
        {
            var res = TryParse(path).IfLeft(ex => raise <ProcessId>(ex));

            parts = res.parts;
            name  = res.name;
            Path  = res.Path;
        }
コード例 #13
0
ファイル: ActorContext.cs プロジェクト: dhalsim/language-ext
 public static Unit RemoveDispatcher(ProcessName name)
 {
     lock (sync)
     {
         dispatchers = dispatchers.Remove(name);
     }
     return(unit);
 }
コード例 #14
0
ファイル: Dispatch.cs プロジェクト: OlduwanSteve/language-ext
 /// <summary>
 /// Registers a dispatcher for a role
 /// Dispatchers take in a 'leaf' ProcessId (i.e. /user/my-process) and return an enumerable
 /// of real ProcessIds that the Process system will use to deliver all of the standard functions
 /// like tell, ask, subscribe, etc.
 /// </summary>
 /// <param name="name">Name of the dispatcher</param>
 /// <param name="selector">Function that will be invoked every time a dispatcher based ProcessId
 /// is used.</param>
 /// <returns>A root dispatcher ProcessId.  Use this to create new ProcessIds that will
 /// be passed to the selector function whenever the dispatcher based ProcessId is used</returns>
 public static ProcessId register(ProcessName name, Func<ProcessId, IEnumerable<ProcessId>> selector)
 {
     lock (sync)
     {
         dispatchers = dispatchers.AddOrUpdate(name, selector);
     }
     return ProcessId.Top["disp"][name];
 }
コード例 #15
0
ファイル: ActorContext.cs プロジェクト: dhalsim/language-ext
 public static ProcessId AddDispatcher(ProcessName name, Func <ProcessId, IEnumerable <ProcessId> > selector)
 {
     lock (sync)
     {
         dispatchers = dispatchers.AddOrUpdate(name, selector);
     }
     return(ProcessId.Top["disp"][name]);
 }
コード例 #16
0
ファイル: Dispatch.cs プロジェクト: OlduwanSteve/language-ext
 /// <summary>
 /// Removes the dispatcher registration for the named dispatcher
 /// </summary>
 /// <param name="name">Name of the dispatcher to remove</param>
 public static Unit deregister(ProcessName name)
 {
     lock (sync)
     {
         dispatchers = dispatchers.Remove(name);
     }
     return unit;
 }
コード例 #17
0
        /// <summary>
        /// Spawns a new process with Count worker processes, 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 <S, T, U>(
            ProcessName Name,
            int Count,
            Func <S> Setup,
            Func <S, U, S> Inbox,
            Func <T, U> Map,
            ProcessFlags Flags = ProcessFlags.Default,
            State <StrategyContext, Unit> Strategy = null,
            int MaxMailboxSize = ProcessSetting.DefaultMailboxSize,
            string WorkerName  = "worker"
            )
        {
            if (Inbox == null)
            {
                throw new ArgumentNullException(nameof(Inbox));
            }
            if (Setup == null)
            {
                throw new ArgumentNullException(nameof(Setup));
            }
            if (Count < 1)
            {
                throw new ArgumentException($"{nameof(Count)} should be greater than 0");
            }

            return(spawn <Unit, T>(
                       Name,
                       () =>
            {
                spawnMany(Count, WorkerName, Setup, Inbox, Flags);
                return unit;
            },
                       (_, msg) =>
            {
                var umsg = Map(msg);

                var disps = (from child in Children.Map(c => Tuple(c, ActorContext.GetDispatcher(c))).Values
                             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, umsg);
                }
                return unit;
            },
                       Flags,
                       Strategy,
                       MaxMailboxSize
                       ));
        }
コード例 #18
0
        /// <summary>
        /// Spawns a new process with N worker processes, each message is mapped
        /// from T to IEnumerable U before each resulting U is passed to the worker
        /// processes randomly.
        /// </summary>
        /// <typeparam name="T">Message type</typeparam>
        /// <typeparam name="U">Mapped message type</typeparam>
        /// <param name="Name">Delegator process name</param>
        /// <param name="Count">Number of worker processes</param>
        /// <param name="map">Maps the message from T to IEnumerable U before each one is passed to the workers</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 randomMapMany <S, T, U>(
            ProcessName Name,
            int Count,
            Func <S> Setup,
            Func <S, U, S> Inbox,
            Func <T, IEnumerable <U> > MapMany,
            ProcessFlags Flags = ProcessFlags.Default,
            State <StrategyContext, Unit> Strategy = null,
            int MaxMailboxSize = ProcessSetting.DefaultMailboxSize,
            string WorkerName  = "worker"
            )
        {
            if (Inbox == null)
            {
                throw new ArgumentNullException(nameof(Inbox));
            }
            if (WorkerName == null)
            {
                throw new ArgumentNullException(nameof(WorkerName));
            }
            if (Count < 1)
            {
                throw new ArgumentException($"{nameof(Count)} should be greater than 0");
            }

            return(spawn <Unit, T>(
                       Name,
                       () =>
            {
                spawnMany(Count, WorkerName, Setup, Inbox, Flags);
                return unit;
            },
                       (_, msg) =>
            {
                var us = MapMany(msg);

                foreach (var u in us)
                {
                    var index = Prelude.random(Children.Count);
                    var child = Children.Skip(index).Take(1).ToArray();

                    if (child.Length == 0)
                    {
                        throw new NoRouterWorkersException();
                    }
                    else
                    {
                        fwd(child[0].Value, u);
                    }
                }
                return unit;
            },
                       Flags,
                       Strategy,
                       MaxMailboxSize
                       ));
        }
コード例 #19
0
 /// <summary>
 /// Create a new process by name (accepts Unit as a return value instead of void).
 /// 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="Inbox">Function that is the process</param>
 /// <param name="Flags">Process flags</param>
 /// <param name="Strategy">Failure supervision strategy</param>
 /// <param name="Terminated">Message function to call when a Process [that this Process
 /// watches] terminates</param>
 /// <returns>A ProcessId that identifies the child</returns>
 public static ProcessId spawnUnit <T>(
     ProcessName Name,
     Func <T, Unit> Inbox,
     ProcessFlags Flags = ProcessFlags.Default,
     State <StrategyContext, Unit> Strategy = null,
     int MaxMailboxSize = ProcessSetting.DefaultMailboxSize,
     Func <ProcessId, Unit> Terminated = null
     ) =>
 spawn <Unit, T>(Name, () => unit, (state, msg) => { Inbox(msg); return(state); }, Flags, Strategy, MaxMailboxSize, (state, pid) => { Terminated(pid); return(state); });
コード例 #20
0
        public static Either <Exception, ProcessId> TryParse(string path)
        {
            if (path == null || path.Length == 0)
            {
                return(new InvalidProcessIdException());
            }
            if (path[0] == '@')
            {
                return(ParseRegisteredProcess(path.Substring(1)));
            }

            if (path[0] != Sep)
            {
                return(new InvalidProcessIdException());
            }

            ProcessName[] parts = null;
            ProcessName   name;
            string        finalPath = null;

            if (path.Length == 1)
            {
                parts = new ProcessName[0];
            }
            else
            {
                try
                {
                    parts = SplitOnSep(path).ToArray();
                }
                catch (InvalidProcessNameException)
                {
                    return(new InvalidProcessIdException());
                }
            }

            finalPath = parts == null
                ? ""
                : parts.Length == 0
                    ? Sep.ToString()
                    : Sep + String.Join(Sep.ToString(), parts);

            if (path != Sep.ToString())
            {
                name = parts == null
                    ? ""
                    : parts.Length == 0
                        ? Sep.ToString()
                        : parts.Last();
            }
            else
            {
                name = "$";
            }

            return(new ProcessId(parts, name, finalPath));
        }
コード例 #21
0
 public static ProcessId Register(ProcessName name, ProcessId process) =>
 map(registered as IProcessInternal,
     self => match(self.GetChildProcess(name),
                   Some: _ => failwith <IProcess>("Process '" + name + "' already registered"),
                   None: () => self.AddChildProcess(new ActorProxy(
                                                        registered.Id,
                                                        name,
                                                        ActorProxyTemplate.Registered,
                                                        () => new ActorProxyConfig(process))))).Id;
コード例 #22
0
 /// <summary>
 /// Spawn by type
 /// </summary>
 /// <typeparam name="TProcess">Process type</typeparam>
 /// <typeparam name="TMsg">Message type</typeparam>
 /// <param name="name">Name of process to spawn</param>
 /// <returns>ProcessId</returns>
 public static ProcessId spawn <TProcess, TMsg>(ProcessName name)
     where TProcess : IProcess <TMsg>, new()
 {
     return(spawn <IProcess <TMsg>, TMsg>(name, () => new TProcess(),
                                          (process, msg) => {
         process.OnMessage(msg);
         return process;
     }));
 }
コード例 #23
0
 public static ProcessId spawnRoundRobin <T>(
     ProcessName Name,
     int Count,
     Action <T> Inbox,
     ProcessFlags Flags = ProcessFlags.Default,
     State <StrategyContext, Unit> Strategy = null,
     int MaxMailboxSize = ProcessSetting.DefaultMailboxSize
     ) =>
 Router.roundRobin(Name, Count, Inbox, Flags, Strategy, MaxMailboxSize);
コード例 #24
0
 /// <summary>
 /// Spawns a new process with Count worker processes, each message is
 /// 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 leastBusy <T>(
     ProcessName Name,
     int Count,
     Action <T> Inbox,
     ProcessFlags Flags = ProcessFlags.Default,
     State <StrategyContext, Unit> Strategy = null,
     int MaxMailboxSize = ProcessSetting.DefaultMailboxSize,
     string WorkerName  = "worker"
     ) =>
 leastBusy <Unit, T>(Name, Count, () => unit, (_, msg) => { Inbox(msg); return(unit); }, Flags, Strategy, MaxMailboxSize, WorkerName);
コード例 #25
0
ファイル: Cluster.cs プロジェクト: pahomovda/language-ext
 /// <param name="nodeName">Unique name for this process.  It becomes the name of the root
 /// node and allows other services on the cluster to discover you and communicate with you.
 /// </param>
 /// <param name="connectionString">Provider defined connection string</param>
 /// <param name="catalogueName">>Provider defined catalogue name</param>
 public static ClusterConfig config(
     ProcessName nodeName,
     string connectionString,
     string catalogueName
     ) =>
 new ClusterConfig(
     nodeName,
     connectionString,
     catalogueName
     );
コード例 #26
0
 public ClusterConfig(
     ProcessName nodeName,
     string connectionString,
     string catalogueName
 )
 {
     NodeName = nodeName;
     ConnectionString = connectionString;
     CatalogueName = catalogueName;
 }
コード例 #27
0
ファイル: Cluster.cs プロジェクト: JamesTryand/language-ext
 /// <param name="nodeName">Unique name for this process.  It becomes the name of the root 
 /// node and allows other services on the cluster to discover you and communicate with you.
 /// </param>
 /// <param name="connectionString">Provider defined connection string</param>
 /// <param name="catalogueName">>Provider defined catalogue name</param>
 public static ClusterConfig config(
     ProcessName nodeName,
     string connectionString,
     string catalogueName
 ) => 
     new ClusterConfig(
         nodeName, 
         connectionString, 
         catalogueName
     );
コード例 #28
0
 public ClusterConfig(
     ProcessName nodeName,
     string connectionString,
     string catalogueName
     )
 {
     NodeName         = nodeName;
     ConnectionString = connectionString;
     CatalogueName    = catalogueName;
 }
コード例 #29
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="Inbox">Function that is the process</param>
 /// <param name="Flags">Process flags</param>
 /// <param name="Strategy">Failure supervision strategy</param>
 /// <param name="Terminated">Message function to call when a Process [that this Process
 /// watches] terminates</param>
 /// <returns>A ProcessId that identifies the child</returns>
 public static ProcessId spawn <S, T>(
     ProcessName Name,
     Func <S> Setup,
     Func <S, T, S> Inbox,
     ProcessFlags Flags = ProcessFlags.Default,
     State <StrategyContext, Unit> Strategy = null,
     int MaxMailboxSize = ProcessSetting.DefaultMailboxSize,
     Func <S, ProcessId, S> Terminated = null
     ) =>
 ActorContext.ActorCreate(ActorContext.SelfProcess, Name, Inbox, Setup, Terminated, Strategy, Flags, MaxMailboxSize, false);
コード例 #30
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="Name">Name of the child-process</param>
 /// <param name="Inbox">Function that is the process</param>
 /// <param name="Flags">Process flags</param>
 /// <param name="Strategy">Failure supervision strategy</param>
 /// <param name="Terminated">Message function to call when a Process [that this Process
 /// watches] terminates</param>
 /// <returns>ProcessId IEnumerable</returns>
 public static IEnumerable <ProcessId> spawnMany <T>(
     int Count,
     ProcessName Name,
     Action <T> Inbox,
     ProcessFlags Flags = ProcessFlags.Default,
     State <StrategyContext, Unit> Strategy = null,
     int MaxMailboxSize            = ProcessSetting.DefaultMailboxSize,
     Action <ProcessId> Terminated = null
     ) =>
 List.map(Range(0, Count), n => spawn($"{Name}-{n}", Inbox, Flags, Strategy, MaxMailboxSize, Terminated)).ToList();
コード例 #31
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="Inbox">Function that is the process</param>
 /// <param name="Flags">Process flags</param>
 /// <param name="Strategy">Failure supervision strategy</param>
 /// <param name="Terminated">Message function to call when a Process [that this Process
 /// watches] terminates</param>
 /// <returns>ProcessId IEnumerable</returns>
 public static IEnumerable <ProcessId> spawnMany <S, T>(
     ProcessName Name,
     Map <int, Func <S> > Spec,
     Func <S, T, S> Inbox,
     ProcessFlags Flags = ProcessFlags.Default,
     State <StrategyContext, Unit> Strategy = null,
     int MaxMailboxSize = ProcessSetting.DefaultMailboxSize,
     Func <S, ProcessId, S> Terminated = null
     ) =>
 Map.map(Spec, (id, state) => ActorContext.ActorCreate(ActorContext.SelfProcess, $"{Name}-{id}", Inbox, state, Terminated, Strategy, Flags, MaxMailboxSize, false)).Values.ToList();
コード例 #32
0
ファイル: ActorContext.cs プロジェクト: dhalsim/language-ext
 public static ProcessId ActorCreate <S, T>(
     ActorItem parent,
     ProcessName name,
     Action <T> actorFn,
     Func <S, ProcessId, S> termFn,
     State <StrategyContext, Unit> strategy,
     ProcessFlags flags,
     int maxMailboxSize,
     bool lazy
     ) =>
 ActorCreate <S, T>(parent, name, (s, t) => { actorFn(t); return(default(S)); }, () => default(S), termFn, strategy, flags, maxMailboxSize, lazy);
コード例 #33
0
ファイル: Cluster.cs プロジェクト: JamesTryand/language-ext
 /// <summary>
 /// Connect to a cluster
 /// </summary>
 /// <param name="providerName">Provider name is a unique name for the persistence layer 
 /// type, for example: "redis"</param>
 /// <param name="nodeName">Unique name for this process.  It becomes the name of the root 
 /// node and allows other services on the cluster to discover you and communicate with you.
 /// </param>
 /// <param name="connectionString">Provider defined connection string</param>
 /// <param name="catalogueName">>Provider defined catalogue name</param>
 public static Unit connect(
     string providerName,
     ProcessName nodeName,
     string connectionString,
     string catalogueName
 )
 {
     var cluster = ClusterFactory.CreateCluster(providerName, config(nodeName,connectionString,catalogueName));
     cluster.Connect();
     return ActorContext.RegisterCluster(cluster);
 }
コード例 #34
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="Inbox">Function that is the process</param>
 /// <param name="Flags">Process flags</param>
 /// <param name="Strategy">Failure supervision strategy</param>
 /// <param name="Terminated">Message function to call when a Process [that this Process
 /// watches] terminates</param>
 /// <returns>ProcessId IEnumerable</returns>
 public static IEnumerable <ProcessId> spawnMany <S, T>(
     int Count,
     ProcessName Name,
     Func <S> Setup,
     Func <S, T, S> Inbox,
     ProcessFlags Flags = ProcessFlags.Default,
     State <StrategyContext, Unit> Strategy = null,
     int MaxMailboxSize = ProcessSetting.DefaultMailboxSize,
     Func <S, ProcessId, S> Terminated = null
     ) =>
 List.map(Range(0, Count), n => ActorContext.ActorCreate(ActorContext.SelfProcess, $"{Name}-{n}", Inbox, Setup, Terminated, Strategy, Flags, MaxMailboxSize, false)).ToList();
コード例 #35
0
 /// <summary>
 /// Spawns a new process with N worker processes, each message is mapped
 /// from T to IEnumerable U before each resulting U is passed to the worker
 /// processes in a round robin fashion.
 /// </summary>
 /// <typeparam name="T">Message type</typeparam>
 /// <typeparam name="U">Mapped message type</typeparam>
 /// <param name="Name">Delegator process name</param>
 /// <param name="Count">Number of worker processes</param>
 /// <param name="map">Maps the message from T to IEnumerable U before each one is passed to the workers</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 randomMapMany <T, U>(
     ProcessName Name,
     int Count,
     Action <U> Inbox,
     Func <T, IEnumerable <U> > MapMany,
     ProcessFlags Flags = ProcessFlags.Default,
     State <StrategyContext, Unit> Strategy = null,
     int MaxMailboxSize = ProcessSetting.DefaultMailboxSize,
     string WorkerName  = "worker"
     ) =>
 randomMapMany(Name, Count, () => unit, (_, umsg) => { Inbox(umsg); return(unit); }, MapMany, Flags, Strategy, MaxMailboxSize, WorkerName);
コード例 #36
0
ファイル: Cluster.cs プロジェクト: ricardopieper/language-ext
 /// <param name="nodeName">Unique name for this process.  It becomes the name of the root 
 /// node and allows other services on the cluster to discover you and communicate with you.
 /// </param>
 /// <param name="connectionString">Provider defined connection string</param>
 /// <param name="catalogueName">>Provider defined catalogue name</param>
 /// <param name="metadata">Provider speific metadata</param>
 public static ClusterConfig config(
     ProcessName nodeName,
     string connectionString,
     string catalogueName,
     Map<string, string> metadata = null
 ) => 
     new ClusterConfig(
         nodeName, 
         connectionString, 
         catalogueName, 
         metadata
     );
コード例 #37
0
ファイル: Cluster.cs プロジェクト: OlduwanSteve/language-ext
 /// <summary>
 /// Connect to a cluster
 /// </summary>
 /// <param name="providerName">Provider name is a unique name for the persistence layer 
 /// type, for example: "redis"</param>
 /// <param name="nodeName">Unique name for this process.  It becomes the name of the root 
 /// node and allows other services on the cluster to discover you and communicate with you.
 /// </param>
 /// <param name="connectionString">Provider defined connection string</param>
 /// <param name="catalogueName">>Provider defined catalogue name</param>
 public static ICluster connect(
     string providerName,
     ProcessName nodeName,
     string connectionString,
     string catalogueName,
     ProcessName role
 )
 {
     var cluster = ClusterFactory.CreateCluster(providerName, config(nodeName,connectionString,catalogueName, role));
     cluster.Connect();
     return cluster;
 }
コード例 #38
0
 public ClusterConfig(
     ProcessName nodeName,
     string connectionString,
     string catalogueName,
     Map<string, string> metadata = null
 )
 {
     NodeName = nodeName;
     ConnectionString = connectionString;
     CatalogueName = catalogueName;
     Metadata = metadata ?? Map.empty<string,string>();
 }
コード例 #39
0
        public ProcessId(string path)
        {
            if (path == null || path.Length == 0)
            {
                throw new InvalidProcessIdException();
            }
            if (path[0] != Sep)
            {
                throw new InvalidProcessIdException();
            }
            if (path.Length == 1)
            {
                parts = new ProcessName[0];
            }
            else
            {
                try
                {
                    parts = path.Substring(1)
                                .Split(Sep)
                                .Select(p => new ProcessName(p))
                                .ToArray();
                }
                catch (InvalidProcessNameException)
                {
                    throw new InvalidProcessIdException();
                }
            }

            Path = parts == null
                ? ""
                : parts.Length == 0
                    ? Sep.ToString()
                    : Sep + String.Join(Sep.ToString(), parts);

            if (path != "/")
            {
                name = parts == null
                    ? ""
                    : parts.Length == 0
                        ? Sep.ToString()
                        : parts.Last();
            }
            else
            {
                name = "$";
            }
        }
コード例 #40
0
ファイル: ProcessLog.cs プロジェクト: jzabroski/language-ext
        /// <summary>
        /// Start up the process log
        /// </summary>
        /// <param name="processNameOverride">Override the default process name</param>
        /// <param name="logViewMax">Size of the log 'window'</param>
        public static Unit startup(Option<ProcessName> processNameOverride, int logViewMax = 200)
        {
            if (processId.IsValid) return unit;
            lock (sync)
            {
                if (processId.IsValid) return unit;

                processName = processNameOverride.IfNone("process-log");
                processId = spawn<State, ProcessLogItem>(processName, () => setup(logViewMax), inbox);

                deadLetterSub = subscribe<DeadLetter>(DeadLetters, msg => tellWarning(msg.ToString()));
                errorSub = subscribe<Exception>(Errors, e => tellError(e));
            }

            return unit;
        }
コード例 #41
0
        public SessionManager(Option<ICluster> cluster, SystemName system, ProcessName nodeName, VectorConflictStrategy strategy)
        {
            this.cluster = cluster;
            this.system = system;
            this.nodeName = nodeName;

            Sync = new SessionSync(system, nodeName, strategy);

            cluster.Iter(c =>
            {
                notify = c.SubscribeToChannel<SessionAction>(SessionsNotify).Subscribe(act => Sync.Incoming(act));

                var now = DateTime.UtcNow;

                // Look for stranded sessions that haven't been removed properly.  This is done once only
                // on startup because the systems should be shutting down sessions on their own.  This just
                // catches the situation where an app-domain died without shutting down properly.
                c.QuerySessionKeys()
                 .Map(key =>
                    from ts in c.GetHashField<long>(key, LastAccessKey)
                    from to in c.GetHashField<int>(key, TimeoutKey)
                    where new DateTime(ts) < now.AddSeconds(to * 2) // Multiply by 2, just to catch genuine non-active sessions
                    select c.Delete(key))
                 .Iter(id => { });

                // Remove session keys when an in-memory session ends
                ended = SessionEnded.Subscribe(sid => Stop(sid));

                touch = Sync.Touched.Subscribe(tup =>
                {
                    try
                    {
                        c.HashFieldAddOrUpdate(SessionKey(tup.Item1), LastAccessKey, DateTime.UtcNow.Ticks);
                        c.PublishToChannel(SessionsNotify, SessionAction.Touch(tup.Item1, system, nodeName));
                    }
                    catch(Exception e)
                    {
                        logErr(e);
                    }
                });
            });
        }
コード例 #42
0
ファイル: ClusterNode.cs プロジェクト: cartermp/language-ext
 public ClusterNode(ProcessName nodeName, DateTime lastHeartbeat, ProcessName role)
 {
     NodeName = nodeName;
     LastHeartbeat = lastHeartbeat;
     Role = role;
 }
コード例 #43
0
 /// <summary>
 /// Deregister all Processes associated with a name. NOTE: Be very careful
 /// with usage of this function if you didn't handle the registration you
 /// are potentially disconnecting many Processes from their registered name.
 /// 
 /// See remarks.
 /// </summary>
 /// <remarks>
 /// Any Process (or dispatcher, or role, etc.) can be registered by a name - 
 /// a kind of DNS for ProcessIds.  There can be multiple names associated
 /// with a single ProcessId and multiple ProcessIds associated with a name.
 /// 
 /// This function removes all registered ProcessIds for a specific name.
 /// If you wish to deregister all names registered for specific Process then
 /// use Process.deregisterById(pid)
 /// </remarks>
 /// <param name="name">Name of the process to deregister</param>
 public static Unit deregisterByName(ProcessName name) =>
     ActorContext.DeregisterByName($"{Role.Current.Value}-{name.Value}");
コード例 #44
0
ファイル: Node.cs プロジェクト: cartermp/language-ext
 internal NodeOnline(ProcessName name)
 {
     Name = name;
 }
コード例 #45
0
ファイル: Dispatch.cs プロジェクト: plouh/language-ext
 /// <summary>
 /// Removes the dispatcher registration for the named dispatcher
 /// </summary>
 /// <param name="name">Name of the dispatcher to remove</param>
 public static Unit deregister(ProcessName name) =>
     ActorContext.RemoveDispatcher(name);
コード例 #46
0
 public static ProcessId Register(ProcessName name, ProcessId process) =>
     map(registered as IProcessInternal,
         self => match(self.GetChildProcess(name),
             Some: _ => failwith<IProcess>("Process '"+ name + "' already registered"),
             None: () => self.AddChildProcess( new ActorProxy(
                                                 registered.Id,
                                                 name,
                                                 ActorProxyTemplate.Registered,
                                                 () => new ActorProxyConfig(process) ) ) ) ).Id;
コード例 #47
0
 public State SetMember(ProcessName nodeName, ClusterNode state) =>
     new State(Members.AddOrUpdate(nodeName, state));
コード例 #48
0
 public ProcessId MakeChildId(ProcessName name) =>
     parts == null
         ? failwith<ProcessId>("ProcessId is None")
         : parts.Length == 0
             ? new ProcessId("" + Sep + name)
             : new ProcessId(Path + Sep + name);
コード例 #49
0
ファイル: Prelude.cs プロジェクト: OlduwanSteve/language-ext
 /// <summary>
 /// Get the child processes by name
 /// </summary>
 public static ProcessId child(ProcessName name) =>
     InMessageLoop
         ? Self[name]
         : raiseUseInMsgLoopOnlyException<ProcessId>(nameof(child));
コード例 #50
0
ファイル: Dispatch.cs プロジェクト: OlduwanSteve/language-ext
 public static Option<Func<ProcessId, IEnumerable<ProcessId>>> getFuncOption(ProcessName name) =>
     dispatchers.Find(name);
コード例 #51
0
ファイル: Dispatch.cs プロジェクト: OlduwanSteve/language-ext
 public static Func<ProcessId, IEnumerable<ProcessId>> getFunc(ProcessName name) =>
     dispatchers.Find(name,
         Some: x => x,
         None: () => (ProcessId Id) => (new ProcessId[0]).AsEnumerable()
         );
コード例 #52
0
 public static Unit UnRegister(ProcessName name) =>
     map(registered.Id + ProcessId.Sep.ToString() + name,
         id =>
             Store.ContainsKey(id)
                 ? Process.kill(id)
                 : unit);
コード例 #53
0
 /// <summary>
 /// Find a process by its *registered* name (a kind of DNS for Processes) in the
 /// role specified.
 /// 
 /// See remarks.
 /// </summary>
 /// <remarks>
 /// Multiple Processes can register under the same name.  You may use 
 /// a dispatcher to work on them collectively (wherever they are in the 
 /// cluster).  i.e. 
 /// 
 ///     var regd = register("proc", pid);
 ///     tell(Dispatch.Broadcast[regd], "Hello");
 ///     tell(Dispatch.First[regd], "Hello");
 ///     tell(Dispatch.LeastBusy[regd], "Hello");
 ///     tell(Dispatch.Random[regd], "Hello");
 ///     tell(Dispatch.RoundRobin[regd], "Hello");
 /// 
 /// </remarks>
 /// <param name="name">Process name</param>
 /// <returns>A ProcessId that allows dispatching to the process(es).  The result
 /// would look like /disp/reg/name</returns>
 public static ProcessId find(ProcessName role, ProcessName name) =>
     ActorContext.Disp["reg"][$"{role.Value}-{name.Value}"];
コード例 #54
0
 /// <summary>
 /// Finds all *persistent* registered names in a role
 /// </summary>
 /// <param name="role">Role to limit search to</param>
 /// <param name="keyQuery">Key query.  * is a wildcard</param>
 /// <returns>Registered names</returns>
 public static IEnumerable<ProcessName> queryRegistered(ProcessName role, string keyQuery, SystemName system = default(SystemName)) =>
     ActorContext.System(system).Cluster
                 .Map(c => c.QueryRegistered(role.Value, keyQuery))
                 .IfNone(List.empty<ProcessName>());
コード例 #55
0
 public State RemoveMember(ProcessName nodeName) =>
     new State(Members.Remove(nodeName));
コード例 #56
0
ファイル: Dispatch.cs プロジェクト: plouh/language-ext
 /// <summary>
 /// Registers a dispatcher for a role
 /// Dispatchers take in a 'leaf' ProcessId (i.e. /user/my-process) and return an enumerable
 /// of real ProcessIds that the Process system will use to deliver all of the standard functions
 /// like tell, ask, subscribe, etc.
 /// </summary>
 /// <param name="name">Name of the dispatcher</param>
 /// <param name="selector">Function that will be invoked every time a dispatcher based ProcessId
 /// is used.</param>
 /// <returns>A root dispatcher ProcessId.  Use this to create new ProcessIds that will
 /// be passed to the selector function whenever the dispatcher based ProcessId is used</returns>
 public static ProcessId register(ProcessName name, Func<ProcessId, IEnumerable<ProcessId>> selector) =>
     ActorContext.AddDispatcher(name, selector);
コード例 #57
0
 /// <summary>
 /// Register a named process (a kind of DNS for Processes).  
 /// 
 /// If the Process is visible to the cluster (PersistInbox) then the 
 /// registration becomes a permanent named look-up until Process.deregister 
 /// is called.
 /// 
 /// See remarks.
 /// </summary>
 /// <remarks>
 /// Multiple Processes can register under the same name.  You may use 
 /// a dispatcher to work on them collectively (wherever they are in the 
 /// cluster).  i.e. 
 /// 
 ///     var regd = register("proc", pid);
 ///     tell(Dispatch.Broadcast[regd], "Hello");
 ///     tell(Dispatch.First[regd], "Hello");
 ///     tell(Dispatch.LeastBusy[regd], "Hello");
 ///     tell(Dispatch.Random[regd], "Hello");
 ///     tell(Dispatch.RoundRobin[regd], "Hello");
 /// 
 /// </remarks>
 /// <param name="name">Name to register under</param>
 /// <param name="process">Process to be registered</param>
 /// <returns>A ProcessId that allows dispatching to the process(es).  The result
 /// would look like /disp/reg/name</returns>
 public static ProcessId register(ProcessName name, ProcessId process) =>
     ActorContext.Register($"{Role.Current.Value}-{name.Value}", process);
コード例 #58
0
 public State SetMember(ProcessName nodeName, ClusterNode state) =>
     state == null
         ? RemoveMember(nodeName)
         : new State(Members.AddOrUpdate(nodeName, state), System);
コード例 #59
0
ファイル: Prelude_Query.cs プロジェクト: plouh/language-ext
 /// <summary>
 /// Finds all *persistent* registered names in a role
 /// </summary>
 /// <param name="role">Role to limit search to</param>
 /// <param name="keyQuery">Key query.  * is a wildcard</param>
 /// <returns>Registered names</returns>
 public static IEnumerable<ProcessName> queryRegistered(ProcessName role, string keyQuery) =>
     ActorContext.Cluster
                 .Map(c => c.QueryRegistered(role.Value, keyQuery))
                 .IfNone(List.empty<ProcessName>());
コード例 #60
0
ファイル: Role.cs プロジェクト: plouh/language-ext
 internal static Unit init(ProcessName name)
 {
     Current = name;
     return unit;
 }