@@ -1565,6 +1565,17 @@ async def try_open_project_for_user(
15651565 )
15661566 async def _open_project () -> bool :
15671567 with managed_resource (user_id , client_session_id , app ) as user_session :
1568+ # check if the project is already opened
1569+ if (
1570+ current_project_ids := await user_session .find (PROJECT_ID_KEY )
1571+ ) and f"{ project_uuid } " in current_project_ids :
1572+ _logger .debug (
1573+ "project %s is already opened by user %s/%s" ,
1574+ project_uuid ,
1575+ user_id ,
1576+ client_session_id ,
1577+ )
1578+ return True
15681579 # Enforce per-user open project limit
15691580 if max_number_of_opened_projects_per_user is not None and (
15701581 len (
@@ -1585,14 +1596,39 @@ async def _open_project() -> bool:
15851596 client_session_id = client_session_id ,
15861597 )
15871598
1588- # Assign project_id to current_session
1599+ # try to assign project_id to current_session
15891600 sessions_with_project = await user_session .find_users_of_resource (
15901601 app , PROJECT_ID_KEY , f"{ project_uuid } "
15911602 )
15921603 if max_number_of_user_sessions_per_project is not None and (
15931604 len (sessions_with_project )
15941605 >= max_number_of_user_sessions_per_project
15951606 ):
1607+ # we need to check has an inactive session in which case we can steal the project
1608+ this_user_other_sessions = [
1609+ s
1610+ for s in sessions_with_project
1611+ if s .user_id == user_id and s != user_session
1612+ ]
1613+ for session in this_user_other_sessions :
1614+ with managed_resource (
1615+ session .user_id , session .client_session_id , app
1616+ ) as other_user_session :
1617+ if await other_user_session .get_socket_id () is None :
1618+ # this user has an inactive session, we can steal the project
1619+ _logger .debug (
1620+ "stealing project %s from user %s/%s" ,
1621+ project_uuid ,
1622+ session .user_id ,
1623+ session .client_session_id ,
1624+ )
1625+ await user_session .add (
1626+ PROJECT_ID_KEY , f"{ project_uuid } "
1627+ )
1628+ await other_user_session .remove (PROJECT_ID_KEY )
1629+
1630+ return True
1631+
15961632 raise ProjectTooManyUserSessionsError (
15971633 max_num_sessions = max_number_of_user_sessions_per_project ,
15981634 user_id = user_id ,
0 commit comments