コード例 #1
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);
        }
コード例 #2
0
 public Map <string, T> GetHashFields <T>(string key) =>
 Retry(() =>
       Db.HashGetAll(key)
       .Fold(
           Map.empty <string, T>(),
           (m, e) => m.Add(e.Name, JsonConvert.DeserializeObject <T>(e.Value)))
       .Filter(notnull));
コード例 #3
0
 public Map <K, T> GetHashFields <K, T>(string key, Func <string, K> keyBuilder) =>
 Retry(() =>
       Db.HashGetAll(key)
       .Fold(
           Map.empty <K, T>(),
           (m, e) => m.Add(keyBuilder(e.Name), JsonConvert.DeserializeObject <T>(e.Value)))
       .Filter(notnull));
コード例 #4
0
 public Map <string, T> GetHashFields <T>(string key, IEnumerable <string> fields) =>
 Db.HashGet(key, fields.Map(x => (RedisValue)x).ToArray())
 .Zip(fields)
 .Filter(x => !x.Item1.IsNullOrEmpty)
 .Fold(
     Map.empty <string, T>(),
     (m, e) => m.Add(e.Item2, JsonConvert.DeserializeObject <T>(e.Item1)));
コード例 #5
0
        public Unit ShutdownProcess(bool maintainState)
        {
            Parent.Actor.UnlinkChild(Id);
            ShutdownProcessRec(ActorContext.SelfProcess, ActorContext.GetInboxShutdownItem().Map(x => (ILocalActorInbox)x.Inbox), maintainState);

            children = Map.empty <string, ActorItem>();
            return(unit);
        }
コード例 #6
0
        public static Unit Startup(Option <ICluster> cluster)
        {
            if (started)
            {
                return(unit);
            }

            ActorContext.cluster = cluster;
            var name = GetRootProcessName();

            if (name.Value == "root" && cluster.IsSome)
            {
                throw new ArgumentException("Cluster node name cannot be 'root', it's reserved for local use only.");
            }
            if (name.Value == "disp" && cluster.IsSome)
            {
                throw new ArgumentException("Cluster node name cannot be 'disp', it's reserved for internal use.");
            }
            if (name.Value == "js")
            {
                throw new ArgumentException("Node name cannot be 'js', it's reserved for ProcessJS.");
            }

            lock (sync)
            {
                if (started)
                {
                    return(unit);
                }

                startupTimestamp = DateTime.UtcNow.Ticks;
                startupSubscription?.Dispose();
                startupSubscription = NotifyCluster(cluster, startupTimestamp);

                Dispatch.init();
                Role.init();
                Reg.init();

                watchers  = Map.empty <ProcessId, Set <ProcessId> >();
                watchings = Map.empty <ProcessId, Set <ProcessId> >();
                var root      = ProcessId.Top.Child(name);
                var rootInbox = new ActorInboxLocal <ActorSystemState, Unit>();
                var parent    = new ActorItem(new NullProcess(), new NullInbox(), ProcessFlags.Default);

                var go          = new AutoResetEvent(false);
                var state       = new ActorSystemState(cluster, root, null, rootInbox, cluster.Map(x => x.NodeName).IfNone(ActorConfig.Default.RootProcessName), ActorConfig.Default);
                var rootProcess = state.RootProcess;
                state.Startup();
                userContext = new ActorRequestContext(rootProcess.Children["user"], ProcessId.NoSender, rootItem, null, null, ProcessFlags.Default);
                rootInbox.Startup(rootProcess, parent, cluster, ProcessSetting.DefaultMailboxSize);
                rootItem = new ActorItem(rootProcess, rootInbox, ProcessFlags.Default);
                started  = true;

                SessionManager.Init(cluster);
                ClusterWatch(cluster);
            }
            return(unit);
        }
コード例 #7
0
ファイル: Actor.cs プロジェクト: pahomovda/language-ext
        public Unit ShutdownProcess()
        {
            //tellSystem(Parent.Actor.Id, SystemMessage.UnlinkChild(Id));
            Parent.Actor.UnlinkChild(Id);
            ShutdownProcessRec(ActorContext.SelfProcess, ActorContext.GetInboxShutdownItem().Map(x => (ILocalActorInbox)x.Inbox));

            children = Map.empty <string, ActorItem>();
            return(unit);
        }
