@@ -297,45 +297,35 @@ async def add_project_members(
297297 username_to_user = {user .name : user for user in users_found }
298298 email_to_user = {user .email : user for user in users_found if user .email }
299299
300- # Build a set of current member IDs so we can quickly check if users are already members
301- member_ids = {m .user_id for m in project .members }
302300 # Build a map from user_id to member for efficient existing member updates
303301 member_by_user_id = {m .user_id : m for m in project .members }
304302
305- # Get current max member_num
306- max_member_num = 0
307- for member in project .members :
308- if member .member_num is not None and member .member_num > max_member_num :
309- max_member_num = member .member_num
310-
311303 # Process each member to add
312304 for member_setting in members :
313305 user_to_add = username_to_user .get (member_setting .username ) or email_to_user .get (
314306 member_setting .username
315307 )
316308 if user_to_add is None :
317- # Error on adding non-existing users instead of silently skipping
318309 raise ServerClientError (f"User not found: { member_setting .username } " )
319310
320- # Check if user is already a member using our fast lookup set
321- if user_to_add .id in member_ids :
322- # Update existing member role if different using our efficient lookup
311+ # Check if user is already a member
312+ if user_to_add .id in member_by_user_id :
313+ # Update existing member role if different
323314 existing_member = member_by_user_id [user_to_add .id ]
324315 if existing_member .project_role != member_setting .project_role :
325316 existing_member .project_role = member_setting .project_role
326317 else :
327- # Add new member
328- max_member_num += 1
318+ # Add new member (let database handle member_num to avoid race conditions)
329319 await add_project_member (
330320 session = session ,
331321 project = project ,
332322 user = user_to_add ,
333323 project_role = member_setting .project_role ,
334- member_num = max_member_num ,
324+ member_num = None , # Let database auto-assign to avoid race conditions
335325 commit = False ,
336326 )
337- # Keep track of newly added members for subsequent iterations
338- member_ids . add ( user_to_add .id )
327+ # Update our local tracking for subsequent iterations
328+ member_by_user_id [ user_to_add .id ] = None # Placeholder to track addition
339329
340330 await session .commit ()
341331
@@ -663,8 +653,6 @@ async def remove_project_members(
663653 username_to_user = {user .name : user for user in users_found }
664654 email_to_user = {user .email : user for user in users_found if user .email }
665655
666- # Build a set of member IDs for faster membership checks
667- member_user_ids = {m .user_id for m in project .members }
668656 # Build a map from user_id to member for efficient member lookups
669657 member_by_user_id = {m .user_id : m for m in project .members }
670658
@@ -675,15 +663,13 @@ async def remove_project_members(
675663 for username in usernames :
676664 user_to_remove = username_to_user .get (username ) or email_to_user .get (username )
677665 if user_to_remove is None :
678- # Error on removing non-existing users instead of silently skipping
679666 raise ServerClientError (f"User not found: { username } " )
680667
681668 # Check if user is actually a member before trying to remove them
682- if user_to_remove .id not in member_user_ids :
683- # Error on removing non-members instead of silently skipping
669+ if user_to_remove .id not in member_by_user_id :
684670 raise ServerClientError (f"User is not a member of this project: { username } " )
685671
686- # Get the member to remove using our efficient lookup
672+ # Get the member to remove
687673 member_to_remove = member_by_user_id [user_to_remove .id ]
688674
689675 # Check if trying to remove project admin
0 commit comments