''' <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
views:
83answers:
2I 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
2010-04-29 13:42:24
@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
2010-04-29 13:59:56
+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
2010-04-29 13:36:58