问题描述
这里的最新文档指出:
如果您的应用程序在提交事务时收到异常,并不总意味着事务失败,您可以收到DatastoreTimeoutException,ConcurrentModificationException,或DatastoreFailureException在事务已被提交并最终成功应用的情况下发生异常。只要有可能,使您的Datastore事务处于幂等状态,这样如果重复事务,最终结果将是相同的。
- 如何才能知道事务是否成功?
- 在收到ConcurrentModificationException之后要做什么?如何知道我是否必须重试?
- 您会如何建议制作支付交易幂等而不知道它是否成功?
几个注释:
-
正如文档所说 - 您无法确定是否应用了交易。这是问题的核心。
只有在出现所有例外的情况下才会回滚。查看此示例: -
使其具有幂等性 - 意思是说,如果您调用它两次,则无关紧要。在支付交易的情况下,您将创建支付交易实体。对于每一笔交易,您都会使用付款数据创建一个特殊实体并将其写入数据存储。这里的关键是从付款数据中生成一个自然ID:用户ID,来源账户,付款金额,目标账户,日期/小时/分钟。然后,如果交易重复,它将创建一个具有相同ID的支付交易实体,并将覆盖旧交易实体 - 这意味着如果只有一个或两个交易完成,结果将是相同的。 (然后通过一系列交易并将其添加到开户金额来计算用户账户的余额 - 这是银行在实践中实际做的AFAIK)。
- How is it possible to know if a transaction succeeded or not?
- What am I going to do after catching ConcurrentModificationException? How do I know if I have to retry?
- How would you recommend making, for example, payment transactions idempotent without any idea whether it was successful?
As docs say - you can not be sure if transaction was applied. That is the core of the problem.
Just rollback in case of all exceptions. See this example: http://code.google.com/appengine/docs/java/datastore/transactions.html#Isolation_and_Consistency
Make it idempotent - meaning if you invoke it twice, it does not matter. In the case of payment transactions, you make "payment transaction" entity. For every transaction you make a special entity with payment data and write it to datastore. The key here is to generate a natural ID from payment data: user ID, source account, payment amount, target account, date/hour/minute. Then if transaction is repeated, it will create a payment transaction entity with the same ID and will overwrite the old one - which means the result will be the same if only one or two transactions were completed. (The balance of the user account is then calculated by going through a series of transactions and adding it to the opening amount - this is what banks actually do in practice AFAIK).
ol>
The latest documentation here http://code.google.com/appengine/docs/java/datastore/transactions.html states:"If your app receives an exception when submitting a transaction, it does not always mean that the transaction failed. You can receive DatastoreTimeoutException, ConcurrentModificationException, or DatastoreFailureException exceptions in cases where transactions have been committed and eventually will be applied successfully. Whenever possible, make your Datastore transactions idempotent so that if you repeat a transaction, the end result will be the same."
Few notes:
这篇关于事务和ConcurrentModificationException文档含糊不清的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!