def delete_connection_from_rooms(connection_id, user, rooms): user_has_left = False for room_id in rooms: room = get_room(room_id) if room: user_in_room = [u for u in room['users'] if u['id'] == user['id']] if len(user_in_room) > 0: user_in_room = user_in_room[0] if connection_id in user_in_room['connections']: # remove connection from user user_in_room['connections'].remove(connection_id) if len(user_in_room['connections']) == 0: # remove user from room room['users'] = [ u for u in room['users'] if u['id'] != user['id'] ] if len(room['users']) == 0: # delete room # fix rooms are also deleted, should be fine # since chat history stays redis_client.delete(room_id) return else: user_has_left = True redis_client.set(room_id, json.dumps(room)) if user_has_left: # broadcast user left broadcast_user_left(room_id, user)
def revoke_token(token): """ Only revoke one given token, not all tokens of user """ user = get_user(token) if not user: return False redis_client.delete(token) remove_token_from_user(user['id'], token) return True
def kill_ghost_connections(): # TODO: mock scan_iter() when not using redis # low priority, when it's single instance without redis # ghost connections are rare for key in redis_client.scan_iter("room*"): data = redis_client.get(key) if data: # value might already be deleted by another # ghost buster thread room = json.loads(data) now = time.time() user_ids_to_be_removed = [] for user in room['users']: connection_ids_to_be_removed = [] for connection in user['connections']: time_elapse = now - connection['heartbeat'] if time_elapse > HEARTBEAT_TIMOUT: connection_id = connection['id'] logger.info( f'[{key}] ghost connection {connection_id} will be removed' ) connection_ids_to_be_removed.append(connection_id) user['connections'] = [ c for c in user['connections'] if c['id'] not in connection_ids_to_be_removed ] if (len(user['connections']) == 0): user_id = user['id'] logger.info(f'ghost user {user_id} will be removed') user_ids_to_be_removed.append(user_id) room['users'] = [ u for u in room['users'] if u['id'] not in user_ids_to_be_removed ] if len(room['users']) == 0: logger.info(f'ghost room {key} will be removed') redis_client.delete(key) else: if len(connection_ids_to_be_removed) > 0: upsert_room(room)
def clean_dead_connections(room_id, user_id, dead_connections): # Remove connection/user from room data # Remove connection from connections map # TODO: enforce how many connections a user can have, similar to MAX_USER_CONNECTION # but not per room, it's for total if len(dead_connections) > 0: print(f'[{room_id}] found dead connections: {len(dead_connections)}') room = get_room(room_id) users = room['users'] user_in_room = [u for u in users if u['id'] == user_id] if len(user_in_room) > 0: user = user_in_room[0] user['connections'] = [connection_id for connection_id in user['connections'] if connection_id not in dead_connections] if len(user['connections']) == 0: room['users'] = [u for u in users if u['id'] != user_id] # TODO: broadcast user left redis_client.set(room_id, json.dumps(room)) for connection_id in dead_connections: # TODO: bulk delete redis_client.delete(connection_id)
def delete_connection_from_rooms(connection, room_ids): user = connection.user connection_id = connection.id if user: user_has_left = False for room_id in room_ids: room = get_room(room_id) if room: user_in_room = [u for u in room['users'] if u['id'] == user['id']] if len(user_in_room) > 0: user_in_room = user_in_room[0] connection_in_room = [ c for c in user_in_room['connections'] if c['id'] == connection_id] if len(connection_in_room) > 0: connection_in_room = connection_in_room[0] # remove connection from user user_in_room['connections'] = [ c for c in user_in_room['connections'] if c['id'] != connection_id] if len(user_in_room['connections']) == 0: # remove user from room room['users'] = [u for u in room['users'] if u['id'] != user['id']] if len(room['users']) == 0: # delete room # fix rooms are also deleted, should be fine # since chat history stays redis_client.delete(room_id) return else: user_has_left = True upsert_room(room) if user_has_left: # broadcast user left broadcast_user_left(connection_id, room_id, user)
def _delete_connection_from_connections(connection_id): data = redis_client.get(connection_id) if data: connection = json.loads(data) redis_client.delete(connection_id) return connection