Example #1
0
        /* Updates the the cached item with an incremented call-count.
         * Returns whether our incremented count puts us over the limit for the token
         * If so, boolean indicates whether we should short-circuit our conputation and return early.
         */
        private bool CacheUpdate(ActionExecutingContext context, string id, LimitCounter oldCounter, string message)
        {
            LimitCounter updatedCounter = new LimitCounter(oldCounter.FirstCallTimestamp, oldCounter.Window, oldCounter.CallCount + 1, oldCounter.Limit);

            /* Cache will periodically prune itself, but if we happen to pull one that expired, we'll take care of it. */
            if (oldCounter.FirstCallTimestamp + oldCounter.Window <= DateTimeOffset.UtcNow)
            {
                Cache.Remove(id);
                return(false);
            }

            /* Due to the nature of distributed or off-site storage, limits may be incremented past their theoretical max.
             * We account for this with a greater than check, rather than a strict equals check */
            if (updatedCounter.CallCount > updatedCounter.Limit)
            {
                TimeSpan availableAt = (updatedCounter.FirstCallTimestamp + updatedCounter.Window) - DateTimeOffset.UtcNow;

                context.Result = new ContentResult {
                    Content = message
                };
                context.HttpContext.Response.StatusCode = 429; /* Too Many Requests */
                context.HttpContext.Response.Headers.Add("Retry-After", availableAt.TotalSeconds.ToString());
                return(true);
            }
            else
            {
                Cache.Set(id, updatedCounter, new MemoryCacheEntryOptions().SetAbsoluteExpiration(updatedCounter.FirstCallTimestamp + updatedCounter.Window));
                return(false);
            }
        }
        public void Increase_WhenLimitExceeds_ThrowsExceptionDuringWaitTime()
        {
            int nrOfRequests     = 1;
            int allowedTime      = 1;
            int secondsSuspended = 3;

            LimitCounter counter = new LimitCounter(nrOfRequests, TimeSpan.FromSeconds(allowedTime), TimeSpan.FromSeconds(secondsSuspended));

            counter.Increase();

            try
            {
                //t1 = DateTime.Now;
                counter.Increase();
                //t2 = DateTime.Now;
                Assert.Fail("Did not throw exception after exceeding limit");
            }
            catch (RateLimitExceededException)
            {
            }

            System.Threading.Thread.Sleep(1000);

            try
            {
                counter.Increase();
                Assert.Fail("Did not throw exception after 1 second of waiting");
            }
            catch (RateLimitExceededException)
            {
            }

            System.Threading.Thread.Sleep(1000);

            try
            {
                counter.Increase();
                Assert.Fail("Did not throw exception after 2 seconds of waiting");
            }
            catch (RateLimitExceededException)
            {
            }

            System.Threading.Thread.Sleep(985);

            try
            {
                //t3 = DateTime.Now;
                counter.Increase();
                Assert.Fail("Did not throw exception after 3 seconds of waiting");
            }
            catch (RateLimitExceededException)
            {
            }
        }
Example #3
0
        public virtual void CountAvailabilityCheck(DispatcherAvailability availability)
        {
            if (availability == DispatcherAvailability.NotChecked)
            {
                return;
            }

            //count check as additional message dispatched
            AvailableLimitCapacity--;
            LimitCounter.InsertTime();
        }
        public void Increase_WhenLimitDidNotExceed_AllowsAfterAllowedTime()
        {
            int nrOfRequests     = 2;
            int allowedTime      = 1;
            int secondsSuspended = 5;

            LimitCounter counter = new LimitCounter(nrOfRequests, TimeSpan.FromSeconds(allowedTime), TimeSpan.FromSeconds(secondsSuspended));

            counter.Increase();
            counter.Increase();

            System.Threading.Thread.Sleep(1000);

            counter.Increase();
        }
Example #5
0
        static void TestLimitCounter()
        {
            int nrOfRequests     = 90000;
            int allowedTime      = 100;
            int secondsSuspended = 1;

            LimitCounter counter = new LimitCounter(nrOfRequests, TimeSpan.FromSeconds(allowedTime), TimeSpan.FromSeconds(secondsSuspended));

            List <System.Threading.Thread> threads = new List <System.Threading.Thread>();


            for (int x = 0; x < 100; ++x)
            {
                var thread = new System.Threading.Thread(() =>
                {
                    var id = System.Threading.Thread.CurrentThread.ManagedThreadId;
                    for (int y = 0; y < 1000; ++y)
                    {
                        try
                        {
                            counter.Increase();
                            Console.WriteLine(String.Format("T-{0}-{1}", id, y));
                        }
                        catch (RateLimitExceededException e)
                        {
                            Console.WriteLine(String.Format("E{0}-{1}-{2}", id, y, e.Message));
                            System.Threading.Thread.Sleep(1000);
                        }


                        System.Threading.Thread.Yield();
                    }
                });

                threads.Add(thread);
            }
            Console.WriteLine("Starting...");
            foreach (var t in threads)
            {
                t.Start();
            }

            while (threads.TrueForAll(p => p.IsAlive == false))
            {
                System.Threading.Thread.Yield();
                System.Threading.Thread.Sleep(1000);
            }
        }
