@@ -182,7 +182,7 @@ async def create_node(self, db: AsyncSession, new_node: NodeCreate, admin: Admin
182182
183183 try :
184184 await node_manager .update_node (db_node )
185- asyncio .create_task (self .connect_node_wrapper (db , db_node .id ))
185+ asyncio .create_task (self .connect_single_node (db , db_node .id ))
186186 except NodeAPIError as e :
187187 await self ._update_single_node_status (db , db_node .id , NodeStatus .error , message = e .detail )
188188
@@ -211,7 +211,7 @@ async def modify_node(
211211 else :
212212 try :
213213 await node_manager .update_node (db_node )
214- asyncio .create_task (self .connect_node_wrapper (db , db_node .id ))
214+ asyncio .create_task (self .connect_single_node (db , db_node .id ))
215215 except NodeAPIError as e :
216216 await self ._update_single_node_status (db , db_node .id , NodeStatus .error , message = e .detail )
217217
@@ -306,9 +306,12 @@ async def connect_single(node: Node) -> dict | None:
306306 elif notif ["status" ] == NodeStatus .error and notif ["old_status" ] != NodeStatus .error :
307307 asyncio .create_task (notification .error_node (notif ["node" ]))
308308
309- async def connect_node_wrapper (self , db : AsyncSession , node_id : int ) -> None :
309+ async def connect_single_node (self , db : AsyncSession , node_id : int ) -> None :
310310 """
311- Connect single node by wrapping it in a list for bulk operation.
311+ Connect a single node and update its status (optimized for single-node operations).
312+
313+ Uses simple UPDATE statement instead of bulk update to avoid deadlock risks
314+ and unnecessary complexity.
312315
313316 Args:
314317 db (AsyncSession): Database session.
@@ -318,10 +321,65 @@ async def connect_node_wrapper(self, db: AsyncSession, node_id: int) -> None:
318321 if db_node is None :
319322 return
320323
321- await self .connect_nodes_bulk (db , [db_node ])
324+ # Get core users once
325+ users = await core_users (db = db )
326+
327+ # Update node manager
328+ try :
329+ await node_manager .update_node (db_node )
330+ except NodeAPIError as e :
331+ # Update status to error using simple CRUD
332+ await update_node_status (
333+ db = db ,
334+ db_node = db_node ,
335+ status = NodeStatus .error ,
336+ message = e .detail ,
337+ )
338+
339+ # Send error notification
340+ node_notif = NodeNotification (
341+ id = db_node .id ,
342+ name = db_node .name ,
343+ message = e .detail ,
344+ )
345+ asyncio .create_task (notification .error_node (node_notif ))
346+ return
347+
348+ # Connect the node
349+ result = await NodeOperation .connect_node (db_node , users )
350+
351+ if not result :
352+ return
353+
354+ # Update status using simple CRUD (NOT bulk!)
355+ await update_node_status (
356+ db = db ,
357+ db_node = db_node ,
358+ status = result ["status" ],
359+ message = result .get ("message" , "" ),
360+ xray_version = result .get ("xray_version" , "" ),
361+ node_version = result .get ("node_version" , "" ),
362+ )
363+
364+ # Send appropriate notification
365+ if result ["status" ] == NodeStatus .connected :
366+ node_notif = NodeNotification (
367+ id = db_node .id ,
368+ name = db_node .name ,
369+ xray_version = result .get ("xray_version" ),
370+ node_version = result .get ("node_version" ),
371+ )
372+ asyncio .create_task (notification .connect_node (node_notif ))
373+ elif result ["status" ] == NodeStatus .error and result ["old_status" ] != NodeStatus .error :
374+ node_notif = NodeNotification (
375+ id = db_node .id ,
376+ name = db_node .name ,
377+ message = result .get ("message" ),
378+ )
379+ asyncio .create_task (notification .error_node (node_notif ))
322380
323381 async def restart_node (self , db : AsyncSession , node_id : Node , admin : AdminDetails ) -> None :
324- await self .connect_node_wrapper (db , node_id )
382+ await self .connect_single_node (db , node_id )
325383 logger .info (f'Node "{ node_id } " restarted by admin "{ admin .username } "' )
326384
327385 async def restart_all_node (self , db : AsyncSession , admin : AdminDetails , core_id : int | None = None ) -> None :
0 commit comments