public void KeepAliveThrowsWhenZero()
        {
            // Arrange
            var config = new TransportOptions();

            // Assert
            Assert.Throws(typeof(ArgumentOutOfRangeException), () => config.KeepAlive = TimeSpan.FromSeconds(0));
        }
        /// <summary>
        /// The amount of time a Topic should stay in memory after its last subscriber is removed.
        /// </summary>
        /// <param name="options"></param>
        /// <returns></returns>
        public static TimeSpan TopicTtl(this TransportOptions options)
        {
            // If the deep-alive is disabled, don't take it into account when calculating the topic TTL.
            var keepAliveTimeout = options.KeepAliveTimeout() ?? TimeSpan.Zero;

            // Keep topics alive for twice as long as we let connections to reconnect. (The DisconnectTimeout)
            // Also add twice the keep-alive timeout since clients might take a while to notice they are disconnected.
            // This should be a very conservative estimate for how long we must wait before considering a topic dead.
            return(TimeSpan.FromTicks((options.DisconnectTimeout.Ticks + keepAliveTimeout.Ticks) * 2));
        }
 /// <summary>
 /// The amount of time the client should wait without seeing a keep alive before trying to reconnect.
 /// </summary>
 public static TimeSpan?KeepAliveTimeout(this TransportOptions options)
 {
     if (options.KeepAlive != null)
     {
         return(TimeSpan.FromTicks(options.KeepAlive.Value.Ticks * MissedTimeoutsBeforeClientReconnect));
     }
     else
     {
         return(null);
     }
 }
        public void DefaultValues()
        {
            // Arrange
            var config = new TransportOptions();

            // Assert
            Assert.Equal(110, config.LongPolling.PollTimeout.TotalSeconds);
            Assert.Equal(30, config.DisconnectTimeout.TotalSeconds);
            Assert.Equal(10, config.KeepAlive.Value.TotalSeconds);
            Assert.Equal(20, config.KeepAliveTimeout().Value.TotalSeconds);
            Assert.Equal(5, config.HeartbeatInterval().TotalSeconds);
            Assert.Equal(100, config.TopicTtl().TotalSeconds);
        }
 /// <summary>
 /// The interval between successively checking connection states.
 /// </summary>
 public static TimeSpan HeartbeatInterval(this TransportOptions options)
 {
     if (options.KeepAlive != null)
     {
         return(TimeSpan.FromTicks(options.KeepAlive.Value.Ticks / HeartBeatsPerKeepAlive));
     }
     else
     {
         // If KeepAlives are disabled, have the heartbeat run at the same rate it would if the KeepAlive was
         // kept at the default value.
         return(TimeSpan.FromTicks(options.DisconnectTimeout.Ticks / HeartBeatsPerDisconnectTimeout));
     }
 }
        /// <summary>
        /// Initializes and instance of the <see cref="TransportHeartbeat"/> class.
        /// </summary>
        /// <param name="serviceProvider">The <see cref="IDependencyResolver"/>.</param>
        public TransportHeartbeat(IOptions<SignalROptions> optionsAccessor,
                                  IPerformanceCounterManager counters,
                                  ILoggerFactory loggerFactory)
        {
            _transportOptions = optionsAccessor.Options.Transports;
            _counters = counters;
            _logger = loggerFactory.CreateLogger<TransportHeartbeat>();

            // REVIEW: When to dispose the timer?
            _timer = new Timer(Beat,
                               null,
                               _transportOptions.HeartbeatInterval(),
                               _transportOptions.HeartbeatInterval());
        }
        public void TwoSecondsAndNullOnlyValidKeepAliveValuesWhenDisconnectTimeoutIsSixSeconds()
        {
            // Arrange
            var config = new TransportOptions();
            config.DisconnectTimeout = TimeSpan.FromSeconds(6);

            // Assert
            Assert.Throws(typeof(ArgumentOutOfRangeException), () => config.KeepAlive = TimeSpan.FromSeconds(1.99));
            Assert.Throws(typeof(ArgumentOutOfRangeException), () => config.KeepAlive = TimeSpan.FromSeconds(2.01));

            // Assert doesn't throw
            config.KeepAlive = TimeSpan.FromSeconds(2);
            config.KeepAlive = null;
        }
        public void KeepAliveThrowsWhenGreaterThanAThirdOfTheDisconnectTimeout()
        {
            // Arrange
            var config = new TransportOptions();

            // Assert
            Assert.Throws(typeof(ArgumentOutOfRangeException), () => config.KeepAlive = TimeSpan.FromSeconds(10.01));
            config.KeepAlive = TimeSpan.FromSeconds(10);

            // Arrange
            config = new TransportOptions();
            config.DisconnectTimeout = TimeSpan.FromSeconds(15);

            // Assert
            Assert.Throws(typeof(ArgumentOutOfRangeException), () => config.KeepAlive = TimeSpan.FromSeconds(5.01));
            config.KeepAlive = TimeSpan.FromSeconds(5);
        }
        public void TopicTopicTimeToLiveIsDoubleTheDisconnectTimeoutWhenKeepAliveIsNull()
        {
            var config = new TransportOptions();
            var random = new Random();
            config.DisconnectTimeout = TimeSpan.FromSeconds(random.Next(6, 31536000)); // 12 seconds to a year
            config.KeepAlive = null;

            // Assert
            Assert.Equal(TimeSpan.FromTicks(config.DisconnectTimeout.Ticks * 2), config.TopicTtl());
        }
        public void DisconnectTimeoutThrowsWhenLessThanSixSeconds()
        {
            // Arrange
            var config = new TransportOptions();

            // Assert
            Assert.Throws(typeof(ArgumentOutOfRangeException), () => config.DisconnectTimeout = TimeSpan.FromSeconds(5.99));
            config.DisconnectTimeout = TimeSpan.FromSeconds(6);
        }
        public void SettingDisconnectTimeoutSetKeepAliveToAThirdOfItself()
        {
            // Arrange
            var config = new TransportOptions();
            var random = new Random();
            config.DisconnectTimeout = TimeSpan.FromSeconds(random.Next(6, 31536000)); // 6 seconds to a year

            // Assert
            Assert.Equal(TimeSpan.FromTicks(config.DisconnectTimeout.Ticks / 3), config.KeepAlive);
        }
        public void DisconnectTimeoutThrowsWhenNegative()
        {
            // Arrange
            var config = new TransportOptions();

            // Assert
            Assert.Throws(typeof(ArgumentOutOfRangeException), () => config.KeepAlive = TimeSpan.FromSeconds(-1));
        }
        public void KeepAliveCannotBeConfiguredBeforeDisconnectTimeout()
        {
            // Arrange
            var config = new TransportOptions();
            config.KeepAlive = TimeSpan.FromSeconds(5);

            // Assert
            Assert.Throws(typeof(InvalidOperationException), () => config.DisconnectTimeout = TimeSpan.FromSeconds(40));

            // Arrange
            config = new TransportOptions();
            config.KeepAlive = null;

            // Assert
            Assert.Throws(typeof(InvalidOperationException), () => config.DisconnectTimeout = TimeSpan.FromSeconds(40));
        }
        public void KeepAliveTimeoutIsTwiceTheKeepAlive()
        {
            // Arrange
            var config = new TransportOptions();
            var random = new Random();
            config.KeepAlive = TimeSpan.FromSeconds(random.NextDouble() * 8 + 2); // 2 to 10 seconds

            // Assert
            Assert.Equal(TimeSpan.FromTicks(config.KeepAlive.Value.Ticks * 2), config.KeepAliveTimeout());

            // Arrange
            config.KeepAlive = null;

            // Assert
            Assert.Equal(null, config.KeepAliveTimeout());
        }
 public SignalROptions()
 {
     Hubs = new HubOptions();
     MessageBus = new MessageBusOptions();
     Transports = new TransportOptions();
 }
        public void TopicTimeToLiveIsDoubleTheDisconnectAndKeepAliveTimeouts()
        {
            var config = new TransportOptions();
            var random = new Random();
            config.DisconnectTimeout = TimeSpan.FromSeconds(random.Next(12, 31536000)); // 12 seconds to a year
            config.KeepAlive = TimeSpan.FromTicks(config.DisconnectTimeout.Ticks / 6); // Set custom keep-alive to half the default

            // Assert
            Assert.Equal(TimeSpan.FromTicks(config.DisconnectTimeout.Ticks * 2 + config.KeepAliveTimeout().Value.Ticks * 2),
                         config.TopicTtl());
        }
        public void HeartbeatIntervalIsASixthOfTheDisconnectTimeoutIfTheKeepAliveIsNull()
        {
            // Arrange
            var config = new TransportOptions();
            var random = new Random();
            config.DisconnectTimeout = TimeSpan.FromSeconds(random.Next(6, 31536000)); // 6 seconds to a year
            config.KeepAlive = null;

            // Assert
            Assert.Equal(TimeSpan.FromTicks(config.DisconnectTimeout.Ticks / 6), config.HeartbeatInterval());
        }
        public void HeartbeatIntervalIsHalfTheKeepAlive()
        {
            // Arrange
            var config = new TransportOptions();
            var random = new Random();
            config.KeepAlive = TimeSpan.FromSeconds(random.NextDouble() * 8 + 2); // 2 to 10 seconds

            // Assert
            Assert.Equal(TimeSpan.FromTicks(config.KeepAlive.Value.Ticks / 2), config.HeartbeatInterval());
        }