如何在 Django 或 DRF 中实现这样的自定义回滚?
How to implement such a custom rollback in Django or DRF?
out系统访问一个中间平台(英文不知道怎么说,我们中文叫中台
),做登录,JWT
验证等认证,等等
然后,当由于意外的程序错误而需要回滚操作时,我们遇到了问题。如下代码,当运行在1 / 0
时程序会崩溃,然后AdminPermission.objects.create
可以回滚,但是do_user_actions
不能回滚,因为它是一个RPC函数。所以,我们需要覆盖 transaction.atomic 或类似的东西来实现我们的要求。但是,我不知道如何实施它。请给我一些建议或示例代码。非常感谢。
@transaction.atomic # can not rollback remote func call `do_user_actions`
def create(self, request, *args, **kwargs):
# call a remote func here to create a admin account.
user_dict = do_user_actions(query_kwargs=query_kwargs, action='create-admin')
user_id = user_dict.get('id')
permission_code = 'base_permission'
AdminPermission.objects.create(user_id=user_id, permission_code=permission_code)
# some unexpected errors, like:
1 / 0
return Response('success')
您可以将装饰器用作上下文管理器,而不是将 atomic
与装饰器一起使用,就像这样,
with transaction.atomic():
try:
# do your stuff
user_dict = do_user_actions(query_kwargs=query_kwargs, action='create-admin')
user_id = user_dict.get('id')
permission_code = 'base_permission'
AdminPermission.objects.create(user_id=user_id, permission_code=permission_code)
1/0 # error
except SomeError: # capture error
revert_user_actions() # revert do_user_actions
transaction.set_rollback(True) # rollback
return Response(status=status.HTTP_424_FAILED_DEPENDENCY) # failure
return Response(serializer.data, status=status.HTTP_201_CREATED) # success
更新
正如@Gorgine 在评论中提到的,文档不建议处理 atomic
中的错误。因为遵循建议总是一个好主意,所以您可以将 atomic
放在 try
块中。在这种情况下,如果发生错误,atomic
块将处理回滚,因此您需要在 except
块中处理 atomic
未回滚的操作。像这样:
try:
with transaction.atomic():
# do your stuff
user_dict = do_user_actions(query_kwargs=query_kwargs, action='create-admin')
user_id = user_dict.get('id')
permission_code = 'base_permission'
AdminPermission.objects.create(user_id=user_id, permission_code=permission_code)
1/0 # error
except SomeError: # capture error
revert_user_actions() # revert do_user_actions
return Response(status=status.HTTP_424_FAILED_DEPENDENCY) # failure
return Response(serializer.data, status=status.HTTP_201_CREATED) # success
out系统访问一个中间平台(英文不知道怎么说,我们中文叫中台
),做登录,JWT
验证等认证,等等
然后,当由于意外的程序错误而需要回滚操作时,我们遇到了问题。如下代码,当运行在1 / 0
时程序会崩溃,然后AdminPermission.objects.create
可以回滚,但是do_user_actions
不能回滚,因为它是一个RPC函数。所以,我们需要覆盖 transaction.atomic 或类似的东西来实现我们的要求。但是,我不知道如何实施它。请给我一些建议或示例代码。非常感谢。
@transaction.atomic # can not rollback remote func call `do_user_actions`
def create(self, request, *args, **kwargs):
# call a remote func here to create a admin account.
user_dict = do_user_actions(query_kwargs=query_kwargs, action='create-admin')
user_id = user_dict.get('id')
permission_code = 'base_permission'
AdminPermission.objects.create(user_id=user_id, permission_code=permission_code)
# some unexpected errors, like:
1 / 0
return Response('success')
您可以将装饰器用作上下文管理器,而不是将 atomic
与装饰器一起使用,就像这样,
with transaction.atomic():
try:
# do your stuff
user_dict = do_user_actions(query_kwargs=query_kwargs, action='create-admin')
user_id = user_dict.get('id')
permission_code = 'base_permission'
AdminPermission.objects.create(user_id=user_id, permission_code=permission_code)
1/0 # error
except SomeError: # capture error
revert_user_actions() # revert do_user_actions
transaction.set_rollback(True) # rollback
return Response(status=status.HTTP_424_FAILED_DEPENDENCY) # failure
return Response(serializer.data, status=status.HTTP_201_CREATED) # success
更新
正如@Gorgine 在评论中提到的,文档不建议处理 atomic
中的错误。因为遵循建议总是一个好主意,所以您可以将 atomic
放在 try
块中。在这种情况下,如果发生错误,atomic
块将处理回滚,因此您需要在 except
块中处理 atomic
未回滚的操作。像这样:
try:
with transaction.atomic():
# do your stuff
user_dict = do_user_actions(query_kwargs=query_kwargs, action='create-admin')
user_id = user_dict.get('id')
permission_code = 'base_permission'
AdminPermission.objects.create(user_id=user_id, permission_code=permission_code)
1/0 # error
except SomeError: # capture error
revert_user_actions() # revert do_user_actions
return Response(status=status.HTTP_424_FAILED_DEPENDENCY) # failure
return Response(serializer.data, status=status.HTTP_201_CREATED) # success