コード例 #8
0
 /// <summary>
 /// Resets the configuration system to all default settings (i.e. empty).  Use this call followed by
 /// one of the ProcessConfig.initialise(...) variants to reload new configuration settings live.
 /// </summary>
 public static Unit unload()
 {
     lock (sync)
     {
         appProfile      = null;
         config          = new ProcessSystemConfig("");
         processSettings = Map.empty <string, object>();
         return(unit);
     }
 }
コード例 #9
0
 public StrategyState(
     Time backoffAmount,
     int failures,
     DateTime lastFailure,
     Map <string, object> metadata
     )
 {
     BackoffAmount = backoffAmount;
     Failures      = failures;
     LastFailure   = lastFailure;
     Metadata      = metadata ?? Map.empty <string, object>();
 }
コード例 #10
0
 public Unit ShutdownProcess(bool maintainState)
 {
     lock (sync)
     {
         return(Parent.Actor.Children.Find(Name.Value).IfSome(self =>
         {
             ShutdownProcessRec(self, sys.GetInboxShutdownItem().Map(x => (ILocalActorInbox)x.Inbox), maintainState);
             Parent.Actor.UnlinkChild(Id);
             children = Map.empty <string, ActorItem>();
         }));
     }
 }
コード例 #11
0
 public static State Empty(IActorSystem system) => new State(Map.empty <ProcessName, ClusterNode>(), system);
コード例 #12
0
 public State()
 {
     Sessions = Map.empty <string, Session>();
     Metadata = Map.empty <string, object>();
 }
コード例 #13
0
ファイル: Role.cs プロジェクト: dhalsim/language-ext
        /// <summary>
        /// Static ctor
        /// Sets up the default roles
        /// </summary>
        static Role()
        {
            ProcessName first      = "role-first";
            ProcessName second     = "role-second";
            ProcessName third      = "role-third";
            ProcessName last       = "role-last";
            ProcessName next       = "role-next";
            ProcessName prev       = "role-prev";
            ProcessName broadcast  = "role-broadcast";
            ProcessName leastBusy  = "role-least-busy";
            ProcessName random     = "role-random";
            ProcessName roundRobin = "role-round-robin";

            var nextNode = fun((bool fwd) => fun((ProcessId leaf) =>
            {
                var self    = leaf.Take(1).GetName();
                var isNext  = false;
                var nodeMap = Nodes(leaf);

                var nodes = fwd
                    ? nodeMap.Values.Append(nodeMap.Values)
                    : nodeMap.Values.Append(nodeMap.Values).Reverse(); //< TODO: Inefficient

                foreach (var node in nodes)
                {
                    if (isNext)
                    {
                        return(new[] { ProcessId.Top[node.NodeName].Append(leaf.Skip(1)) }.AsEnumerable());
                    }

                    if (node.NodeName == self)
                    {
                        isNext = true;
                    }
                }
                return(new ProcessId[0].AsEnumerable());
            }));

            // Next
            nextRoot = Dispatch.register(next, nextNode(true));

            // Prev
            prevRoot = Dispatch.register(prev, nextNode(false));

            // First
            First = Dispatch.register(first, leaf => NodeIds(leaf).Take(1));

            // Second
            Second = Dispatch.register(second, leaf => NodeIds(leaf).Skip(1).Take(1));

            // Third
            Third = Dispatch.register(third, leaf => NodeIds(leaf).Skip(2).Take(1));

            // Last
            Last = Dispatch.register(last, leaf => NodeIds(leaf).Reverse().Take(1));

            // Broadcast
            Broadcast = Dispatch.register(broadcast, NodeIds);

            // Least busy
            LeastBusy = Dispatch.register(leastBusy, leaf =>
                                          NodeIds(leaf)
                                          .Map(pid => Tuple(inboxCount(pid), pid))
                                          .OrderBy(tup => tup.Item1)
                                          .Map(tup => tup.Item2)
                                          .Take(1));

            // Random
            Random = Dispatch.register(random, leaf => {
                var workers = NodeIds(leaf).ToArray();
                return(new ProcessId[1] {
                    workers[Prelude.random(workers.Length)]
                });
            });

            // Round-robin
            object            sync            = new object();
            Map <string, int> roundRobinState = Map.empty <string, int>();

            RoundRobin = Dispatch.register(roundRobin, leaf => {
                var key     = leaf.ToString();
                var workers = NodeIds(leaf).ToArray();
                int index   = 0;
                lock (sync)
                {
                    roundRobinState = roundRobinState.AddOrUpdate(key, x => { index = x % workers.Length; return(x + 1); }, 0);
                }
                return(new ProcessId[1] {
                    workers[index]
                });
            });
        }
