tags:

views:

83

answers:

2
''' <summary>
''' Returns true if a submission by the same IP address has not been submitted in the past n minutes.     
'' </summary>
Protected Function EnforceMinTimeBetweenSubmissions(ByVal minTimeBetweenRequestsMinutes  as Integer) As Boolean       
    If minTimeBetweenRequestsMinutes = 0 Then
        Return True
    End If
    If Cache("submitted-requests") Is Nothing Then            
        Cache("submitted-requests") = New Dictionary(Of String, Date)
    End If
    ' Remove old requests. '
    Dim submittedRequests As Dictionary(Of String, Date) = CType(Cache("submitted-requests"), Dictionary(Of String, Date))
    Dim itemsToRemove = submittedRequests.Where(Function(s) s.Value < Now).Select(Function(s) s.Key).ToList
    For Each key As String In itemsToRemove
        submittedRequests.Remove(key)
    Next
    If submittedRequests.ContainsKey(Request.UserHostAddress) Then
        ' User has submitted a request in the past n minutes. '
        Return False
    Else            
        submittedRequests.Add(Request.UserHostAddress, Now.AddMinutes(minTimeBetweenRequestsMinutes))
    End If
    Return True
End Function
+3  A: 
Justin Niessner
I don't know. Without locking that entire method I can envision some pretty strange sequencing of events. Imagine two thread that both see Cache("submitted-request") as Nothing. They both create new dictionaries and the race is on to write it to the Cache. I am afraid there might be a subtle bug that causes the code to incorrectly identify if a user has a previously submitted request. I would have to trace things out in detail, but a quick glace makes me suspicious.
Brian Gideon
@Brian Gideon - That situation could easily be handled by a double check (checking to see if the cache object is null outside the lock, and then again inside the lock).
Justin Niessner
+1  A: 

The System.Web.Caching.Cache class is thread-safe according to the MSDN documenation. However, the documenation also shows an example where a read and a write are performed on the cache without locking. That cannot possibily be thread-safe since the write is dependent on the read. The code you posted basically looks like the example. I definitely recommend putting a lock around the entire method.

Brian Gideon