Загрузка данных


import time
# Функция принимает 5 параметров:
# 1. response: locust.FastResponse (https://docs.locust.io/en/stable/_modules/locust/contrib/fasthttp.html#FastResponse) для HTTP-зарпосов
# и тело ответа для всех асинхронных операций
# 2. Объект операции (то, вы создавали здесь в UI). Формат операции и ее ключи можно посмотреть в итоговом JSON
# 3. Словарь, "переменная": "значение" с локальными переменными потока
# 4. Список созданных листенеров Kafka, WS, gRPC
# 5. Объект класса UserClass
#
# И должна возвращать 4 параметра:
# 1. Успешность операции (None, если успешность должна быть определена стандартными средствами
# В http по коду ответа, в других протоколах всегда успешно))
# 2. id следующей операции (None, если на этом нужно завершить итерацию)
# 3. Словарь, "переменная": "значение" (может быть пустым - {}) для локальных переменных потока
# 4. Словарь, "переменная": "значение" (может быть пустым - {}) для глобальных переменных теста


from typing import NamedTuple, Optional
# from locust.contrib.fasthttp import ResponseContextManager
# from app.clients.class_builder import UserClass
# from app.data_classes.config import OperationTypes
# from app.data_classes.user_vars import UserVar
# from app.users.async_response_readers import AsyncResponseReader, WebSocketResponseReader, KafkaResponseReader


class ReturnFromPostProcessor(NamedTuple):
    is_operation_successful: bool
    next_operation_id: Optional[str]
    local_vars: dict
    global_vars: dict

def has_remaining_iterations(user_vars):
    return int(user_vars['iteration'].value) < int(user_vars['total_iterations'].value) - 1

# def post_processor(response: Union[ResponseContextManager, str, bytes], operation: OperationTypes, user_vars: dict[str, UserVar], listeners: list[AsyncResponseReader], user_class: UserClass, *args, **kwargs) -> ReturnFromPostProcessor:
def post_processor(
    response, operation, user_vars, listener, user_class, *args, **kwargs
) -> ReturnFromPostProcessor:
    
    if response.status_code == 200: # if isinstance(response, ResponseContextManager
        if has_remaining_iterations(user_vars):
            try:
                conf = f"{user_class.environment.config=}"  # считываем конфиг
                position = conf.find("UC29_prelogin_AUTH_pp.py") # находим область, принадлежащую главной (родительской) операции
                pacing = conf[position:position+130]        # запоминаем интересующую часть конфига
                pacing = pacing.split(",")[3]  # Здесь была ошибка IndexError
                position = pacing.find("'")
                pacing = pacing[position+1:len(pacing)-1]
                position = pacing.find("-")
                numA = pacing[0:position]
                numB = pacing[position+1:len(pacing)]
                pacing = (((float(numB)+float(numA)) / 2) - 15) / int(user_vars['total_iterations'].value)
                time.sleep(pacing)
            except (IndexError, ValueError, AttributeError) as e:
                # Если ошибка — просто продолжаем без задержки
                pass 
            return ReturnFromPostProcessor(True, "UC29_GET_contacts_WEB", {"iteration": str(int(user_vars['iteration'].value) + 1)}, {})
        else:    
            return ReturnFromPostProcessor(True, None, {"iteration": str(int(user_vars['iteration'].value) * 0)}, {})
    elif has_remaining_iterations(user_vars):
        return ReturnFromPostProcessor(False, "UC29_GET_contacts_WEB", {"iteration": str(int(user_vars['iteration'].value) + 1)}, {})
    else:
        return ReturnFromPostProcessor(False, None, {"iteration": str(int(user_vars['iteration'].value) * 0)}, {})