Google 数据存储事务异常
Google Datastore transaction exception
如 Google 数据存储文档中所述:
If your application receives an exception when committing a transaction, it does not always mean that the transaction failed. You can receive errors in cases where transactions have been committed.
除了更新事务内的实体外,我还将推送任务添加到推送队列。如果事务抛出异常,但确实提交成功,是否说明推送队列任务入队成功?
如果交易确实成功 - 即使它遇到异常 - 推送队列任务也应该正确入队。
根据您提到的文档 here,它说:
You can enqueue a task as part of a Datastore transaction, such that the task is only enqueued—and guaranteed to be enqueued—if the transaction is committed successfully. Tasks added in a transaction are considered to be a part of it and have the same level of isolation and consistency.
这意味着此推送将与交易的其余部分一起发生,使用与交易相同的功能和特性。这样,如果交易成功,您应该将您的任务正确排队。
如果有信息请告诉我
根据 gso_gabriel 中 post 的引述,答案似乎是肯定的。
不过我有些疑惑。事务性任务排队似乎是数据存储客户端库(ndb/your java 库)的一项功能——我不记得曾将其记录为通用数据存储(即服务器端)功能。
如果这是正确的,那么答案可能取决于实际的库实现。这就是我的疑虑所在——在某些情况下,客户无法从异常本身确定事务是否成功提交。例如,请参阅 app engine datastore transaction exception - 虽然答案还表明任务排队将在服务器端正确处理)。仍然可以确保使用额外的逻辑正确的任务排队,但同样 - 依赖于实现。
如果您想完全避免这种不确定性,我相信您有 2 个选择:
- 如果即使在这些不利条件下正确及时地入队很重要,您也可以尝试使用 task naming 作为使任务入队幂等的方法:即使异常不能指示任务是否已正确入队,重试不会有什么坏处,因为您不能(暂时)将一个命名任务入队两次。不过,您需要一种生成唯一任务名称的方法。
An advantage of assigning your own task names is that named tasks are
de-duplicated, which means you can use task names to guarantee that a
task is only added once. De-duplication continues for 9 days after the
task is completed or deleted.
- 如果执行任务的时间不是那么重要,则可以用不同的方式处理整个故事。例如,我已经安排了一些定期的高级完整性检查工作来寻找孤立的项目(不管它们存在的原因)。在我的例子中,错过任务排队的影响只是产生这种孤儿实体的一种方式。由于时间并不重要,而且遇到此类事件的可能性很低,因此甚至不必担心它们是可以接受的,保持简单并将恢复(重新尝试任务排队)留给这些完整性检查作业。
如 Google 数据存储文档中所述:
If your application receives an exception when committing a transaction, it does not always mean that the transaction failed. You can receive errors in cases where transactions have been committed.
除了更新事务内的实体外,我还将推送任务添加到推送队列。如果事务抛出异常,但确实提交成功,是否说明推送队列任务入队成功?
如果交易确实成功 - 即使它遇到异常 - 推送队列任务也应该正确入队。
根据您提到的文档 here,它说:
You can enqueue a task as part of a Datastore transaction, such that the task is only enqueued—and guaranteed to be enqueued—if the transaction is committed successfully. Tasks added in a transaction are considered to be a part of it and have the same level of isolation and consistency.
这意味着此推送将与交易的其余部分一起发生,使用与交易相同的功能和特性。这样,如果交易成功,您应该将您的任务正确排队。
如果有信息请告诉我
根据 gso_gabriel 中 post 的引述,答案似乎是肯定的。
不过我有些疑惑。事务性任务排队似乎是数据存储客户端库(ndb/your java 库)的一项功能——我不记得曾将其记录为通用数据存储(即服务器端)功能。
如果这是正确的,那么答案可能取决于实际的库实现。这就是我的疑虑所在——在某些情况下,客户无法从异常本身确定事务是否成功提交。例如,请参阅 app engine datastore transaction exception - 虽然答案还表明任务排队将在服务器端正确处理)。仍然可以确保使用额外的逻辑正确的任务排队,但同样 - 依赖于实现。
如果您想完全避免这种不确定性,我相信您有 2 个选择:
- 如果即使在这些不利条件下正确及时地入队很重要,您也可以尝试使用 task naming 作为使任务入队幂等的方法:即使异常不能指示任务是否已正确入队,重试不会有什么坏处,因为您不能(暂时)将一个命名任务入队两次。不过,您需要一种生成唯一任务名称的方法。
An advantage of assigning your own task names is that named tasks are de-duplicated, which means you can use task names to guarantee that a task is only added once. De-duplication continues for 9 days after the task is completed or deleted.
- 如果执行任务的时间不是那么重要,则可以用不同的方式处理整个故事。例如,我已经安排了一些定期的高级完整性检查工作来寻找孤立的项目(不管它们存在的原因)。在我的例子中,错过任务排队的影响只是产生这种孤儿实体的一种方式。由于时间并不重要,而且遇到此类事件的可能性很低,因此甚至不必担心它们是可以接受的,保持简单并将恢复(重新尝试任务排队)留给这些完整性检查作业。