feat: delete ps node #20

Open
ivan.dev wants to merge 6 commits from VORKOUT-29 into master
10 changed files with 419 additions and 24 deletions
Showing only changes of commit 43e6053c6d - Show all commits

View File

@@ -129,66 +129,52 @@ async def get_nodes_for_deletion_ordered(connection: AsyncConnection, node_id: i
return ordered_node_ids
async def delete_ps_node_by_id_CASCADE(connection: AsyncConnection, node_id: int) -> tuple[bool, str]:
"""
Полностью удаляет узел из базы данных по ID - ON DELETE CASCADE.
"""
try:
node_query = select(ps_node_table).where(ps_node_table.c.id == node_id)
node_result = await connection.execute(node_query)
node_data = node_result.mappings().first()
if not node_data:
return False, "Node not found"
ps_id = node_data["ps_id"]
await remove_node_from_process_schema_settings(connection, ps_id, node_id)
result = await connection.execute(delete(ps_node_table).where(ps_node_table.c.id == node_id))
if result.rowcount > 0:
await connection.commit()
return True, "Success"
else:
await connection.rollback()
return False, "Node not found"
except Exception as e:
await connection.rollback()
return False, str(e)
async def delete_ps_nodes_delete_handler(connection: AsyncConnection, node_ids: List[int]) -> List[int]:
"""
Поочередно удаляет узлы из базы данных.
Возвращает список успешно удаленных ID узлов.
Очищает settings и удаляет ноды для каждого ps_id.
Возвращает список успешно удаленных ID нод.
"""
successfully_deleted = []
if not node_ids:
return []
for node_id in node_ids:
success, error_message = await delete_ps_node_by_id_CASCADE(connection, node_id)
if success:
successfully_deleted.append(node_id)
ps_id_rows = await connection.execute(
select(ps_node_table.c.id, ps_node_table.c.ps_id).where(ps_node_table.c.id.in_(node_ids))
)
rows = ps_id_rows.mappings().all()
if not rows:
return []
ps_to_node_ids = {}
for r in rows:
ps_to_node_ids.setdefault(r["ps_id"], []).append(r["id"])
deleted_all = []
for ps_id, ids_in_ps in ps_to_node_ids.items():
await remove_nodes_from_process_schema_settings(connection, ps_id, ids_in_ps)
result = await connection.execute(delete(ps_node_table).where(ps_node_table.c.id.in_(ids_in_ps)))
if result.rowcount and result.rowcount > 0:
deleted_all.extend(ids_in_ps)
else:
raise Exception(f"Failed to delete node {node_id}: {error_message}")
return successfully_deleted
raise Exception(f"Failed to delete nodes for ps_id={ps_id}")
await connection.commit()
return deleted_all
async def remove_node_from_process_schema_settings(connection: AsyncConnection, ps_id: int, node_id: int):
async def remove_nodes_from_process_schema_settings(connection: AsyncConnection, ps_id: int, node_ids: List[int]):
"""
Удаляет ноду из поля settings в таблице process_schema.
Удаляет ноды из поля settings в таблице process_schema по списку node_ids.
"""
from api.db.logic.process_schema import get_process_schema_by_id
process_schema = await get_process_schema_by_id(connection, ps_id)
if not process_schema or not process_schema.settings:
return
settings = process_schema.settings
if "nodes" in settings and isinstance(settings["nodes"], list):
node_ids_set = set(node_ids)
settings["nodes"] = [
node_item
for node_item in settings["nodes"]
@@ -196,7 +182,7 @@ async def remove_node_from_process_schema_settings(connection: AsyncConnection,
isinstance(node_item, dict)
and "node" in node_item
and isinstance(node_item["node"], dict)
and node_item["node"].get("id") == node_id
and node_item["node"].get("id") in node_ids_set
)
ivan.dev marked this conversation as resolved
Review

Ну и здесь на каждый id будет по несколько отдельных запросов. Неэффективно.

Ну и здесь на каждый id будет по несколько отдельных запросов. Неэффективно.
]