Метод PUT /api/v1/connector/{id_connector}/configuration-metadata/{configuration_metadata_type}

Краткое описание

Создаёт или обновляет (upsert) метаданные конфигурации 1С для объектов данных. Эндпоинт:

  • Поддерживает потоковую передачу данных без загрузки в память

  • Автоматически выбирает действие: CREATE или UPDATE

  • Использует механизм ON CONFLICT PostgreSQL для безопасной вставки/обновления

  • Поддерживает сжатие данных gzip

Входные параметры

Параметры пути (обязательные):

  1. id_connector (строка, обязательный)

    • Уникальный идентификатор коннектора 1С

    • Пример: 8f4e5a2c-1234-5678-90ab-cdef12345678

  2. configuration_metadata_type (enum, обязательный)

    • Тип метаданных конфигурации

    • Допустимые значения: common, constants, catalogs, documents, document-journals, enumerations, reports, data-processors, charts-of-characteristic-types, charts-of-accounts, charts-of-calculation-types, information-registers, accumulation-registers, accounting-registers, calculation-registers, business-processes, tasks, external-data-sources, other.

    • При передаче неверного значения возвращается 400

Заголовки запроса (опциональные):

  1. Content-Encoding (заголовок, опциональный)

    • Если значение gzip — данные в теле запроса сжаты алгоритмом gzip

    • По умолчанию: не сжато

    • Используется для оптимизации при передаче больших файлов

Тело запроса (обязательное):

  1. Бинарные данные

    • Формат: JSON или бинарные данные

    • Может быть обычные данные или gzip-сжатые (если Content-Encoding: gzip)

    • Данные передаются потоком (streaming) — обрабатываются по частям

Алгоритм работы метода

ЭТАП 1: Валидация и инициализация

  • Проверяется допустимость configuration_metadata_type через enum

  • Если невалидный — возвращается HTTPException(400)

  • Извлекается заголовок Content-Encoding

  • Если Content-Encoding == "gzip" — создаётся декомпрессор zlib

ЭТАП 2: Проверка существования записи

  • Подключается к PostgreSQL через асинхронный коннектор psycopg

  • Выполняется SELECT для поиска существующей записи: WHERE id_connector = {переданный_id} AND type = {переданный_тип}

Результаты:

  • Если запись найдена:

    • existing_id = id из найденной записи

    • target_id = existing_id

    • action = "updated"

  • Если запись НЕ найдена:

    • existing_id = None

    • target_id = новый UUID

    • action = "created"

ЭТАП 3: Создание временной таблицы для данных

  • Создаётся TEMP TABLE cm_tmp_data для временного хранения JSON

  • TEMP TABLE автоматически удаляется при завершении транзакции

  • Используется ON COMMIT DROP для гарантированной очистки

ЭТАП 4: Потоковая загрузка данных в TEMP TABLE

  • Открывается COPY поток для вставки в временную таблицу

  • Начинается CSV-строка (открывающая кавычка b'"')

  • Цикл async for chunk in request.stream():

    • Читает данные из тела запроса по частям

    • Пропускает пустые chunks

    • Если gunzip активен — распаковывает каждый chunk

    • Экранирует кавычки для CSV формата (двойные кавычки)

    • Пишет в COPY поток

  • После завершения потока:

    • Если gunzip активен — вызывается gunzip.flush()

    • Добавляются оставшиеся распакованные данные

    • Завершается CSV-строка (закрывающая кавычка и \n)

ЭТАП 5: Вставка или обновление с ON CONFLICT

  • Выполняется INSERT с явным указанием конфликта:

INSERT INTO configuration_metadata_entity (id_configuration_metadata_entity, id_connector, type, data, ecc_dt) SELECT target_id, id_connector, type, data, NOW() FROM cm_tmp_data ON CONFLICT (id_connector, type) DO UPDATE SET data = EXCLUDED.data, ecc_dt = EXCLUDED.ecc_dt