.. _smev_ql_request: Запросы ^^^^^^^^ Запросы к серверу выполняют методом POST и содержат в теле JSON-объект, состоящий из обязательных блоков: - Блок Credentials; - Блок Query; Также пространстве методов server находятся методы, помогающие эксплуатации корректно конфигурировать хранилища данных относительно модели СМЭВ QL. Блок Credentials ################ .. code-block:: json "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 } } Блок Query ########## .. code-block:: json { "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" ] } } } } } Условия фильтрации Conditions """""""""""""""""""""""""""""" Объединение условий только по `and` (MVP) Операции сравнения (op): - = (по умолчанию) - > - >= - < - <= - in - like (на перспективу) Условия сравнения применимы к численным типам, датам, временам и таймштампам. Варианты определения условий фильрации: По равенству .. code-block:: json { "query": { "office": { "conditions": { "phone": "(347) 246-53-00" } } } } На основе сравнения, краткая запись .. code-block:: json { "query": { "office": { "conditions": { "area": [">","130"] } } } } На основе сравнения, полная запись .. code-block:: json { "query": { "office": { "conditions": { "area": { "op": ">", "value": "130" } } } } } Комплексное условие .. code-block:: json { "query": { "office": { "conditions": { "area": [">","130"], "floor": ["in", [1, 2]] } } } } **OR (ИЛИ) в условиях** В **conditions** СМЭВ QL запроса поддерживается возможность указывать логический ИЛИ через зарезервированное слово **or**. В блок **or** необходимо передать массив объектов, содержащих условия в свою очередь объединённые логическим **И** (**AND**). Все условия, находящиеся на одном уровне с **or** группируются через логическое **И** (**AND**), как при обычном СМЭВ QL Запросе. Пример: .. code-block:: json "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) соберутся в следующую конструкцию: .. code-block:: yaml ... WHERE (lastname = 'П' AND middlename = 'И' AND birthdate = '2021-11-29 00:00:00') OR (vin ='в1') OR (vin2='в2' AND model = 'bmw') ... Сортировка и пагинация """"""""""""""""""""""" В блоке **conditions** опционально можно добавить блок **fetch**, в котором указывать условия сортировки и выбора страниц. Пример блока: .. code-block:: json "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, то должно использоваться дефолтное значение. .. code-block:: yaml pagination: default: 100 //количество элементов на странице по умолчанию max: 1000 //максимальное количество элементов на странице Эксплуатационные запросы ######################### В пространстве методов server находятся методы, помогающие эксплуатации корректно конфигурировать хранилища данных относительно модели СМЭВ QL. Метод возврата списка обязательных для создания индексов: ``GET server/indexes/required`` В ответе должен возвращаться JSON с полями, используемыми в связях моделей (connections) и блоке conditions.allowed моделей, если они определены (conditions) .. code-block:: json { "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"] } ] } } Обработка запросов ##################### Логирование мета-данных """"""""""""""""""""""""" У каждого запроса логируются данные из блока ``credentials`` в ``info`` и выше. Формат строки лога: .. code-block:: json { "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" } } Для каждого входящего запроса логируется каждый отправленный запрос к источнику: .. code-block:: json { "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}`` Логирование ответа .. code-block:: json { "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" } } Исполнение плана запроса """""""""""""""""""""""""""""""" **Запускающее событие** - Подготовлен план выполнения запроса. **Ход выполнения** Указанная последовательность выполняется для каждого подзапроса из плана. При этом сначала параллельно выполняются подзапросы первого уровня, затем подзапросы второго уровня на основе данных полученных на первом уровне и т.д. по всем уровням иерархии плана запроса. В качестве ответа от Источника могут быть сами запрашиваемые данные (если обращение к источнику шло в синхронном режиме) или токен (если обращение к источнику шло в асинхронном режиме). 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 Асинхронное получение данных клиентом). Процесс завершается после получения всех ответов от всех источников и вызывается выполнение передачи ответа потребителю. .. _request_plan: .. figure:: /_static/img/modules/smevql/request_plan.png :align: center :alt: План запроса Пример блока с описанием ошибки: .. code-block:: yaml "errors": [ - блок ошибок, единый для всех ресурсов и источников { "resource": <название ресурса>, - новое поле "source": <название источника>, - новое поле (опциональное) "error": "Ошибка обращения к источнику prostore: connection timed out after 30000 ms: prostore.dtm-test1.svc.cluster.local/10.111.97.115:9010", "code": "901" } ]