コード例 #14
0
 /// <summary>
 /// Access a map setting
 /// If in a Process message loop, then this accesses the configuration settings
 /// for the Process from the the configuration file, or stored in the cluster.
 /// If not in a Process message loop, then this accesses 'global' configuration
 /// settings.
 /// </summary>
 /// <param name="name">Name of the setting</param>
 /// <param name="prop">If the setting is a complex value (like a map or record), then
 /// this selects the property of the setting to access</param>
 /// <returns>Optional configuration setting value</returns>
 public static Map <string, T> readMap <T>(string name, string prop = "value") =>
 read(name, prop, Map.empty <string, T>());
コード例 #15
0
        static Dispatch()
        {
            ProcessName broadcast  = "broadcast";
            ProcessName leastBusy  = "least-busy";
            ProcessName random     = "random";
            ProcessName roundRobin = "round-robin";

            ProcessName first  = "first";
            ProcessName second = "second";
            ProcessName third  = "third";
            ProcessName last   = "last";

            var processes = fun((ProcessId leaf) =>
            {
                if (!leaf.IsValid)
                {
                    return(new ProcessId[0]);
                }
                if (leaf.IsSelection)
                {
                    return(leaf.GetSelection());
                }
                if (leaf.Head().Name == "disp")
                {
                    leaf = leaf.Skip(1);
                    if (!leaf.IsValid)
                    {
                        return(new ProcessId[0]);
                    }
                    return(getFunc(leaf.Head().Name)(leaf.Skip(1)));
                }
                return(new ProcessId[1] {
                    leaf
                });
            });

            // Broadcast
            Broadcast = register(broadcast, processes);

            // First
            First = register(first, leaf => processes(leaf).Take(1));

            // Second
            Second = register(second, leaf => processes(leaf).Skip(1).Take(1));

            // Third
            Third = register(third, leaf => processes(leaf).Skip(2).Take(1));

            // Last
            Last = register(last, leaf => processes(leaf).Reverse().Take(1));

            // Least busy
            LeastBusy = register(leastBusy, leaf =>
                                 processes(leaf)
                                 .Map(pid => Tuple(inboxCount(pid), pid))
                                 .OrderBy(tup => tup.Item1)
                                 .Map(tup => tup.Item2)
                                 .Take(1));

            // Random
            Random = register(random, leaf => {
                var workers = processes(leaf).ToArray();
                return(new ProcessId[1] {
                    workers[Prelude.random(workers.Length)]
                });
            });

            // Round-robin
            object            sync            = new object();
            Map <string, int> roundRobinState = Map.empty <string, int>();

            RoundRobin = register(roundRobin, leaf => {
                var key     = leaf.ToString();
                var workers = processes(leaf).ToArray();
                int index   = 0;
                lock (sync)
                {
                    roundRobinState = roundRobinState.AddOrUpdate(key, x => { index = x % workers.Length; return(x + 1); }, 0);
                }
                return(new ProcessId[1] {
                    workers[index]
                });
            });
        }
コード例 #16
0
 public Map <string, ProcessId> GetChildren() =>
 List.fold(
     MapRoleMembers(disp => disp.GetChildren()),
     Map.empty <string, ProcessId>(),
     (s, x) => s + x
     );
コード例 #17
0
ファイル: Actor.cs プロジェクト: pahomovda/language-ext
 private Unit RemoveAllSubscriptions()
 {
     subs.Iter(x => x.Dispose());
     subs = Map.empty <string, IDisposable>();
     return(unit);
 }
