/// <summary>
 /// TBD
 /// </summary>
 /// <param name="role">TBD</param>
 /// <param name="rememberEntities">TBD</param>
 /// <param name="journalPluginId">TBD</param>
 /// <param name="snapshotPluginId">TBD</param>
 /// <param name="passivateIdleEntityAfter">TBD</param>
 /// <param name="stateStoreMode">TBD</param>
 /// <param name="tuningParameters">TBD</param>
 /// <param name="coordinatorSingletonSettings">TBD</param>
 /// <param name="leaseSettings">TBD</param>
 public ClusterShardingSettings(
     string role,
     bool rememberEntities,
     string journalPluginId,
     string snapshotPluginId,
     TimeSpan passivateIdleEntityAfter,
     StateStoreMode stateStoreMode,
     TuningParameters tuningParameters,
     ClusterSingletonManagerSettings coordinatorSingletonSettings,
     LeaseUsageSettings leaseSettings)
 {
     Role                         = role;
     RememberEntities             = rememberEntities;
     JournalPluginId              = journalPluginId;
     SnapshotPluginId             = snapshotPluginId;
     PassivateIdleEntityAfter     = passivateIdleEntityAfter;
     StateStoreMode               = stateStoreMode;
     TuningParameters             = tuningParameters;
     CoordinatorSingletonSettings = coordinatorSingletonSettings;
     LeaseSettings                = leaseSettings;
 }
        /// <summary>
        /// Creates a new instance of the <see cref="ClusterSingletonManagerSettings"/>.
        /// </summary>
        /// <param name="singletonName">The actor name of the child singleton actor.</param>
        /// <param name="role">
        /// Singleton among the nodes tagged with specified role. If the role is not specified
        /// it's a singleton among all nodes in the cluster.
        /// </param>
        /// <param name="removalMargin">
        /// Margin until the singleton instance that belonged to a downed/removed partition is
        /// created in surviving partition. The purpose of  this margin is that in case of
        /// a network partition the singleton actors  in the non-surviving partitions must
        /// be stopped before corresponding actors are started somewhere else.
        /// This is especially important for persistent actors.
        /// </param>
        /// <param name="handOverRetryInterval">
        /// When a node is becoming oldest it sends hand-over
        /// request to previous oldest, that might be leaving the cluster. This is
        /// retried with this interval until the previous oldest confirms that the hand
        /// over has started or the previous oldest member is removed from the cluster
        /// (+ <paramref name="removalMargin"/>).
        /// </param>
        /// <param name="leaseSettings">LeaseSettings for acquiring before creating the singleton actor</param>
        /// <exception cref="ArgumentException">TBD</exception>
        public ClusterSingletonManagerSettings(string singletonName, string role, TimeSpan removalMargin, TimeSpan handOverRetryInterval, LeaseUsageSettings leaseSettings)
        {
            if (string.IsNullOrWhiteSpace(singletonName))
            {
                throw new ArgumentNullException(nameof(singletonName));
            }
            if (removalMargin < TimeSpan.Zero)
            {
                throw new ArgumentException("ClusterSingletonManagerSettings.RemovalMargin must be positive", nameof(removalMargin));
            }
            if (handOverRetryInterval <= TimeSpan.Zero)
            {
                throw new ArgumentException("ClusterSingletonManagerSettings.HandOverRetryInterval must be positive", nameof(handOverRetryInterval));
            }

            SingletonName         = singletonName;
            Role                  = role;
            RemovalMargin         = removalMargin;
            HandOverRetryInterval = handOverRetryInterval;
            LeaseSettings         = leaseSettings;
        }
        /// <summary>
        /// Creates a new <see cref="ClusterSingletonManagerSettings"/> instance.
        /// </summary>
        /// <param name="config">The HOCON configuration used to create the settings.</param>
        /// <returns>The requested settings.</returns>
        public static ClusterSingletonManagerSettings Create(Config config)
        {
            if (config.IsNullOrEmpty())
            {
                throw ConfigurationException.NullOrEmptyConfig <ClusterSingletonManagerSettings>();
            }


            LeaseUsageSettings lease = null;
            var leaseConfigPath      = config.GetString("use-lease");

            if (!string.IsNullOrEmpty(leaseConfigPath))
            {
                lease = new LeaseUsageSettings(leaseConfigPath, config.GetTimeSpan("lease-retry-interval"));
            }

            return(new ClusterSingletonManagerSettings(
                       singletonName: config.GetString("singleton-name"),
                       role: RoleOption(config.GetString("role")),
                       removalMargin: TimeSpan.Zero, // defaults to ClusterSettings.DownRemovalMargin
                       handOverRetryInterval: config.GetTimeSpan("hand-over-retry-interval"),
                       leaseSettings: lease));
        }
 public ClusterShardingSettings WithLeaseSettings(LeaseUsageSettings leaseSettings)
 {
     return(Copy(leaseSettings: leaseSettings));
 }
        /// <summary>
        /// TBD
        /// </summary>
        /// <param name="config">TBD</param>
        /// <param name="singletonConfig">TBD</param>
        /// <returns>TBD</returns>
        public static ClusterShardingSettings Create(Config config, Config singletonConfig)
        {
            if (config.IsNullOrEmpty())
            {
                throw ConfigurationException.NullOrEmptyConfig <ClusterShardingSettings>();
            }

            var tuningParameters = new TuningParameters(
                coordinatorFailureBackoff: config.GetTimeSpan("coordinator-failure-backoff"),
                retryInterval: config.GetTimeSpan("retry-interval"),
                bufferSize: config.GetInt("buffer-size"),
                handOffTimeout: config.GetTimeSpan("handoff-timeout"),
                shardStartTimeout: config.GetTimeSpan("shard-start-timeout"),
                shardFailureBackoff: config.GetTimeSpan("shard-failure-backoff"),
                entityRestartBackoff: config.GetTimeSpan("entity-restart-backoff"),
                rebalanceInterval: config.GetTimeSpan("rebalance-interval"),
                snapshotAfter: config.GetInt("snapshot-after"),
                keepNrOfBatches: config.GetInt("keep-nr-of-batches"),
                leastShardAllocationRebalanceThreshold: config.GetInt("least-shard-allocation-strategy.rebalance-threshold"),
                leastShardAllocationMaxSimultaneousRebalance: config.GetInt("least-shard-allocation-strategy.max-simultaneous-rebalance"),
                waitingForStateTimeout: config.GetTimeSpan("waiting-for-state-timeout"),
                updatingStateTimeout: config.GetTimeSpan("updating-state-timeout"),
                entityRecoveryStrategy: config.GetString("entity-recovery-strategy"),
                entityRecoveryConstantRateStrategyFrequency: config.GetTimeSpan("entity-recovery-constant-rate-strategy.frequency"),
                entityRecoveryConstantRateStrategyNumberOfEntities: config.GetInt("entity-recovery-constant-rate-strategy.number-of-entities"),
                leastShardAllocationAbsoluteLimit: config.GetInt("least-shard-allocation-strategy.rebalance-absolute-limit"),
                leastShardAllocationRelativeLimit: config.GetDouble("least-shard-allocation-strategy.rebalance-relative-limit"));

            var coordinatorSingletonSettings = ClusterSingletonManagerSettings.Create(singletonConfig);
            var role = config.GetString("role", null);

            if (role == string.Empty)
            {
                role = null;
            }

            var usePassivateIdle   = config.GetString("passivate-idle-entity-after").ToLowerInvariant();
            var passivateIdleAfter =
                usePassivateIdle.Equals("off") ||
                usePassivateIdle.Equals("false") ||
                usePassivateIdle.Equals("no")
                    ? TimeSpan.Zero
                    : config.GetTimeSpan("passivate-idle-entity-after");

            LeaseUsageSettings lease = null;
            var leaseConfigPath      = config.GetString("use-lease");

            if (!string.IsNullOrEmpty(leaseConfigPath))
            {
                lease = new LeaseUsageSettings(leaseConfigPath, config.GetTimeSpan("lease-retry-interval"));
            }

            return(new ClusterShardingSettings(
                       role: role,
                       rememberEntities: config.GetBoolean("remember-entities"),
                       journalPluginId: config.GetString("journal-plugin-id"),
                       snapshotPluginId: config.GetString("snapshot-plugin-id"),
                       passivateIdleEntityAfter: passivateIdleAfter,
                       stateStoreMode: (StateStoreMode)Enum.Parse(typeof(StateStoreMode), config.GetString("state-store-mode"), ignoreCase: true),
                       tuningParameters: tuningParameters,
                       coordinatorSingletonSettings: coordinatorSingletonSettings,
                       leaseSettings: lease));
        }
 /// <summary>
 /// Create a singleton manager with specified singleton lease settings.
 /// </summary>
 /// <param name="leaseSettings">TBD</param>
 /// <returns></returns>
 public ClusterSingletonManagerSettings WithLeaseSettings(LeaseUsageSettings leaseSettings)
 {
     return(Copy(leaseSettings: leaseSettings));
 }