Esempio n. 1
0
        public void ThrottledWorker_CanPreventConcurrentRequests()
        {
            // no more than 2 concurrent threads.
            ThrottleConfiguration configuration = new ThrottleConfiguration
            {
                MaxConcurrentThreads = 2
            };
            Throttle        throttle        = new Throttle(configuration);
            ThrottledWorker throttledWorker = new ThrottledWorker(throttle);

            ManualResetEvent        awaiter = new ManualResetEvent(false);
            CancellationTokenSource outerCancellationSource = new CancellationTokenSource(5 * 1000); // 5 seconds

            const long requestCount = 5;

            long success = 0;

            for (int i = 0; i < requestCount; i++)
            {
                int       instance = i;
                Stopwatch sw       = new Stopwatch();
                sw.Start();
                throttledWorker.Enqueue(async() => {
                    CancellationTokenSource innerCancellationSource = CancellationTokenSource.CreateLinkedTokenSource(
                        outerCancellationSource.Token,
                        new CancellationTokenSource(5 * 1000).Token  // 5 seconds
                        );
                    Log.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] Request {instance}: acquired lease (waitTime: {sw.Elapsed})");

                    sw.Restart();
                    awaiter.WaitOne();

                    await Task.Delay(1000, innerCancellationSource.Token); // do some work

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

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

                    long current = Interlocked.Increment(ref success);
                    Log.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] Request {instance}: thread complete (runTime: {sw.Elapsed}, success: {current})");
                });
            }

            Log.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] set.....");
            awaiter.Set();
            throttledWorker.Wait(outerCancellationSource.Token);
            Log.WriteLine($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] complete.....");
            long actual = Interlocked.Read(ref success);

            Assert.Equal(requestCount, actual);
        }
Esempio n. 2
0
        public void ThrottledWorker_CanWaitBetweenRequests_SlidingWindow()
        {
            // no more than 2 request per 1 second
            ThrottleConfiguration configuration = new ThrottleConfiguration
            {
                WaitTimeBetweenLease = TimeSpan.FromSeconds(1),
                WaitStrategy         = ThrottleWaitStrategy.SlidingWindow,
                MaxRequests          = 2,
                //RecursionStrategy = ThrottleRecursionStrategy.AllowsRecursion
            };

            Throttle        throttle        = new Throttle(configuration);
            ThrottledWorker throttledWorker = new ThrottledWorker(throttle);
            const int       requestCount    = 10;

            ManualResetEvent awaiter = new ManualResetEvent(false);

            for (int i = 0; i < requestCount; i++)
            {
                int instance = i;
                throttledWorker.Enqueue(() => {
                    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;

                        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}] set.....");
            awaiter.Set();
            throttledWorker.Wait();
        }
Esempio n. 3
0
        public void ThrottledWorker_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);
            ThrottledWorker throttledWorker = new ThrottledWorker(throttle);
            const int       requestCount    = 5;

            ManualResetEvent awaiter = new ManualResetEvent(false);

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

                    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}] set.....");
            awaiter.Set();
            throttledWorker.Wait();
        }
Esempio n. 4
0
        public void ThrottledWorker_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);
            ThrottledWorker throttledWorker = new ThrottledWorker(throttle);
            const int       requestCount    = 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 < requestCount; i++)
            {
                int       instance = i;
                Stopwatch sw       = new Stopwatch();
                sw.Start();
                throttledWorker.Enqueue(() =>
                {
                    awaiter.WaitOne();

                    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}] set.....");
            awaiter.Set();
            throttledWorker.Wait();

            long actual = Interlocked.Read(ref success);

            Assert.Equal(requestCount, actual);
        }