コード例 #1
0
 public Unit UpdateSettings(ProcessSystemConfig settings, AppProfile profile)
 {
     this.settings   = settings;
     this.appProfile = profile;
     // TODO: Consider notification system for Processes
     return(unit);
 }
コード例 #2
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);
     }
 }
コード例 #3
0
        /// <summary>
        /// Process system configuration initialisation
        /// This will parse the configuration text, you should call this
        /// function from within Application_BeginRequest of Global.asax.  It can run multiple times, once the config
        /// has loaded the system won't re-load the config until you call ProcessConfig.unload() followed by
        /// ProcessConfig.initialiseFileSystem(...), so it's safe to not surround it with ifs.
        ///
        /// NOTE: If a cluster is specified in the cluster.conf and its 'node-name' matches nodeName, then those settings
        /// will be used to connect to the cluster.  This allows for different staging environments to be setup.
        /// </summary>
        /// <param name="nodeName">If a cluster is specified in the cluster.conf and its 'node-name' matches nodeName, then
        /// those settings will be used to connect to the cluster.  This allows for different staging environments to be
        /// setup.</param>
        /// <param name="setup">A setup function to call on successful loading of the configuration files - this will
        /// happen once only.</param>
        /// <param name="strategyFuncs">Plugin extra strategy behaviours by passing in a list of FuncSpecs.</param>
        public static AppProfile initialise(string configText, Option <string> nodeName, Action <AppProfile> setup = null, IEnumerable <FuncSpec> strategyFuncs = null)
        {
            if (appProfile != null)
            {
                return(appProfile);
            }
            lock (sync)
            {
                if (appProfile != null)
                {
                    return(appProfile);
                }

                config = new ProcessSystemConfig(nodeName.IfNone(""), strategyFuncs);
                config.ParseConfigText(configText);

                appProfile = AppProfile.NonClustered;

                nodeName.Iter(node =>
                {
                    var provider    = config.GetClusterSetting("provider", "value", "redis");
                    var role        = config.GetClusterSetting("role", "value", name => clusterSettingMissing <string>(name));
                    var clusterConn = config.GetClusterSetting("connection", "value", "localhost");
                    var clusterDb   = config.GetClusterSetting("database", "value", "0");
                    var env         = config.GetClusterSetting <string>("env", "value");
                    var userEnv     = config.GetClusterSetting <string>("user-env", "value");

                    appProfile = new AppProfile(
                        node,
                        role,
                        clusterConn,
                        clusterDb,
                        env,
                        userEnv
                        );

                    Cluster.connect(provider, node, clusterConn, clusterDb, role);
                });

                config.PostConnect();

                setup(appProfile);
                return(appProfile);
            }
        }
コード例 #4
0
        public static Unit StartSystem(SystemName system, Option <ICluster> cluster, AppProfile appProfile, ProcessSystemConfig config)
        {
            lock (sync)
            {
                if (systems.ContainsKey(system))
                {
                    throw new InvalidOperationException($"Process-system ({system}) already started");
                }

                var asystem = new ActorSystem(system, cluster, appProfile, config);
                systems.AddOrUpdate(system, asystem, (_, __) => asystem);
                try
                {
                    asystem.Initialise();

                    // Set the default system if the 'default: yes' setting is in the ProcessSystemConfig
                    defaultSystem = defaultSystem.IsValid
                        ? (from c in config.Cluster
                           where c.Default
                           select system)
                                    .IfNone(defaultSystem)
                        : system;
                }
                catch
                {
                    systems.TryRemove(system, out asystem);
                    try
                    {
                        asystem.Dispose();
                    }
                    catch { }
                    throw;
                }
                return(unit);
            }
        }
コード例 #5
0
        public static Unit StartSystem(SystemName system, Option<ICluster> cluster, AppProfile appProfile, ProcessSystemConfig config)
        {
            lock (sync)
            {
                if (systems.ContainsKey(system))
                {
                    throw new InvalidOperationException($"Process-system ({system}) already started");
                }

                var asystem = new ActorSystem(system, cluster, appProfile, config);
                systems.AddOrUpdate(system, asystem, (_, __) => asystem);
                try
                {
                    asystem.Initialise();

                    // Set the default system if the 'default: yes' setting is in the ProcessSystemConfig
                    defaultSystem = defaultSystem.IsValid
                        ? (from c in config.Cluster
                           where c.Default
                           select system)
                          .IfNone(defaultSystem)
                        : system;
                }
                catch
                {
                    systems.TryRemove(system, out asystem);
                    try
                    {
                        asystem.Dispose();
                    }
                    catch { }
                    throw;
                }
                return unit;
            }
        }
コード例 #6
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));
        }
コード例 #7
0
        private static void StartFromConfig(ProcessSystemConfig config)
        {
            lock (sync)
            {
                config.Cluster.Match(
                    Some: _ =>
                {
                    // Extract cluster settings
                    var provider    = config.GetClusterSetting("provider", "value", "redis");
                    var role        = config.GetClusterSetting("role", "value", name => clusterSettingMissing <string>(name));
                    var clusterConn = config.GetClusterSetting("connection", "value", "localhost");
                    var clusterDb   = config.GetClusterSetting("database", "value", "0");
                    var env         = config.SystemName;
                    var userEnv     = config.GetClusterSetting <string>("user-env", "value");

                    var appProfile = new AppProfile(
                        config.NodeName,
                        role,
                        clusterConn,
                        clusterDb,
                        env,
                        userEnv
                        );

                    // Look for an existing actor-system with the same system name
                    var current = ActorContext.Systems.Filter(c => c.Value == env).HeadOrNone();

                    // Work out if something significant has changed that will cause us to restart
                    var restart = current.Map(ActorContext.System)
                                  .Map(c => c.AppProfile.NodeName != appProfile.NodeName ||
                                       c.AppProfile.Role != appProfile.Role ||
                                       c.AppProfile.ClusterConn != appProfile.ClusterConn ||
                                       c.AppProfile.ClusterDb != appProfile.ClusterDb);

                    // Either restart / update settings / or start new
                    restart.Match(
                        Some: r =>
                    {
                        if (r)
                        {
                            // Restart
                            try
                            {
                                ActorContext.StopSystem(env);
                            }
                            catch (Exception e)
                            {
                                logErr(e);
                            }
                            StartFromConfig(config);
                        }
                        else
                        {
                            // Update settings
                            ActorContext.System(env).UpdateSettings(config, appProfile);
                            var cluster = from systm in current.Map(ActorContext.System)
                                          from clstr in systm.Cluster
                                          select clstr;
                        }
                    },
                        None: () =>
                    {
                        // Start new
                        ICluster cluster = Cluster.connect(
                            provider,
                            config.NodeName,
                            clusterConn,
                            clusterDb,
                            role
                            );

                        ActorContext.StartSystem(env, Optional(cluster), appProfile, config);
                        config.PostConnect();
                    });
                },
                    None: () =>
                {
                    ActorContext.StartSystem(new SystemName(""), None, AppProfile.NonClustered, config);
                });
            }
        }