If it makes you feel better, Bank Of America doesn't seem to have solved
this, "auto-paid" my car payment 3 times this month because of an error and
mailed off 3 checks to Capital One.
 
The solution to all of these problems could be what B Of A does, bounce one
of the transaction, then send the user a bill for $35 * 10 for the $2.10
transactions from Google. 
 
PS 
If you solve this issue, please make the solution open source so B of A can
use it. 
 
PSS
It'd be awesome if we could get consolidated Monthly billing for GAE for
less than $500  a month J
 
 
From: [email protected]
[mailto:[email protected]] On Behalf Of AndyD
Sent: Saturday, January 21, 2012 3:08 PM
To: [email protected]
Subject: Re: [google-appengine] Re: Once-only transactions
 
Yes, I see what you're saying.  But in looking at both your and Robert's
approaches, I still have questions.
 
Jeff, how does your approach avoid executing the operation twice?  Let's say
there's a web page with a submit button that triggers the process, and the
user clicks that button twice.  The algorithm you outlined...
 
Create TxnID entity instance
Repeat until success {
 * start txn
 * load TxnID (if null, return success immediately)
 * debit $5 from AccountA
 * credit $5 to AccountB
 * delete TxnID
 * commit txn
} 
 
...if run serially, would do the operation twice, wouldn't it?  The first
execution would create the TxnID entity, then in the loop, it would load
that entity successfully, perform the operation, then delete the TxnID
entity.  Then, when the 2nd button click is handled, the operation would be
be performed again.
 
Robert, I didn't quite follow your algorithm.  Does your marker indicate
that the operation has not yet been performed?  If so, shouldn't 2b say "if
the marker is not found, abort?  Also, is there an implied retry mechanism
(e.g. a task) encompassing step 2?
 
It seems to me there are multiple challenges:
1) eliminate the potential of concurrency
2) retry on failure
3) only do the operation once
 
If we don't eliminate concurrency, then two parallel threads, in the same or
different instances, could find the operation not yet completed and both
perform it.   If we don't indicate (by the presence or absence of a marker)
that the operation has been completed, then two serial executions would both
perform it.  And if we don't have a retry mechanism, there is a risk that
the operation won't be performed at all. 
 
It still seems to me that the task queue approach addresses 1 (by not
dequeing a task to two handlers simultaneously and also not accepting a
duplicate task into the queue) and 2 (by automatically retrying on failure),
but as Jeff pointed out, not 3.  If you add an "operation not performed yet"
marker entity to the picture that gets deleted in the same transaction as
the run-once operation, does that cover all the bases? 
 
Just to make it interesting, what if the operation to be performed once was
not a datastore operation?  What if it was a call to an external system
(like a credit card processing service)?  You could successfully make the
external call, but fail to write the "operation complete" entity.
 
-Andy
-- 
You received this message because you are subscribed to the Google Groups
"Google App Engine" group.
To view this discussion on the web visit
https://groups.google.com/d/msg/google-appengine/-/YU3N7fnt8rAJ.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/google-appengine?hl=en.

-- 
You received this message because you are subscribed to the Google Groups 
"Google App Engine" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/google-appengine?hl=en.

Reply via email to