ValueError: Failed to commit transaction in 5 attempts
ValueError: Failed to commit transaction in 5 attempts
TL;DR 事务未按预期更新计数器
场景:
我有名为 projects
和 activities
的子集。
项目集合用于存储有关任何正在进行的项目的信息,活动集合用作对项目集合中发生的任何更改的审计跟踪。
我编写了一个触发活动集合的云函数 on create event
。在活动集合中创建文档后,我需要在项目子集合中由 projectId
标识的文档中更新名为 activityCount
的计数器。
云函数(部分删减)如下:
@firestore.transactional
def update_activity_count_in_transaction(transaction, activity):
"""
updates the activity count for a project
"""
try:
# get the project details of associated project at home/{orgId}/projects/{projectId}
project = activity.project.doc_ref.get(transaction=transaction)
# get the activity count from the transactional snapshot
activity_count = project.get(FireBaseConfig.ACTIVITY_COUNT)
# increment the counter using transaction
transaction.update(activity.project.doc_ref, {FireBaseConfig.ACTIVITY_COUNT: activity_count + 1})
except KeyError as err:
print(err)
# create activityCount key if not present in projects collection and increment the counter using transaction
transaction.update(activity.project.doc_ref, {FireBaseConfig.ACTIVITY_COUNT: 1})
print('transaction success')
return True
def activity_on_create(event, context):
"""
update the activity count in projects sub collection
This is invoked on create event at home/{orgId}/activities/{activityId}
"""
# parse the event data received from cloud functions into a FireStoreActivity object
activity = FireStoreActivity(event, context)
try:
if not activity.project.id:
print('no project id')
return True
# get firestore transaction object
# activity.transaction() is equivalent to firestore.client().transaction()
transaction = activity.transaction()
# update the counter using transaction
update_activity_count_in_transaction(transaction, activity)
except Exception as err:
pass
return True
执行时出现以下错误:
ValueError: Failed to commit transaction in 5 attempts
回溯:
File "/env/local/lib/python3.7/site-packages/google/cloud/functions/worker.py", line 333, in run_background_function
_function_handler.invoke_user_function(event_object)
File "/env/local/lib/python3.7/site-packages/google/cloud/functions/worker.py", line 199, in invoke_user_function
return call_user_function(request_or_event)
File "/env/local/lib/python3.7/site-packages/google/cloud/functions/worker.py", line 196, in call_user_function
event_context.Context(**request_or_event.context))
File "/user_code/main.py", line 149, in activity_on_create
raise err
File "/user_code/main.py", line 146, in activity_on_create
update_activity_count_in_transaction(transaction, activity)
File "/env/local/lib/python3.7/site-packages/google/cloud/firestore_v1beta1/transaction.py", line 327, in __call__
raise ValueError(msg)
ValueError: Failed to commit transaction in 5 attempts.
Note: This error occurs randomly and not all the time. But it does occur.
知道这里可能出了什么问题吗?
当事务由于对同一目标文档的大量并发写入而无法提交时,Firestore 客户端将在放弃之前重试事务最多 N
次。对于 Python Firestore 客户端,默认情况下为 N = 5
。您可以通过将 max_attempts
参数传递给 client.transaction()
方法调用来控制此参数。
TL;DR 事务未按预期更新计数器
场景:
我有名为 projects
和 activities
的子集。
项目集合用于存储有关任何正在进行的项目的信息,活动集合用作对项目集合中发生的任何更改的审计跟踪。
我编写了一个触发活动集合的云函数 on create event
。在活动集合中创建文档后,我需要在项目子集合中由 projectId
标识的文档中更新名为 activityCount
的计数器。
云函数(部分删减)如下:
@firestore.transactional
def update_activity_count_in_transaction(transaction, activity):
"""
updates the activity count for a project
"""
try:
# get the project details of associated project at home/{orgId}/projects/{projectId}
project = activity.project.doc_ref.get(transaction=transaction)
# get the activity count from the transactional snapshot
activity_count = project.get(FireBaseConfig.ACTIVITY_COUNT)
# increment the counter using transaction
transaction.update(activity.project.doc_ref, {FireBaseConfig.ACTIVITY_COUNT: activity_count + 1})
except KeyError as err:
print(err)
# create activityCount key if not present in projects collection and increment the counter using transaction
transaction.update(activity.project.doc_ref, {FireBaseConfig.ACTIVITY_COUNT: 1})
print('transaction success')
return True
def activity_on_create(event, context):
"""
update the activity count in projects sub collection
This is invoked on create event at home/{orgId}/activities/{activityId}
"""
# parse the event data received from cloud functions into a FireStoreActivity object
activity = FireStoreActivity(event, context)
try:
if not activity.project.id:
print('no project id')
return True
# get firestore transaction object
# activity.transaction() is equivalent to firestore.client().transaction()
transaction = activity.transaction()
# update the counter using transaction
update_activity_count_in_transaction(transaction, activity)
except Exception as err:
pass
return True
执行时出现以下错误:
ValueError: Failed to commit transaction in 5 attempts
回溯:
File "/env/local/lib/python3.7/site-packages/google/cloud/functions/worker.py", line 333, in run_background_function
_function_handler.invoke_user_function(event_object)
File "/env/local/lib/python3.7/site-packages/google/cloud/functions/worker.py", line 199, in invoke_user_function
return call_user_function(request_or_event)
File "/env/local/lib/python3.7/site-packages/google/cloud/functions/worker.py", line 196, in call_user_function
event_context.Context(**request_or_event.context))
File "/user_code/main.py", line 149, in activity_on_create
raise err
File "/user_code/main.py", line 146, in activity_on_create
update_activity_count_in_transaction(transaction, activity)
File "/env/local/lib/python3.7/site-packages/google/cloud/firestore_v1beta1/transaction.py", line 327, in __call__
raise ValueError(msg)
ValueError: Failed to commit transaction in 5 attempts.
Note: This error occurs randomly and not all the time. But it does occur.
知道这里可能出了什么问题吗?
当事务由于对同一目标文档的大量并发写入而无法提交时,Firestore 客户端将在放弃之前重试事务最多 N
次。对于 Python Firestore 客户端,默认情况下为 N = 5
。您可以通过将 max_attempts
参数传递给 client.transaction()
方法调用来控制此参数。