views:

61

answers:

4

I have a design pattern I have been struggling with on how best to prevent duplicate posting of data.

Here are the steps:

  1. Client submits data with a unique guid (client generated guid - guaranteed unique)
  2. Server side software makes sure client guid doesn't exist yet in the DB
  3. begins transaction
  4. process data (can take between 1-20 seconds depending upon payload)
  5. commits transaction

Here are the scenarios: Client submits data with guid "1", and then resubmits data with guid "1" before step (5) is hit for the original data submission, then the transaction is processed twice.

What is the best design pattern to prevent this without using semaphores or blocking? The user should be able to resubmit, in case the first submission fails for some reason (hardware issue on the server side, etc.).

Thanks!

A: 

I don't know what you are using to develop your front end, but in a web application you can use ajax to check on the server transition status giving the user some feedback while waiting and also disabling the submit option.

redhatlab
This is coming disconnected from a mobile client. So, the issue is that the users network drops - thinking the transaction failed, so they resubmit.
Chris Mo
A: 

You could implement step 2 by using a query which reads uncommitted data. For instance, if you are using MS SQL Server, you could do this:

IF NOT EXIST(SELECT * FROM SomeTable (NOLOCK) WHERE Guid = @ClienGUID)
BEGIN
   -- Insert the GUID ASAP in the transaction so that the next query will read it
   -- Do steps 3-5
END

The key here is the (NOLOCK) hint, which reads uncommitted data

RyanHennig
But if it reads uncommitted data, and then the original transaction fails, then the user will be told it has already been processed incorrectly, right? i.e. in step 2 returns a response saying it has already been processed (to the second submission) - then the original submission fails on step 4.
Chris Mo
Not necessarily. The user can be told that they need to wait for the first transaction to finish before trying to submit again. After reading the accepted answer, I guess I assumed that he was asking for a way to prevent a second submission while the first is being processed; not to simply ensure it would fail if the first one has already been processed.
RyanHennig
A: 

Could you hash the data that the user is providing and store it in a table -- check that the hash doesn't match any previous submission before continuing?

sonnyrao
I guess you'd use the client guid with the hash to make sure there aren't any collisions between users
sonnyrao
I was thinking something along those lines, but then that makes it a non-sequential process. In other words, the process becomes:1. create hash and save2. check if hash exists3. check if submission id exists4. begin transaction5. process submission6. commit transactionWhat do I do if line 5 fails due to a disk drive failing? When do I clear out the hash table?
Chris Mo
If line 5 fails due to disk drive failing the whole transaction fails and step 6 simply never ocurrs, right? I'm not sure why you say it's non-sequential, could you explain that a little more
sonnyrao
Also, to answer when to clear the hash table -- you could timestamp the hash record, when the hashtable gets full clear out old records to make space for new ones
sonnyrao
Sonnyrao - thanks for responding - appreciate it.The problem is, if the hash from step 1 isn't in the transaction, then it won't roll back if the transaction isn't processed for some reason. If it is in the transaction, then it suffers from the exact same issue as the GUID I originally posted about (i.e. the thread handling the second submission wouldn't see the hash since its within a transaction that hasn't committed yet).
Chris Mo
A: 

Store the GUID in a column with an SQL UNIQUE constraint.

When you attempt (within the transaction) to insert a second duplicate GUID, the operation will fail, at which point you roll back the entire transaction.

David Gelhar