Skip to content
This repository was archived by the owner on Nov 1, 2023. It is now read-only.

Ensuring thread safety

Compare
Choose a tag to compare
@stefanprodan stefanprodan released this 10 Dec 16:01
· 143 commits to master since this release

In order to ensure thread safety, the ThrottleCounter object is now of type struct and all CRUD operations are done with locking.

static readonly object _processLocker = new object();
private ThrottleCounter ProcessRequest(
    ThrottlePolicy throttlePolicy, 
    RequestIndentity throttleEntry, 
    TimeSpan timeSpan, 
    RateLimitPeriod period, out string id)
{
    var throttleCounter = new ThrottleCounter();
    throttleCounter.Timestamp = DateTime.UtcNow;
    throttleCounter.TotalRequests = 1;

    id = "throttle";

    //computed request unique id from IP, client key, url and period

    //get the hash value of the computed id
    var hashId = ComputeHash(id);

    //serial reads and writes
    lock (_processLocker)
    {
        var entry = Repository.FirstOrDefault(hashId);
        if (entry.HasValue)
        {
            //entry has not expired
            if (entry.Value.Timestamp + timeSpan >= DateTime.UtcNow)
            {
                //increment request count
                var totalRequests = entry.Value.TotalRequests + 1;

                //deep copy
                throttleCounter = new ThrottleCounter
                {
                    Timestamp = entry.Value.Timestamp,
                    TotalRequests = totalRequests
                };
            }
        }

        //stores: id (string) - timestamp (datetime) - total (long)
        Repository.Save(hashId, throttleCounter, timeSpan);
    }

    return throttleCounter;
}