Пример #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
        public static Unit StartSystem(SystemName system, Option <ICluster> cluster, AppProfile appProfile, ProcessSystemConfig config)
        {
            lock (sync)
            {
                if (SystemExists(system))
                {
                    throw new InvalidOperationException($"Process-system ({system}) already started");
                }

                var asystem = new ActorSystem(system, cluster, appProfile, config);
                AddOrUpdateSystem(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 = systems.Filter(a => a.SystemName != system).ToArray();
                    try
                    {
                        asystem.Dispose();
                    }
                    catch { }
                    throw;
                }
                return(unit);
            }
        }
Пример #3
0
        private static void StartFromConfig(ProcessSystemConfig config)
        {
            lock (sync)
            {
                InitLocalScheduler();

                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);
                });
            }
        }
Пример #4
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;
            Ping             = new Ping(this);
            startupTimestamp = DateTime.UtcNow.Ticks;
            sessionManager   = new SessionManager(cluster, SystemName, appProfile.NodeName, VectorConflictStrategy.Branch);
            watchers         = Map <ProcessId, Set <ProcessId> >();
            watchings        = Map <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);

            Root        = rootItem.Actor.Id;
            RootJS      = Root["js"];
            System      = Root[ActorSystemConfig.Default.SystemProcessName];
            User        = Root[ActorSystemConfig.Default.UserProcessName];
            Errors      = System[ActorSystemConfig.Default.ErrorsProcessName];
            DeadLetters = System[ActorSystemConfig.Default.DeadLettersProcessName];
            NodeName    = cluster.Map(c => c.NodeName).IfNone("user");
            AskId       = System[ActorSystemConfig.Default.AskProcessName];
            Disp        = ProcessId.Top["disp"].SetSystem(SystemName);

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