コード例 #18
0
 /// <summary>
 /// Get a list of cluster nodes that are online
 /// </summary>
 public static Map <ProcessName, ClusterNode> ClusterNodes(SystemName system = default(SystemName)) =>
 ActorContext.System(system).ClusterState == null
         ? Map.empty <ProcessName, ClusterNode>()
         : ActorContext.System(system).ClusterState.Members;
コード例 #19
0
 /// <summary>
 /// Finds all *persistent* processes based on the search pattern provided and then returns the
 /// meta-data associated with them.
 /// </summary>
 /// <param name="keyQuery">Key query.  * is a wildcard</param>
 /// <returns>Map of ProcessId to ProcessMetaData</returns>
 public static Map <ProcessId, ProcessMetaData> queryProcessMetaData(string keyQuery) =>
 ActorContext.Cluster
 .Map(c => c.QueryProcessMetaData(keyQuery))
 .IfNone(Map.empty <ProcessId, ProcessMetaData>());
コード例 #20
0
 public Map <string, ProcessId> GetChildren() =>
 Map.empty <string, ProcessId>();
コード例 #21
0
 /// <summary>
 /// Finds all *persistent* processes based on the search pattern provided and then returns the
 /// meta-data associated with them.
 /// </summary>
 /// <param name="keyQuery">Key query.  * is a wildcard</param>
 /// <returns>Map of ProcessId to ProcessMetaData</returns>
 public static Map <ProcessId, ProcessMetaData> queryProcessMetaData(string keyQuery, SystemName system = default(SystemName)) =>
 ActorContext.System(system).Cluster
 .Map(c => c.QueryProcessMetaData(keyQuery))
 .IfNone(Map.empty <ProcessId, ProcessMetaData>());
コード例 #22
0
        public ActorSystem(SystemName systemName, Option <ICluster> cluster, AppProfile appProfile, ProcessSystemConfig settings)
        {
            var name = GetRootProcessName(cluster);

            if (name.Value == "root" && cluster.IsSome)
            {
                throw new ArgumentException("Cluster node name cannot be 'root', it's reserved for local use only.");
            }
            if (name.Value == "disp" && cluster.IsSome)
            {
                throw new ArgumentException("Cluster node name cannot be 'disp', it's reserved for internal use.");
            }
            if (name.Value == "js")
            {
                throw new ArgumentException("Node name cannot be 'js', it's reserved for ProcessJS.");
            }

            SystemName       = systemName;
            this.appProfile  = appProfile;
            this.settings    = settings;
            this.cluster     = cluster;
            startupTimestamp = DateTime.UtcNow.Ticks;
            sessionManager   = new SessionManager(cluster, SystemName, appProfile.NodeName, VectorConflictStrategy.Branch);
            watchers         = Map.empty <ProcessId, Set <ProcessId> >();
            watchings        = Map.empty <ProcessId, Set <ProcessId> >();

            startupSubscription = NotifyCluster(cluster, startupTimestamp);

            Dispatch.init();
            Role.init(cluster.Map(r => r.Role).IfNone("local"));
            Reg.init();

            var root      = ProcessId.Top.Child(GetRootProcessName(cluster));
            var rootInbox = new ActorInboxLocal <ActorSystemBootstrap, Unit>();
            var parent    = new ActorItem(new NullProcess(SystemName), new NullInbox(), ProcessFlags.Default);

            var state = new ActorSystemBootstrap(
                this,
                cluster,
                root, null,
                rootInbox,
                cluster.Map(x => x.NodeName).IfNone(ActorSystemConfig.Default.RootProcessName),
                ActorSystemConfig.Default,
                Settings,
                sessionManager.Sync
                );

            var rootProcess = state.RootProcess;

            state.Startup();
            rootItem    = new ActorItem(rootProcess, rootInbox, ProcessFlags.Default);
            userContext = new ActorRequestContext(
                this,
                rootProcess.Children["user"],
                ProcessId.NoSender,
                rootItem,
                null,
                null,
                ProcessFlags.Default,
                null,
                null);
            rootInbox.Startup(rootProcess, parent, cluster, settings.GetProcessMailboxSize(rootProcess.Id));
        }