Протоколы и режимы обработки данных
Далее, рассматривается архитектура и принципы работы пользовательских блоков, реализованных на языке Python. Ниже разберём протоколы обмена данными между системой и пользовательским кодом, а также режимы выполнения: от получения метаданных до обработки данных и завершения сессии.
Старт модуля блоков на Python
Модуль запускается после старта контейнера. Если Proceset уже работает, модуль отправляет ему уведомление о своём запуске, после чего Proceset с помощью команды --get-info запрашивает информацию о доступных пользовательских блоках, реализованных на Python. В случае, если модуль был запущен раньше Proceset, последний при старте самостоятельно запрашивает у модуля данные о реализованных блоках.
При старте модуля все entrypoint.py, указанные в конфигурационном файле com.infomaximum.subsystem.automationagentextpy.json, запускаются с аргументом --get-info. Запуск скрипта подтверждается появлением команды в выходном потоке stdout.
{"cmd":"start"}
Пример ожидаемого ответа в stdout:
{
"uuid":"<uuid>",
"data": {
"mode" : "isolated",
"protocol_version": 2,
"groups" : [{
"uuid": "test_group_17d80e527c6eb4cb9b9cc4031378ae176",
"name": {
"en": "Testing group info",
"ru": "Тестовая группа"
},
"category": "tools",
"icon":"icons/test_group_17d80e527c6eb4cb9b9cc4031378ae176.png",
"blocks" : [{
"uuid" : "test_block_7914294fbc6042e180c40ea276ad041b",
"type" : "action",
"name" : {
"en" : "Testing block info",
"ru" : "Тестовый блок",
},
"description" : {
"en" : "Testing block description",
"ru" : "Описание тестового блока",
},
"compatible_connections" : [],
"optionals" : {
"is_save_data_on_fail_block_type" : False,
"is_system_block_type" : False
},
"fields" : """[{
key: 'var_1',
type: 'text',
label: 'Введи 1 число',
hint: "Поле для ввода первого числа",
required: true
}, {
key: 'var_2',
type: 'text',
label: 'Введи 2 число',
hint: "Поле для ввода второго числа",
required: true
}]"""
},{
"uuid" : "test_block_9ceab1276c364fa981e765d4b51d90a0",
"type" : "action",
"name" : {
"en" : "Testing block info",
"ru" : "Тестовый блок",
},
"description" : {
"en" : "Testing block description",
"ru" : "Описание тестового блока",
},
"compatible_connections" : ["test_connection_422178d485924ee89121d4e7b992f918"],
"optionals" : {
"is_save_data_on_fail_block_type" : False,
"is_system_block_type" : False
},
"fields" : """[{
key: 'f_1',
type: 'text',
label: 'Поле1',
hint: "Первое поле",
required: true
}, {
key: 'f_2',
type: 'text',
label: 'Поле2',
hint: "Второе необязательное поле",
required: false
}]"""
}],
"connections" : [{
"uuid" : "test_connection_422178d485924ee89121d4e7b992f918",
"name" : {
"en" : "Testing connection info",
"ru" : "Тестовое подключение",
},
"description" : {
"en" : "Testing connection description",
"ru" : "Описание тестового подключения",
},
"fields" :"""[{
key: 'var_1',
type: 'text',
label: 'Введи число',
hint: 'Поле для ввода 1',
required: true
},{
key: 'var_2',
type: 'text',
label: 'Введите что-нибудь',
hint: 'Поле для ввода 2',
required: true
}]"""
}]
}]
}
}
Где:
data— основные данные, которые содержат информацию о группе, блоках и подключенияхmode— режим запуска блоков (interactive/isolated)protocol_version— версия протоколаgroups— массив группuuid— уникальный идентификатор группы. Для уникальности идентификаторов используйте сгенерированный UUIDname— локализованное название группыen— на английскомru— на русском
icon— путь к файлу иконки группы относительно папки скриптаcategory— категория верхнего уровня, в которую попадают блоки. Доступны следующие значения:"databases","storages","services","tools"blocks— массив блоковuuid— уникальный идентификатор блокаtype— тип блока (action/trigger)name— локализованное название блокаen— на английскомru— на русском
description— локализованное описание блокаen— на английскомru— на русском
compatible_connections— список UUID-подключений, которые совместимы с блокомfields— строка с описанием полей блока. Представляет собой JS-код, который описывает поля для ввода данных и прочие элементы управления профиля блока. Соответсвует описанию пользовательских интеграций
connections— массив подключенийuuid— уникальный идентификатор подключенияname— локализованное название подключенияen— на английскомru— на русском
description— локализованное описание подключенияen— на английскомru— на русском
compatible_connections— список UUID-подключений, которые совместимы с блокомfields— строка с описанием полей подключения. Представляет собой JS-код, который описывает поля для ввода данных, и прочие элементы управления профиля блока. Соответсвует описанию пользовательских интеграций
Если возникает ошибка (например, InvalidBlockDefinitionException или ValidationError), проверьте, что структура данных, возвращаемая скриптом, соответствует ожидаемому формату: каждая группа должна содержать корректно описанные блоки, подключения и обязательные поля, такие как uuid, name, fields и другие.
Режим изолированных запусков
Каждая сессия обработки данных запускает точку входа — entrypoint.py. Особенности работы системы Request-Response:
- Для каждого запроса генерируется уникальный идентификатор.
- Каждый запрос отправляется в отдельном потоке.
- Запрос и ответ — однострочные, переводы строк экранируются.
Старт сессии
При запуске блока запускается скрипт. Также, запуск блока обозначает старт сессии обработки данных.
Имена и значения константных полей, а также список имен переменных полей, передаются один раз вместе с первой пачкой (batch) данных. Последовательность значений переменных полей определяется порядком их имен в списке.
Аргументы запуска:
--start
--block-uuid "some_block_4345f5709cbb4a8486d800b2908168bf"
--input-data {
"data": {
"static_fields": [{
"name": "field1",
"value": "value1"
},{
"name": "field3",
"value": 3
}],
"dynamic_field_names": ["StringField1", "FrequencyDoubleField", "ObjectField3", "LongArrayField4", "FileContentField5"],
"execution_mode": "DEBUG_BLOCK",
"connection_fields": [{
"name": "host",
"value": "115.151.51.1"
},{
"name": "port",
"value": 1088
},{
"name": "token",
"value": "TIh3YEFigvdF1DiDdmASZNPD8tJjYvFOhqtW6TWirKKdLBBlL75TXnO5jr4Z577aTsf1MLLJDPTpeMk4uJt5MGVz3jARBznWaZVtaEQXL0YWvAng5f8K"
}]
},
"uuid": "a1db9946-2454-423f-a76e-fd8a6e815f97"
}
Где:
--start— команда запуска сессии обработки данных--block-uuid— идентификатор блока--input-data— входные данные в формате JSONuuid— уникальный идентификатор запросаstatic_fields— поля, значения которых не меняются между записями входящих данных, т. е. не содержат маппингdynamic_field_names— список имен полей, значения которых меняются между записями входящих данных, т. е. содержат маппингexecution_mode— режим выполненияSIMPLE_EXECUTION— обычное выполнение опубликованного скриптаDEBUG_FULL— полное тестирование скриптаDEBUG_BLOCK— режим тестирования блока
connection_fields— значения полей подключения
Пример ответа:
{
"uuid": "a1db9946-2454-423f-a76e-fd8a6e815f97",
"data": {
"batch_size": 10,
}
}
Где:
uuid— идентификатор запросаbatch_size— количество записей в запросе разработки итераций
Обработка итераций
При обработке итераций входные данные приходят в виде набора входных полей с учетом примененного маппинга. Типы входных полей должны быть заранее известны на стороне Python — на их основе формируется описание, возвращаемое в ответ на команду --get-info.
Конвертация типов значений определяется соглашением о типах данных. Значения переменных входных полей передаются в виде вложенных массивов. В последующих пачках данных приходят только значения переменных входных полей.
Пример передаваемой пачки данных:
{
"uuid": "e3128e7c-26f5-494c-8beb-3ad96c470310",
"cmd": "insert",
"data": {
"dynamic_field_values": [[
"Строка1",
9.99,
{"Name":"Иван","Values":[1723717500,1725971582,1599741185]},
[1, 2],
"file_contents/4xXmZtu0zjuYxVQOnIZH.tmp"
],[
"Строка2",
8.88,
{"Name":"Анна","Values":[1747678746,1724876374,1587798799]},
[3, 4],
"file_contents/vyquY2sx7mfTw2omCzk0oLB.tmp"
]],
"end_of_data": true
}
}
Где:
uuid— уникальный идентификатор запросаcmd— команда вставки данныхdata— объект с вставляемыми даннымиdynamic_field_values— массив записей для вставкиend_of_data— флаг (true), указывающий на последнюю пачку данных для вставки
Ответ на первую пачку данных:
{
"uuid": "dcbce17f-3606-4f0a-bba3-26f196512b2d",
"data": {
"aggregate_mode": true,
"output_variables": [{
"type": "FileContent",
"name":"File1"
},{
"type": "Long",
"name":"Long1"
} ,{
"type": "Object",
"name":"var_2",
"struct": [{
"name": "field1",
"type": "UnixTime"
},{
"name": "field2",
"type": "Long"
}]
},{
"type": "ObjectArray",
"name": "var3",
"struct": [{
"name": "field1",
"type": "Object",
"struct": [{
"name": "field1_1",
"type": "BigIntegerArray"
}]
},{
"name": "field2",
"type": "String"
}]
}],
"records": [[ #ответ на первую запись [
"/file_contents/77YRlI4CB6u2mj4ARVuB.tmp",
101,
{
"field1":1735035524,
"Field2":1234512
},
[{
"field1":{
"field1_1": [3243243254324324323, 87568758758657865765]
},
"field2": "StringValue1"
}]
],[
"/file_contents/77YRlI4CB6u2mj4ARVuB.tmp",
102,
{
"field1":1735035524,
"Field2":1234512
},
[]
]],[#ответ на вторую запись
],[#две пустых записи - агрегация
],[#результат агрегации
"/file_contents/BC2ZD1n8EZ29XrOtjhUq.tmp",
951,
{
"field1":1735031111,
"Field2":9876541
},
[{
"field1":{
"field1_1": [44444444444444444, 55555555555555555555]
},
"field2": "StringValue2"
}]
]]
}
}
Где:
uuid— уникальный идентификатор запросаdata— объект с данными ответаaggregate_mode— режим агрегации. В значенииtrueбудет прервана связь с вышестоящими блоками, так как у одной записи несколько источников и невозможно определить корректную ссылку на родительский блокoutput_variables— описание выходных переменныхname— имя поляtype— тип поля
records— возвращаемые записи. Представляет собой массив трех уровней вложенности:- 1-й уровень — каждый элемент соответствует одной входящей записи
- 2-ой уровень — каждый элемент соответствует одной исходящей записи. Набор элементов представляет собой ответ на входящую запись
- 3-й уровень — каждый элемент соответствует значению поля исходящей записи. Порядок и типы полей соответствуют описанию в
output_variables
Ответ на последующие пачки данных:
{
"uuid": "9beb4eef-832f-47dd-b828-ebb3edefbae6",
"data": {
"records": [[#ответ на первую запись - две выходных записи [
"file:file_contents/77YRlI4CB6u2mj4ARVuB.tmp",
101,
{
"field1":1735035524,
"Field2":1234512
},
[{
"field1":{
"field1_1": [3243243254324324323, 87568758758657865765]
},
"field2": "StringValue1"
}]
],[
"file:file_contents/77YRlI4CB6u2mj4ARVuB.tmp",
102,
{
"field1":1735035524,
"Field2":1234512
},
[]
]],[#ответ на вторую запись - пусто
],[#две пустых записи - агрегация или фильтрация
],[[
"base64:5W2Jipw4e4kvyquY2sx7mfTw2omCzk0oLBs0F2Z7LF2nDI3wwF6ggbAYRVA5fPKtS0tHdsce9i7aZ73VcWGt2MzLHQTueQ6QYbacrwAoXR0SlKEbR5Tx",
951,
{
"field1":1735031111,
"Field2":9876541
},
[{
"field1":{
"field1_1": [44444444444444444, 55555555555555555555]
},
"field2": "StringValue2"
}]
]]]
}
}
Где:
uuid— уникальный идентификатор запросаdata— объект с данными ответаrecords— возвращаемые записи. Представляет собой массив трех уровней вложенности:- 1-й уровень — каждый элемент соответствует одной входящей записи
- 2-ой уровень — каждый элемент соответствует одной исходящей записи. Набор элементов представляет собой ответ на входящую запись
- 3-й уровень — каждый элемент соответствует значению поля исходящей записи. Порядок и типы полей соответствуют описанию в
output_variables
Чтобы избежать ошибки в результате выполнения запроса, данные должны соответствовать формату output_variables.
Ответ может поддерживать следующие типы данных:
- Long
- LongArray
- Double
- DoubleArray
- Boolean
- BooleanArray
- String
- StringArray
- BigInteger
- BigIntegerArray
- BigDecimal
- BigDecimalArray
- DateTime
- DateTimeArray
- Object
- ObjectArray
- FileContent
По умолчанию используются числовые типы максимального размера: BigInteger и BigDecimal. Если известно, что передаваемые значения не превышают допустимые границы для меньших типов, можно использовать типы Long и Double — это улучшит производительность.
ObjectArray и Object — сложные типы. Элемент метаданных должен содержать поле "struct", описывающее структуру объекта. ObjectArray — всегда массив объектов, поэтому для описания типа его элементов также достаточно поля "struct", описывающего структуру его элемента.
Закрытие сессии
Пример закрытия сессии:
{
"uuid":"731d5558-f474-4a27-94e0-4008b60ca48d",
"cmd":"close",
"data":{}
}
Где:
uuid— уникальный идентификатор сессииcmd— команда закрытия данныхdata— пустой объект данных
Пример ответа:
{
"uuid":"731d5558-f474-4a27-94e0-4008b60ca48d"
}
Где uuid — уникальный идентификатор запроса.
Логирование
{
"cmd": "log",
"data": {
"level": "INFO",
"text": "Received value var_1=123"
}
}
Где:
cmd— команда закрытия сессииdata— пустой объект данных
Идентификатор запроса не требуется — ответ не ожидается и не обрабатывается (по принципу fire-and-forget).
Список уровней логирования:
ERRORWARNINFODEBUGTRACE
Обработка ошибок
В ответ на любой запрос можно вернуть ошибку.
{
"uuid":"f6a820f5-34c4-4c23-bb51-2bffa26d9898",
"cmd": "error",
"data": {
"code": "unknown_error",
"text": "Непредвиденная ошибка",
"params": [{
"name": "file",
"value": "vkK8Og2BNyPnJ15wp5Mc.tmp"
}]
}
}
Где:
uuid— уникальный идентификатор запросаcmd— команда ошибкиdata— объект данныхcode— код ошибкиtext— текст сообщенияparams— параметры ошибкиname— имя параметраvalue— значение параметра
Была ли статья полезна?