Exemple #1
0
        public void Throttle_CanWaitBetweenRequests_FromEndOfLastRequest()
        {
            // no more than 1 thread per second from end of last request
            ThrottleConfiguration configuration = new ThrottleConfiguration
            {
                WaitTimeBetweenLease = TimeSpan.FromSeconds(1),
                WaitStrategy         = ThrottleWaitStrategy.FromEndOfLastRequest
            };

            Throttle throttle = new Throttle(configuration);

            Task[] threads = new Task[5];

            ManualResetEvent awaiter = new ManualResetEvent(false);

            for (int i = 0; i < threads.Length; i++)
            {
                int instance = i;
                threads[i] = Task.Run(() => {
                    awaiter.WaitOne();
                    Log.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] Instance {instance}: thread started");

                    using (throttle.AcquireLease())
                    {
                        TimeSpan?timeSinceLastRequest = DateTimeOffset.Now - throttle.LastFinishTime;

                        Log.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] Instance {instance}: aquired lease (threads: {throttle.ActiveThreads}, timeSinceLastRequest: {timeSinceLastRequest})");

                        Assert.True(throttle.ActiveThreads <= configuration.MaxConcurrentThreads, $"Instance {instance}: Thread count exceeds max concurrent threads (actual: {throttle.ActiveThreads}, max: {configuration.MaxConcurrentThreads})");

                        if (timeSinceLastRequest != null)
                        {
                            Assert.True(timeSinceLastRequest >= configuration.WaitTimeBetweenLease, $"Instance {instance}: Wait time exceeds min wait time (actual: {timeSinceLastRequest}, min: {configuration.WaitTimeBetweenLease})");
                        }

                        Thread.Sleep(1000); // do some work

                        Log.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] Instance {instance}: completed work");
                    }

                    Log.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] Instance {instance}: released lease (threads: {throttle.ActiveThreads})");
                });
            }

            Log.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] set.....");
            awaiter.Set();
            Task.WaitAll(threads);
        }
Exemple #2
0
        public void Throttle_CanWaitBetweenRequests_TumblingWindow()
        {
            // No more than 2 requests per 5 seconds and only 1 concurrent thread.
            ThrottleConfiguration configuration = new ThrottleConfiguration
            {
                WaitTimeBetweenLease = TimeSpan.FromSeconds(5),
                WaitStrategy         = ThrottleWaitStrategy.TumblingWindow,
                MaxConcurrentThreads = 1,
                MaxRequests          = 2
            };

            Throttle throttle = new Throttle(configuration);

            Task[] threads = new Task[5];

            ManualResetEvent awaiter = new ManualResetEvent(false);

            for (int i = 0; i < threads.Length; i++)
            {
                int instance = i;
                threads[i] = Task.Run(() => {
                    awaiter.WaitOne();
                    Log.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] Instance {instance}: thread started");

                    using (throttle.AcquireLease())
                    {
                        TimeSpan?timeSinceLastRequest = DateTimeOffset.Now - throttle.LastFinishTime;

                        Log.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] Instance {instance}: acquired lease (window: {throttle.RateWindow?.DateTime:yyyy-MM-dd HH:mm:ss.fff}, threads: {throttle.ActiveThreads}, requests: {throttle.RequestCount})");

                        Assert.True(throttle.ActiveThreads <= configuration.MaxConcurrentThreads, $"Instance {instance}: Thread count exceeds max concurrent threads (actual: {throttle.ActiveThreads}, max: {configuration.MaxConcurrentThreads})");

                        Assert.True(throttle.RequestCount <= configuration.MaxRequests, $"Instance {instance}: Request count exceeds max request count (actual: {throttle.RequestCount}, max: {configuration.MaxRequests})");

                        Thread.Sleep(1000); // do some work

                        Log.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] Instance {instance}: completed work");
                    }

                    Log.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] Instance {instance}: released lease (threads: {throttle.ActiveThreads})");
                });
            }

            Log.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] set.....");
            awaiter.Set();
            Task.WaitAll(threads);
        }
Exemple #3
0
        public void Throttle_CanWaitBetweenRequests_FromStartOfLastRequest()
        {
            // no more than 1 thread per second from start of last request.
            ThrottleConfiguration configuration = new ThrottleConfiguration
            {
                WaitTimeBetweenLease = TimeSpan.FromSeconds(1),
                WaitStrategy         = ThrottleWaitStrategy.FromStartOfLastRequest
            };
            Throttle throttle = new Throttle(configuration);

            Task[] threads = new Task[5];

            ManualResetEvent awaiter = new ManualResetEvent(false);

            CancellationTokenSource outerCancellationSource = new CancellationTokenSource(12 * 1000); // 12 seconds

            DateTimeOffset?lastRequestTime = null;
            object         _lock           = new object();

            long success = 0;

            for (int i = 0; i < threads.Length; i++)
            {
                int       instance = i;
                Stopwatch sw       = new Stopwatch();
                sw.Start();
                threads[i] = Task.Run(() => {
                    awaiter.WaitOne();
                    Log.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] Instance {instance}: thread started");

                    using (throttle.AcquireLease())
                    {
                        TimeSpan?timeSinceLastRequest;
                        lock (_lock)
                        {
                            timeSinceLastRequest = DateTimeOffset.Now - lastRequestTime;

                            if (lastRequestTime == null || throttle.LastRequestTime > lastRequestTime)
                            {
                                lastRequestTime = throttle.LastRequestTime;
                            }
                        }

                        Log.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] Instance {instance}: aquired lease (threads: {throttle.ActiveThreads}, timeSinceLastRequest: {timeSinceLastRequest})");

                        Assert.True(throttle.ActiveThreads <= configuration.MaxConcurrentThreads, $"Instance {instance}: Thread count exceeds max concurrent threads (actual: {throttle.ActiveThreads}, max: {configuration.MaxConcurrentThreads})");

                        if (timeSinceLastRequest != null)
                        {
                            Assert.True(timeSinceLastRequest >= configuration.WaitTimeBetweenLease, $"Instance {instance}: Wait time exceeds min wait time (actual: {timeSinceLastRequest}, min: {configuration.WaitTimeBetweenLease})");
                        }

                        Thread.Sleep(1000); // do some work

                        long current = Interlocked.Increment(ref success);
                        Log.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] Instance {instance}: completed work");
                    }

                    Log.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] Instance {instance}: released lease (threads: {throttle.ActiveThreads})");
                });
            }

            Log.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] set.....");
            awaiter.Set();
            Task.WaitAll(threads, CancellationToken.None);

            long actual = Interlocked.Read(ref success);

            Assert.Equal(threads.Length, actual);
        }