假设您的网络应用中有一个 User
模型,并且您需要通过 API 使该用户与外部服务保持同步。因此,当您在本地创建用户时,您还需要远程创建它。
您的所有操作都在 transaction.atomic()
下,并且您尝试将所有第 3 方 API 调用保留在原子 block 之后,这是合理的。
但是,系统就是一个系统,它会变得越来越复杂,直到您在更新调用中删除一些非常难以删除的第 3 方调用。
也就是说,有没有办法扩展 Django 的事务机制,添加一些回调函数,例如 rollback.add_callback(clean_3rdparty_user(user_id=134))
?
这样我就可以保证采取所有必要的回滚操作并且我的系统保持同步?
最佳答案
Django事务钩子(Hook)代码的作者有this to say关于为什么有 on_commit()
但没有 on_rollback()
:
A rollback hook is even harder to implement robustly than a commit hook, since a variety of things can cause an implicit rollback. For instance, your database connection was dropped because your process was killed without a chance to shutdown gracefully: your rollback hook will never run.
由于回滚通常是由异常触发的,因此一种简单的方法是捕获任何异常并在那里运行撤消代码。
try:
with transaction.atomic():
# Do database stuff
# Do external stuff
except:
# We know the database stuff has rolled back, so...
# Undo external stuff
raise
这并不是特别优雅。我同意以下来自同一来源的观点:
The solution is simple: instead of doing something during the atomic block (transaction) and then undoing it if the transaction fails, use on_commit to delay doing it in the first place until after the transaction succeeds. It’s a lot easier to undo something you never did in the first place!
但听起来你也同意这一点。
关于Django 事务 : How to run extra code during rollback?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50222974/