Created
August 14, 2011 21:10
-
-
Save wcharczuk/1145315 to your computer and use it in GitHub Desktop.
Rate Limiter written in c#
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Web; | |
using System.Threading; | |
namespace YourNamespaceHere | |
{ | |
[Serializable()] | |
public class RateLimiter | |
{ | |
public RateLimiter(Int32 requests, TimeSpan interval) | |
{ | |
this.Requests = requests; | |
this.Interval = interval; | |
} | |
public Int32 Requests { get; set; } | |
public TimeSpan Interval { get; set; } | |
private ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); | |
private Dictionary<String, Queue<DateTime>> _internalStorage = new Dictionary<String, Queue<DateTime>>(); | |
public Boolean Process(String address) | |
{ | |
_lock.EnterUpgradeableReadLock(); | |
try | |
{ | |
if (!_internalStorage.ContainsKey(address)) | |
{ | |
_lock.EnterWriteLock(); | |
try | |
{ | |
_internalStorage.Add(address, new Queue<DateTime>()); | |
_internalStorage[address].Enqueue(DateTime.Now); | |
return true; | |
} | |
finally | |
{ | |
_lock.ExitWriteLock(); | |
} | |
} | |
else | |
{ | |
PurgeOldEntries(address); | |
_lock.EnterWriteLock(); | |
try | |
{ | |
_internalStorage[address].Enqueue(DateTime.Now); | |
return _internalStorage[address].Count <= Requests; | |
} | |
finally | |
{ | |
_lock.ExitWriteLock(); | |
} | |
} | |
} | |
finally | |
{ | |
_lock.ExitUpgradeableReadLock(); | |
} | |
} | |
private void PurgeOldEntries(String address) | |
{ | |
_lock.EnterWriteLock(); | |
try | |
{ | |
while (_internalStorage[address].Count > 0 && (DateTime.Now - _internalStorage[address].Peek() > Interval)) | |
{ | |
_internalStorage[address].Dequeue(); | |
} | |
} | |
finally | |
{ | |
_lock.ExitWriteLock(); | |
} | |
} | |
} | |
} |
Is there an example on how to use this? The following doesn't seem to work and the queue appears to just continue piling up.
static void Main()
{
var limiter = new RateLimiter(10, TimeSpan.FromSeconds(5));
var t = Task.Run(() =>
{
for (var i = 0; i < 100; i++)
{
while (!limiter.Process("foo"))
{
Task.Delay(1).Wait();
}
Console.WriteLine(i);
}
});
Task.WaitAll(t);
Console.ReadKey();
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
thx a lot!