Example #6
0
 //limitation methods
 public virtual void CountSendAttempt(SignalDispatch <TKey> dispatch,
                                      ProcessingResult result, DispatcherAvailability availability)
 {
     if (result == ProcessingResult.Success)
     {
         AvailableLimitCapacity--;
         LimitCounter.InsertTime();
         Interrupter.Success(dispatch);
     }
     else if (result == ProcessingResult.Fail)
     {
         AvailableLimitCapacity--;
         LimitCounter.InsertTime();
         Interrupter.Fail(dispatch, availability);
     }
 }
Example #7
0
    void UseLimitCounter()
    {
        LimitCounter limitCounter = new LimitCounter();

        limitCounter.SetLimit(3);
        Debug.Log("at limit: " + limitCounter.AtLimit());
        // "at limit: False"
        limitCounter.IncrementCounter();//already implemented in BaseLimitCounter
        // "Counter: 1"
        limitCounter.IncrementCounter();
        // "Counter: 2"
        limitCounter.IncrementCounter();
        // "Counter: 3"
        Debug.Log("at limit: " + limitCounter.AtLimit());
        // "at limit: True"
    }
Example #8
0
        //IDisposable
        public virtual void Dispose()
        {
            if (Dispatcher != null)
            {
                Dispatcher.Dispose();
            }

            if (LimitCounter != null)
            {
                LimitCounter.Dispose();
            }

            if (Interrupter != null)
            {
                Interrupter.Dispose();
            }
        }
Example #9
0
        /* Inserts the limit as a LimitCounter struct tied to the given id, and expiring when the Window lapses.
         * The boolean returned indictes whether this item was whitelisted, and therefore if we should
         * short-circuit our computation and return early.
         */
        private bool InsertLimit(string id, RateLimit limit)
        {
            DateTimeOffset now = DateTimeOffset.UtcNow;

            /* Nulls in these spots mean this item is whitelisted. Add it to our whitelist. */
            if (limit.Window == null || limit.Limit == null)
            {
                /* White-listing lasts one hour, so that if whitelisting status changes, server won't require a restart to clear the cache. */
                WhiteList.Set(id, true, new MemoryCacheEntryOptions().SetAbsoluteExpiration(TimeSpan.FromHours(1)));
                return(true);
            }
            else
            {
                LimitCounter counter = new LimitCounter(now, limit.Window.Value, 1, limit.Limit);
                Cache.Set(id, counter, new MemoryCacheEntryOptions().SetAbsoluteExpiration(limit.Window.Value)); // Passed a null check above, value exists
                return(false);
            }
        }
        public void Increase_WhenLimitExceeds_ThrowsException()
        {
            int nrOfRequests     = 1;
            int allowedTime      = 1;
            int secondsSuspended = 5;

            LimitCounter counter = new LimitCounter(nrOfRequests, TimeSpan.FromSeconds(allowedTime), TimeSpan.FromSeconds(secondsSuspended));

            counter.Increase();

            try
            {
                counter.Increase();
                Assert.Fail("Did not throw exception");
            }
            catch (RateLimitExceededException)
            {
            }
        }
        public void Increase_WhenLimitExceeds_AllowsAfterWaitTime()
        {
            int nrOfRequests     = 1;
            int allowedTime      = 1;
            int secondsSuspended = 2;

            LimitCounter counter = new LimitCounter(nrOfRequests, TimeSpan.FromSeconds(allowedTime), TimeSpan.FromSeconds(secondsSuspended));

            counter.Increase();
            try
            {
                counter.Increase();
                Assert.Fail("Did not throw first time");
            }
            catch (RateLimitExceededException)
            {
            }

            System.Threading.Thread.Sleep(2000);

            counter.Increase();
        }
Example #12
0
                    /// <summary>
                    /// Create Get Log state reply object
                    /// </summary>
                    /// <param name="reply">Raw 9 or 21-bit Get Log State reply</param>
                    public LogState(byte[] reply)
                    {
                        if (!((9 == reply.Length) || (20 == reply.Length)))
                        {
                            throw new ArgumentOutOfRangeException("GetLogState replies must be 9 or 20 bytes in length");
                        }
                        int offset = 0;
                        _LimitCount = new LimitCounter(reply, offset); offset += 4;
                        _SystemStat = new SystemStatus(reply, offset); offset += 4;
                        
                        if (20 == reply.Length)
                        {   
                            _SetShelLifeBlock0 = new ShelfLifeBlock0(reply, offset);
                            offset += 4;
                            _SetShelLifeBlock1 = new ShelfLifeBlock1(reply, offset);
                             offset += 4;
                             _remainingShelfLife = GetRemainingShelfLife(reply, offset);
                            offset += 3;
                        }

                        _StatFlags = new StatusFlags(reply[offset]); offset += 1;
                    }
Example #13
0
 public virtual void SetRestrictionsDuration()
 {
     _nextLimitsEndUtc  = LimitCounter.GetLimitsEndTimeUtc();
     _nextTimeoutEndUtc = Interrupter.GetTimeoutEndUtc();
 }
Example #14
0
 public virtual void SetLimitsCapacity()
 {
     AvailableLimitCapacity = LimitCounter.GetLimitCapacity();
 }