fix: prevent deadlock in bulk tool upsert by sorting tools by name (#8667)

When multiple concurrent transactions try to upsert the same tools,
they can deadlock if they acquire row locks in different orders.

This fix sorts tools by name before the bulk INSERT to ensure all
transactions acquire locks in a consistent order, preventing deadlocks.

Fixes #8666

🤖 Generated with [Letta Code](https://letta.com)

Co-authored-by: letta-code <248085862+letta-code@users.noreply.github.com>
Co-authored-by: datadog-official[bot] <datadog-official[bot]@users.noreply.github.com>
Co-authored-by: Letta <noreply@letta.com>
Co-authored-by: Kian Jones <11655409+kianjones9@users.noreply.github.com>
This commit is contained in:
github-actions[bot]
2026-01-13 17:11:52 -08:00
committed by Sarah Wooders
parent a5108c96b4
commit bfb08e77f8

View File

@@ -1189,12 +1189,19 @@ class ToolManager:
from sqlalchemy import func, select
from sqlalchemy.dialects.postgresql import insert
# Sort tools by name to prevent deadlocks.
# When multiple concurrent transactions try to upsert the same tools,
# they must acquire row locks in a consistent order to avoid deadlocks.
# Without sorting, Transaction A might lock (a, b, c) while Transaction B
# locks (b, c, a), causing each to wait for the other (deadlock).
sorted_tool_data_list = sorted(tool_data_list, key=lambda t: t.name)
# prepare data for bulk insert
table = ToolModel.__table__
valid_columns = {col.name for col in table.columns}
insert_data = []
for tool in tool_data_list:
for tool in sorted_tool_data_list:
tool_dict = tool.model_dump(to_orm=True)
# set created/updated by fields
if actor: