10. Запросы

Запросы к серверу выполняют методом POST и содержат в теле JSON-объект, состоящий из обязательных блоков:

  • Блок Credentials;

  • Блок Query;

Также пространстве методов server находятся методы, помогающие эксплуатации корректно конфигурировать хранилища данных относительно модели СМЭВ QL.

10.1. Блок Credentials

"credentials":{
    "system":{
        "mnemonic":"117bed7f-1c07-4079-a446-1161588db4e5",
        "instance_id":"ccb4a88f-f44b-43e7-8a97-3e45c8345e90",
        "user_id":"5ed38461-0907-486a-930a-7b443482932c"
    },
    "request":{
        "id":"df5a0073-c6be-4d8c-8eb2-9b2f4188a429",
        "sub_id":"0cdb59ce-224b-4118-8da1-c5ea08a5d955",
        "name":"driver_data",
        "purpose_id":"ed1170f1-3caa-4985-aa38-c9c5a190b770",
        "audit":"false",
        "audit_id":"fc1048fe-323d-4eeb-92df-5710b3d1d100",
        "audit_token":"39e47aac-45d2-44c1-8c26-2d9b28b1703b"
    },
    "signature":{
        "digest": null,
        "signature": null
    }
}

10.2. Блок Query

{
    "query": {
        "office": {
            "conditions": {
                "phone": "(347) 246-53-00"
            },
            "attributes": [
                "id",
                "phone",
                "name"
            ],
            "cabinet": {
                "conditions": {
                    "available": true
                },
                "attributes": [
                    "number",
                    "name",
                    "seats"
                ],
                "online_room": {
                    "conditions": {
                        "public": true,
                        "software": "zoom"
                    },
                    "attributes": [
                        "url"
                    ]
                },
                "parking": {
                    "conditions": {
                        "free": true,
                        "available": true
                    },
                    "attributes": [
                        "number",
                        "floor"
                    ]
                }
            }
        }
    }
}

10.2.1. Условия фильтрации Conditions

Объединение условий только по and (MVP)

Операции сравнения (op):

  • = (по умолчанию)

  • >

  • >=

  • <

  • <=

  • in

  • like (на перспективу)

Условия сравнения применимы к численным типам, датам, временам и таймштампам.

Варианты определения условий фильрации:

По равенству

{
    "query": {
        "office": {
            "conditions": {
                "phone": "(347) 246-53-00"
            }
        }
    }
}

На основе сравнения, краткая запись

{
    "query": {
        "office": {
            "conditions": {
                "area": [">","130"]
            }
        }
    }
}

На основе сравнения, полная запись

{
    "query": {
        "office": {
            "conditions": {
                "area": {
                    "op": ">",
                    "value": "130"
                }
            }
        }
    }
}

Комплексное условие

{
    "query": {
        "office": {
            "conditions": {
                "area": [">","130"],
                "floor": ["in", [1, 2]]
            }
        }
    }
}

OR (ИЛИ) в условиях

В conditions СМЭВ QL запроса поддерживается возможность указывать логический ИЛИ через зарезервированное слово or.

В блок or необходимо передать массив объектов, содержащих условия в свою очередь объединённые логическим И (AND).

Все условия, находящиеся на одном уровне с or группируются через логическое И (AND), как при обычном СМЭВ QL Запросе.

Пример:

"conditions": {
"lastname": "П",
"middlename": "И",
"birthdate": "2021-11-29 00:00:00",
"or": [
    {
        "vin": "в1"
    },
    {
        "vin2": "в2",
        "model": "bmw"
    }
],
"fetch": {
    "order": [["id", "ASC"], ["number", "DESC"]], // ASC default
    "page": [2, 10] // limit 10 offset 10
}
}

Условия описанного выше запроса (без учета fetch) соберутся в следующую конструкцию:

...
WHERE
        (lastname = 'П' AND middlename = 'И' AND birthdate = '2021-11-29 00:00:00')
    OR
        (vin ='в1')
    OR
        (vin2='в2' AND model = 'bmw')
...

10.2.2. Сортировка и пагинация

В блоке conditions опционально можно добавить блок fetch, в котором указывать условия сортировки и выбора страниц.

Пример блока:

"conditions": {
"lastname": "П",
"middlename": "И",
"birthdate": "2021-11-29 00:00:00",
"fetch": {
    "order": [["id", "ASC"], ["number", "DESC"]], // ASC default
    "page": [2, 10] // limit 10 offset 10
}
}

Если порядок сортировки не указан, то применяется ASC.

Если не указаны страницы, то по умолчанию всегда устанавливается первая страница с лимитом, равными параметру default блока pagination в файле конфигураций application.yaml.

Если запрашивается элементов на страницу больше, чем значение max, то должно использоваться дефолтное значение.

pagination:
    default: 100 //количество элементов на странице по умолчанию
    max: 1000 //максимальное количество элементов на странице

10.3. Эксплуатационные запросы

В пространстве методов server находятся методы, помогающие эксплуатации корректно конфигурировать хранилища данных относительно модели СМЭВ QL.

Метод возврата списка обязательных для создания индексов: GET server/indexes/required

В ответе должен возвращаться JSON с полями, используемыми в связях моделей (connections) и блоке conditions.allowed моделей, если они определены (conditions)

{
    "server": {
        "mnemonic": "#mnemonic",
        "instance": "#instance"
    },
    "indexes": {
        "connections": [{
                "source": "#source_name2",
                "table": "#table_name2",
                "fields": ["#field_name1", "#field_name2"]
            },
            {
                "source": "#source_name2",
                "table": "#table_name2",
                "fields": ["#field_name1", "#field_name2"]
            }
        ],
        "conditions": [{
                "source": "#source_name2",
                "table": "#table_name2",
                "fields": ["#field_name1", "#field_name2"]
            },
            {
                "source": "#source_name2",
                "table": "#table_name2",
                "fields": ["#field_name1", "#field_name2"]
            }
        ]
    }
}

10.4. Обработка запросов

10.4.1. Логирование мета-данных

У каждого запроса логируются данные из блока credentials в info и выше.

Формат строки лога:

{
    "level": "info",
    "time": "2000-01-01T01:01:01.111Z",
    "name": "#{smevql_server_name}.request",
    "system": {
        "mnemonic": "117bed7f-1c07-4079-a446-1161588db4e5",
        "instance_id": "ccb4a88f-f44b-43e7-8a97-3e45c8345e90",
        "user_id": "5ed38461-0907-486a-930a-7b443482932c"
    },
    "request": {
        "id": "df5a0073-c6be-4d8c-8eb2-9b2f4188a429",
        "sub_id": "0cdb59ce-224b-4118-8da1-c5ea08a5d955",
        "name": "driver_data",
        "purpose_id": "ed1170f1-3caa-4985-aa38-c9c5a190b770",
        "audit": "false",
        "audit_id": "fc1048fe-323d-4eeb-92df-5710b3d1d100",
        "audit_token": "39e47aac-45d2-44c1-8c26-2d9b28b1703b"
    }
}

Для каждого входящего запроса логируется каждый отправленный запрос к источнику:

{
    "level": "info",
    "time": "2000-01-01T01:01:01.111Z",
    "name": "#{smevql_server_name}.request",
    "system": {
        "mnemonic": "117bed7f-1c07-4079-a446-1161588db4e5",
        "instance_id": "ccb4a88f-f44b-43e7-8a97-3e45c8345e90",
        "user_id": "5ed38461-0907-486a-930a-7b443482932c"
    },
    "request": {
        "id": "df5a0073-c6be-4d8c-8eb2-9b2f4188a429",
        "sub_id": "0cdb59ce-224b-4118-8da1-c5ea08a5d955",
        "name": "driver_data",
        "purpose_id": "ed1170f1-3caa-4985-aa38-c9c5a190b770",
        "audit": "false",
        "audit_id": "fc1048fe-323d-4eeb-92df-5710b3d1d100",
        "audit_token": "39e47aac-45d2-44c1-8c26-2d9b28b1703b"
    },
    "source_request": {
        "id": "1cdb59ce-224b-4118-8da1-c5ea08a5d955",
        "source": "#{source_name}"
    }
}

Передача идентификаторов:

  1. source_request.id передается в queryId тела запроса в Простор.

  2. В x-request-id передается склейка {request.id};{request.sub_id};{source_request.id}

Логирование ответа

{
    "level": "info",
    "time": "2000-01-01T01:01:01.111Z",
    "name": "#{smevql_server_name}.response",
    "system": {
        "mnemonic": "117bed7f-1c07-4079-a446-1161588db4e5",
        "instance_id": "ccb4a88f-f44b-43e7-8a97-3e45c8345e90",
        "user_id": "5ed38461-0907-486a-930a-7b443482932c"
    },
    "request": {
        "id": "df5a0073-c6be-4d8c-8eb2-9b2f4188a429",
        "sub_id": "0cdb59ce-224b-4118-8da1-c5ea08a5d955",
        "name": "driver_data",
        "purpose_id": "ed1170f1-3caa-4985-aa38-c9c5a190b770",
        "audit": "false",
        "audit_id": "fc1048fe-323d-4eeb-92df-5710b3d1d100",
        "audit_token": "39e47aac-45d2-44c1-8c26-2d9b28b1703b"
    },
    "source_request": {
        "id": "1cdb59ce-224b-4118-8da1-c5ea08a5d955",
        "source": "#{source_name}"
    },
    "response": {
        "duration": "1ms",
        "code": 200,
        "result": "ok"
    }
}

10.4.2. Исполнение плана запроса

Запускающее событие

  • Подготовлен план выполнения запроса.

Ход выполнения

Указанная последовательность выполняется для каждого подзапроса из плана. При этом сначала параллельно выполняются подзапросы первого уровня, затем подзапросы второго уровня на основе данных полученных на первом уровне и т.д. по всем уровням иерархии плана запроса.

В качестве ответа от Источника могут быть сами запрашиваемые данные (если обращение к источнику шло в синхронном режиме) или токен (если обращение к источнику шло в асинхронном режиме).

  1. Система отправляет подзапрос к источнику с указанным в плане sql-выражением. Так же на этом шаге Система обновляет счетчики лимитов в Redis, при этом количество увеличивается на величину подзапросов к источникам данных.

  2. Система ожидает ответ и определяет режим обработки подзапроса к источнику ресурса. Для этого определяет значение параметра fetch->policy в модели данных ресурса:

    a) если установлено значение sync или async_on_timeout и ответ пришёл в течение заданного таймаута, то режим обработки подзапроса синхронный, переход к выполнению шага 2. b) иначе, установлено значение async или async_on_timeout и исчтоник не отвечает в в течение заданного таймаута, то режим обработки подзапроса асинхронный, переход к выполнению шага 6.

  3. Система обрабатывает полученный ответ от источника или обрабатывает ситуацию, когда ответ не получен:

    a) если ответ получен и он некорректного формата или ответ не получен в заданный таймаут, то Система формрует блок с описанием ошибки (пример приведен ниже) и переходит к следующему источнику. b) если, ответ корректен и получен в заданный таймаут, а источником данных является prostore, то данный процесс завершается и вызывается выполнение передачи ответа потребителю. c) иначе, ответ корректен и получен в заданный таймаут, а источником данных является smevql, переход к выполнению следующего шага.

  4. Система проверяет, что ответ от источника подписан цифровой подписью (далее ЦП). Для этого извлекает данные из полученного ответа (блок signature) и отправляет данные ЦП на проверку в модуль Notarius. После чего дожидается результатов проверки ЦП от Notarius:

    a) если ЦП не прошла успешную проверку в Notarius или блок signature не заполнен источником, то ответ считается невалидным, Система передаёт соответствующее сообщение об ошибке, процесс завершается. b) иначе, ЦП прошла успешную проверку в Notarius, ответ валиден, переход к выполнению следующего шага.

  5. Система накладывает свою ЦП на ответ источника. Для этого отправляет запрос в модуль Notarius и ожидает получение ответа. После чего ответ подписан ЦП (заполнен блок partials в ответе для потребителя). Процесс завершается после получения всех ответов от всех источников и вызывается выполнение передачи ответа потребителю.

  6. Система генерирует токен (по которому в дальнейшем Потребитель сможет отдельно запросить данные) и записывает его в блоке персистентности Redis.

  7. Система в качестве временного ответа от источника подставляет токен (получение данных по токену см. раздел 3.5.4 Асинхронное получение данных клиентом). Процесс завершается после получения всех ответов от всех источников и вызывается выполнение передачи ответа потребителю.

План запроса

Пример блока с описанием ошибки:

"errors": [ - блок ошибок, единый для всех ресурсов и источников
    {
        "resource": <название ресурса>, - новое поле
        "source": <название источника>, - новое поле (опциональное)
        "error": "Ошибка обращения к источнику prostore: connection timed out after 30000 ms: prostore.dtm-test1.svc.cluster.local/10.111.97.115:9010",
        "code": "901"
    }
]