Verdi
Описание команд всех сервисов, которые входят в состав Verdi.
Список версий
v9.0.0
Прочие изменения
- Frontend
- components
- cor-table
- Изменено поведение ввода страницы в пагинации - добавлена маска.
- Использован компонент cor-single-select для выбора количества элементов на странице
- Пагинация приведана по стилям к макетам
- cor-input
- Удалена директива small у customIcon
- Добавлены иконки cross-s, search-small, delete-s в выбор customIcon в storybook
- theme
- Стили ссылки приведены к макетам
- Добавлены переменные для text-link(primary|secondary) для состояний
hover,focused - Создан файл text-link.scss с стилями ссылки
- theme-ui
- Исправлен баг с трясущимся табом на особенных шрифтах
v4.0.0
Ломающие изменения
UI
- Изменено определение завершения сессии пользователя: при получением HTTP ответа со статусом "401 UNAUTHORIZED" и ErrorResponse с "businessError" = "SES001" будет сделан редирект на страницу входа в систему.
api-gateway
- Изменена обработка завершения сессии пользователя (у jwt закончился срок действия): при получении недействительного jwt будет возвращен ответ со статусом "401 UNAUTHORIZED" и ErrorResponse с "businessError" = "SES001".
data-model
- Изменен Action для проверки прав в команде "listFilesInfoWithTags". Новый action: "DataModel_ListFilesInfo".
verdi-libs
- Добавлена возможность сменить топик для записи событий журнала, чтобы миновать команды Nestor и использовать другой сервис для обработки таких команд. Это привело к изменению создания nestor-client: добавлены настройки "mode" и "topic".
Прочие изменения
alexandrina
- Новые переменные окружения для политики ретраев коннекта к Consul: ALEXANDRINA_SENDERLIB_CONSUL_CONNECTION_RETRY_MAX, ALEXANDRINA_SENDERLIB_CONSUL_CONNECTION_RETRY_DELAY
- В команде searchCatalogs была исправлены ошибки при сортировке по умолчанию и при парсинге json
api-gateway
- исправление ошибки конфигов для политики ретраев коннекта к Consul без изменения имен переменных окружения: APIGATEWAY_CONSUL_RETRY_MAX, APIGATEWAY_CONSUL_RETRY_DELAY
- при обработке команды mon_http_ChangeUserPassword проверка валидности jwt токена игнорирует ошибку истечения срока действия пароля
- теперь header команд LoginBy пробрасывается в ответ к пользователю только в случае успеха
- Команды mon_http_LoginByCredentials, mon_http_LoginByKerberos, mon_http_LoginByKeycloak, mon_http_GetKeycloakAuthUrl теперь доступны и с плохим jwt(чтобы пользователь мог обновить протухший jwt)
archiver
- новые переменные окружения для политики ретраев коннекта к Consul: ARCHIVER_SENDERLIB_CONSUL_CONNECTION_RETRY_MAX, ARCHIVER_SENDERLIB_CONSUL_CONNECTION_RETRY_DELAY
attila
- новые переменные окружения для политики ретраев коннекта к Consul: ATTILA_SENDERLIB_CONSUL_CONNECTION_RETRY_MAX, ATTILA_SENDERLIB_CONSUL_CONNECTION_RETRY_DELAY
command-status
- новые переменные окружения для политики ретраев коннекта к Consul: COMMAND_STATUS_SERVICE_CONSUL_RETRY_MAX, COMMAND_STATUS_SERVICE_CONSUL_RETRY_DELAY
data-model
- новые переменные окружения для политики ретраев коннекта к Consul: DATA_MODEL_SENDERLIB_CONSUL_CONNECTION_RETRY_MAX, DATA_MODEL_SENDERLIB_CONSUL_CONNECTION_RETRY_DELAY
erika
- Добавлена возможность отмены запроса с обработкой файла через передачу таймаута обработки (только для HTTP роутов "/convert" или "/report")
event-status
- новые переменные окружения для политики ретраев коннекта к Consul: EVENT_STATUS_SENDERLIB_CONSUL_CONNECTION_RETRY_MAX, EVENT_STATUS_SENDERLIB_CONSUL_CONNECTION_RETRY_DELAY
integration
- новые переменные окружения для политики ретраев коннекта к Consul: INTEGRATION_SENDERLIB_CONSUL_CONNECTION_RETRY_MAX, INTEGRATION_SENDERLIB_CONSUL_CONNECTION_RETRY_DELAY
mon
- новые переменные окружения для политики ретраев коннекта к Consul: MON_SENDERLIB_CONSUL_CONNECTION_RETRY_MAX, MON_SENDERLIB_CONSUL_CONNECTION_RETRY_DELAY
- Добавлена переменная MON_JWT_COOKIE_EXPIRE_OFFSET, которая добавляет смещение времени жизни jwt cookie относительно jwt токена. По умолчанию, переменная имеет значение "24h", чтобы продлить жизнь cookie и оставить управление токенами на стороне backend-а.
oberto
- новые переменные окружения для политики ретраев коннекта к Consul: OBERTO_SENDERLIB_CONSUL_CONNECTION_RETRY_MAX, OBERTO_SENDERLIB_CONSUL_CONNECTION_RETRY_DELAY
tech-constants
- новые переменные окружения для политики ретраев коннекта к Consul: TECH_CONSTANTS_SENDERLIB_CONSUL_CONNECTION_RETRY_MAX, TECH_CONSTANTS_SENDERLIB_CONSUL_CONNECTION_RETRY_DELAY
ui-storage
- новые переменные окружения для политики ретраев коннекта к Consul: UI_STORAGE_SENDERLIB_CONSUL_CONNECTION_RETRY_MAX, UI_STORAGE_SENDERLIB_CONSUL_CONNECTION_RETRY_DELAY
v3.3.0
Прочие изменения
- UI
- Была добавлена библиотека @foundation/theme-ui с разделом "Настройка темы"
- В corund/components был добавлен сервис для чтения конфига
- В app-config была добавлена настройка для переопределения css переменных
- Значение переменной "cssVariables" будет установлено для
document.documentElement.style
- Значение переменной "cssVariables" будет установлено для
- Обновлена цветовая палитра
- Добавлены ряд переменных с градациями основных цветов от 100 до 1000
- Добавлены контекстные переменные, названия которых соответствуют шаблону
type [-element][-appearance][-state][-interaction] - Подробнее про работу с цветами можно прочитать в конфлюенсе
- Все сервисы
- Обновлены версии бибилиотек, в которых были найдены уязвимости безопасности
- api-gateway
- Изменено поведение при скачивании и загрузке файлов
- Теперь UserContext запрашивается аналогичным образом, что и для команд (с учетом APIGATEWAY_TOKEN_HANDLING)
- Добавлены константы для ограничения анонимного доступа (добавляются в APIGATEWAY_ANONYMOUS_ACCESS_COMMANDS)
- "apigw_uploadFile" для доступа к /upload
- "apigw_downloadFile" для доступа к /download
- "apigw_getFileMeta" для доступа к /metadata
- Изменено поведение при скачивании и загрузке файлов
- indexation
- Добавлена возможность указывать произвольные параметры для плагинов индексации в описании индексации
v3.2.0
Прочие изменения
- alexandrina
- Добавлена переменная окружения ALEXANDRINA_KAFKA_PRODUCER_MESSAGE_MAX_BYTES, которая определяет лимит байт на отправку в топик по событиям команд
- data-model
- Добавлена переменная окружения DATA_MODEL_KAFKA_PRODUCER_MESSAGE_MAX_BYTES, которая определяет лимит байт на отправку в топик по событиям команд
- verdi-libs
- Добавлена настройка, которая определяет лимит байт на отправку в топик по событиям команд. Если размер payload-а в отправляемом сообытии превышает лимит, то payload будет замен на стандартное сообщение
"The command response size ($valueBytes) exceeded $valueMaxBytes bytes limit. The response could not be sent."- Ограничения на размер Kafka сообщения учитывают, что событие команды может содержать ErrorResponse и сохраняют эту структуру при замене payload
- Добавлена настройка, которая определяет лимит байт на отправку в топик по событиям команд. Если размер payload-а в отправляемом сообытии превышает лимит, то payload будет замен на стандартное сообщение
v3.1.0
Прочие изменения
Все сервисы
- Улучшенны логи для трассировки запросов
- Добавлен логер "com.embedika.verdi.CommandLogger" и настройка для выбора уровня логов "***_LOG_LEVEL_COMMANDLOGGER", где *** - уникальный префикс для сервиса.
- Улучшенны логи для трассировки запросов
alexandrina
- Добавлены переменные окружения для настройки kafka consumer: ALEXANDRINA_KAFKA_CONSUMER_POLL_TIMEOUT, ALEXANDRINA_KAFKA_CONSUMER_POLL_INTERVAL, ALEXANDRINA_KAFKA_CONSUMER_PROPS
apigateway
- Изменение логики привязки пользователя к загруженному им файлу через роут POST /upload. Теперь вместо локального кеша используется механизм ограничения доступа на уровне fsclient
- Добавлены переменные окружения для настройки kafka consumer/producer: APIGATEWAY_KAFKA_CONSUMER_POLL_TIMEOUT, APIGATEWAY_KAFKA_CONSUMER_POLL_INTERVAL, APIGATEWAY_KAFKA_CONSUMER_PROPS, APIGATEWAY_KAFKA_PRODUCER_PROPS
archiver
- Добавлены переменные окружения для настройки kafka consumer/producer: ARCHIVER_KAFKA_CONSUMER_POLL_TIMEOUT, ARCHIVER_KAFKA_CONSUMER_POLL_INTERVAL, ARCHIVER_KAFKA_CONSUMER_PROPS, ARCHIVER_KAFKA_PRODUCER_PROPS
attila
- Добавлены переменные окружения для настройки kafka consumer: ATTILA_KAFKA_CONSUMER_POLL_TIMEOUT, ATTILA_KAFKA_CONSUMER_POLL_INTERVAL, ATTILA_KAFKA_CONSUMER_PROPS
erika
- Ограничение доступа к генерируемым и конвертируемым файлам. Созданы новые команды для конвертации в ПДФ: convertToPdf2, convertToPdf2Async, доработаны существующие createReport, createReportAsync (в payload команд добавлено опциональное поле ownerUserId)
- В используемый тестами конфиг добавлен параметр, позволяющий игнорировать системное сообщение библиотеки генерации об используемой триальной лицензии, негативно влияющее на результаты тестов при их локальном запуске (достаточно указать переменную окружения
IGNORE_LICENSE_WARNING=true)
event-status
- Добавлены переменные окружения для настройки kafka consumer: EVENT_STATUS_KAFKA_CONSUMER_POLL_TIMEOUT, EVENT_STATUS_KAFKA_CONSUMER_POLL_INTERVAL, EVENT_STATUS_KAFKA_CONSUMER_PROPS
data-model
- Добавлены переменные окружения для настройки kafka consumer/producer: DATA_MODEL_KAFKA_CONSUMER_POLL_TIMEOUT, DATA_MODEL_KAFKA_CONSUMER_POLL_INTERVAL, DATA_MODEL_KAFKA_CONSUMER_PROPS, DATA_MODEL_KAFKA_PRODUCER_PROPS
integration
- Добавлены переменные окружения для настройки kafka consumer/producer: INTEGRATION_KAFKA_CONSUMER_POLL_TIMEOUT, INTEGRATION_KAFKA_CONSUMER_POLL_INTERVAL, INTEGRATION_KAFKA_CONSUMER_PROPS, INTEGRATION_KAFKA_PRODUCER_PROPS
mon
- Добавлены переменные окружения для настройки kafka consumer: MON_KAFKA_CONSUMER_POLL_TIMEOUT, MON_KAFKA_CONSUMER_POLL_INTERVAL, MON_KAFKA_CONSUMER_PROPS
nestor
- При использовании хранилища clickhouse теперь используется "кластерный режим"
- Изменен тип engine для таблицы с "MergeTree" на "ReplicatedMergeTree"
- Изменено значение по умолчанию для переменной CLICKHOUSE_CONNECT_TYPE на "cluster-aware" (опция "single-host" тоже досутпена)
- При использовании ENGINE_TYPE="clickhouse" теперь всегда требуется настраивать кластер clickhouse, даже если у вас используется одна нода (опция "single-host" на это не виляет).
- При использовании хранилища clickhouse теперь используется "кластерный режим"
oberto
- Добавлены переменные окружения для настройки kafka consumer: OBERTO_KAFKA_CONSUMER_POLL_TIMEOUT, OBERTO_KAFKA_CONSUMER_POLL_INTERVAL, OBERTO_KAFKA_CONSUMER_PROPS
tech-constant
- Добавлены переменные окружения для настройки kafka consumer: TECH_CONSTANTS_KAFKA_CONSUMER_POLL_TIMEOUT, TECH_CONSTANTS_KAFKA_CONSUMER_POLL_INTERVAL, TECH_CONSTANTS_KAFKA_CONSUMER_PROPS
ui-storage
- Добавлены переменные окружения для настройки kafka consumer: UI_STORAGE_KAFKA_CONSUMER_POLL_TIMEOUT, UI_STORAGE_KAFKA_CONSUMER_POLL_INTERVAL, UI_STORAGE_KAFKA_CONSUMER_PROPS
user-profile
- Добавлены переменные окружения для настройки kafka consumer: USER_PROFILE_CONSUMER_POLL_TIMEOUT, USER_PROFILE_CONSUMER_POLL_INTERVAL, USER_PROFILE_CONSUMER_PROPS
verdi-libs
- Расширение api fs-client:
- В metadata добавлено опциональное поле "ownerUserId", в которое указывается id пользователя (UUID). Если поле заполнено, то файл будет доступен только указанному пользователю.
- Добавлены методы, реализующую логику привязки файлов к пользователю: uploadPrivate(), moveWithAccessControl(), copyWithAccessControl(), copyAndUpdateAccessSettings();
- расширена логика методов получения информации по файлу (теперь учитывают опциональную привязку файла к пользователю при передаче ownerUserId): get(), getMeta(), getManaged().
- Опциональная metadata в fs-client:
- Методы на чтение заменяют metadata на fallback, если она отсутствует.
- Методы для копирования и удаления игнорируют отсутствие metadata.
- Новые параметры конструктора StreamingKafkaConsumer:
- parallelism - параллелизм обработки сообщений в одной партиции
- pollTimeout - timeout запроса poll
- pollInterval - интервал между запросами poll
- consumerProperties - дополнительные параметры для kafka consumer
- Расширение api fs-client:
v3.0.0
Ломающие изменения
nestor
- Изменены модели
NewEventиEvent, возможны ошибки компиляции. Чтобы снизить кол-во проблем добавлены конструкторы для прежнего формата- Поле "userId" теперь имеет тип UserId вместо String.
- Теперь при поиске с помощью InSetQuery событий, у которых userId = "", будут возвращены ТОЛЬКО СТАРЫЕ события от лица анонимного пользователя. Новые события, записанные анонимным пользователем, имеют userId = UserId.Anonymous. Для того, чтобы получить все события от лица анонимных пользователей нужно искать события, у которых userId = UserId.Anonymous.
- Изменены модели
verdi-libs
- Layer FsClientCreator.liveDepend теперь потенциально может вернуть ошибку FSManagerConnectionError
- Ошибка FSConnectionError разделена на две ошибки: FSClientConnectionError и FSManagerConnectionError
- Изменилось поведение метода "ErrorResponse.fromThrowable": теперь учитывается исключения из БД о "дублях", которое будет иметь следующий message "ERROR: duplicate value - $field=$value already exists".
Прочие изменения
alexandrina
- Для поля "title" у CatalogItem был увеличен лимит на максимальную длину с 1500 до 10000 символов.
- Добавлены необязательные переменные ALEXANDRINA_FS_TARGET_THROUGHPUT_IN_GPS, ALEXANDRINA_FS_MINIMUM_PART_SIZE_IN_BYTES, ALEXANDRINA_FS_CHECKSUM_VALIDATION_ENABLED
apigateway
- Добавлены необязательные переменные APIGATEWAY_FS_TARGET_THROUGHPUT_IN_GPS, APIGATEWAY_FS_MINIMUM_PART_SIZE_IN_BYTES, APIGATEWAY_FS_CHECKSUM_VALIDATION_ENABLED
- Добавлены переменные окружения APIGATEWAY_FS_TARGET_THROUGHPUT_IN_GPS, APIGATEWAY_FS_MINIMUM_PART_SIZE_IN_BYTES, APIGATEWAY_FS_CHECKSUM_VALIDATION_ENABLED
- Добавлена поддержка множественных лицензий
archiver
- Были удалены переменные окружения ARCHIVER_FS_CACHE_SIZE и ARCHIVER_FS_CACHE_TTL т.к. они не используются в сервисе.
data-model
- Добавлены необязательные переменные DATA_MODEL_FS_TARGET_THROUGHPUT_IN_GPS, DATA_MODEL_FS_MINIMUM_PART_SIZE_IN_BYTES, DATA_MODEL_FS_CHECKSUM_VALIDATION_ENABLED
datamodel
- Исправлена ошибка в командах updateObjectFieldsList и deleteObjectSearch при указании только relation фильтров
erika
- Добавлены необязательные переменные FS_TARGET_THROUGHPUT_IN_GPS, FS_MINIMUM_PART_SIZE_IN_BYTES, FS_CHECKSUM_VALIDATION_ENABLED
indexation
- Добавлены необязательные переменные FS_TARGET_THROUGHPUT_IN_GPS, FS_MINIMUM_PART_SIZE_IN_BYTES, FS_CHECKSUM_VALIDATION_ENABLED
- Исправлен текст констант
integration
- Добавлены необязательные переменные INTEGRATION_FS_TARGET_THROUGHPUT_IN_GPS, INTEGRATION_FS_MINIMUM_PART_SIZE_IN_BYTES, INTEGRATION_FS_CHECKSUM_VALIDATION_ENABLED
lamp-client
- Добавлены необязательные переменные FS_TARGET_THROUGHPUT_IN_GPS, FS_MINIMUM_PART_SIZE_IN_BYTES, FS_CHECKSUM_VALIDATION_ENABLED
mon
- Добавлены необязательные переменные MON_FS_TARGET_THROUGHPUT_IN_GPS, MON_FS_MINIMUM_PART_SIZE_IN_BYTES, MON_FS_CHECKSUM_VALIDATION_ENABLED
- Добавлены переменные MON_FS_AUTH_MODE, MON_FS_AUTH_CONFIG, MON_FS_CACHE_SIZE, MON_FS_CACHE_TTL
- Теперь в сервисе используется кэширующий FSClient, который умеет принимать разные креды для разных бакетов
- Добавлена поддержка множественных лицензий
nestor
- В nestor добавлено преобразование пустого userId, получаемого в событии, из пустой строки в UserId.Anonymous(00000000-0000-0000-0000-000000000000)
- Теперь при поиске с помощью InSetQuery событий, у которых userId = UserId.Anonymous, будут возвращены также и события, у которых userId = "". При этом likeQuery такой функциональностью не обладает.
- Исправлены проблемы с фильтром Search с хранилищем ClickHouse
- Исправлены тексты ошибок валидации
oberto
- Добавлена поддержка множественных лицензий
tagging-plugin
- Добавлены необязательные переменные FS_TARGET_THROUGHPUT_IN_GPS, FS_MINIMUM_PART_SIZE_IN_BYTES, FS_CHECKSUM_VALIDATION_ENABLED
ui-storage
- Добавлены необязательные переменные UI_STORAGE_FS_TARGET_THROUGHPUT_IN_GPS, UI_STORAGE_FS_MINIMUM_PART_SIZE_IN_BYTES, UI_STORAGE_FS_CHECKSUM_VALIDATION_ENABLED
verdi-libs
- S3AsyncClient из библиотеки "software.amazon.awssdk.s3" заменен на S3CRTAsyncClient
- FsClientCreator.live и FsClientCreator.liveFromConfig теперь по умолчанию используют S3CRTAsyncClient
- В FSConfig и FSConfigRep добавлены параметры targetThroughputInGbps, minimumPartSizeInBytes, checksumValidationEnabled
- В FsClientCreator добавлены методы создания S3CRTAsyncClient, методы создания S3AsyncClient помечерены как deprecated
- Добавлены базовые интерфейсы для работы с множественными лицензиями
- Доработаны модели сервиса nestor
v2.1.0
Прочие изменения
mon
- Исправлены проблемы, когда ограничение лицензии activeUserLimit действовало и на привилегированных пользователей.
- Исправлена проблема, когда ограничения лицензии применялись к команде "mon_http_LoginByCredentials", которая не проходила валидацию.
Был добавлен buzzer-client
v2.0.0
Ломающие изменения
verdi-libs
- В трейте
com.embedika.verdi.senderlib.ServiceHealthApiдобавлены новые методы для управления ready статусом.
- В трейте
adapter_folder
- Директория перенесена из репозитория Cursor в репозиторий Verdi
archiver
- Директория перенесена из репозитория Cursor в репозиторий Verdi
data-model
- Директория перенесена из репозитория Cursor в репозиторий Verdi
data-model-client
- Изменено название пакета с "com.embedika.cursor" на "com.embedika.verdi" т.к. изменился репозиторий.
- Директория перенесена из репозитория Cursor в репозиторий Verdi
indexation
- Директория перенесена из репозитория Cursor в репозиторий Verdi
integration
- Директория перенесена из репозитория Cursor в репозиторий Verdi
intelligent-plugins/linkplugins
- Директория перенесена из репозитория Cursor в репозиторий Verdi
lamp-client
- Директория перенесена из репозитория Cursor в репозиторий Verdi
server-common
- Директория перенесена из репозитория Cursor в репозиторий Verdi
ui-storage
- Директория перенесена из репозитория Cursor в репозиторий Verdi
- В FormType удалено поле "id". Теперь в качестве primaryKey используется поле "code".
- Тип формы "searchFilter" переименован в "filterPanel"
- Типы форм "graphInfo", "graphPopup", "plagiarismList", "smartSearchSnippet", "textSearchSnippet" удалены. Ранее типы были "захардкожены" в сервисе, теперь их нужно добавлять с помощью переменной "UI_STORAGE_ADDITIONAL_FORM_TYPES".
- Пример для "UI_STORAGE_ADDITIONAL_FORM_TYPES": "graphInfo, Панель информации в графе, Панель информации в графе; graphPopup, Всплывающее окно в графе, Всплывающее окно в графе; plagiarismList, Список содержательных пересечений, Список объектов, с которыми найдены содержательные пересечения; smartSearchSnippet, Сниппет интеллектуального поиска, Сниппет интеллектуального поиска; textSearchSnippet,Сниппет текстового поиска, Сниппет текстового поиска".
- Настройки удаленных типов форм (EntityFormSettings) были сохранены в таблицу "OldEntityFormSettings". Данные из этой таблицы можно скопировать в таблицу "EntityFormSettings" после добаления типов через переменную "UI_STORAGE_ADDITIONAL_FORM_TYPES".
user-profile
- Директория перенесена из репозитория Cursor в репозиторий Verdi
Прочие изменения
verdi-libs
- Добавлено описание для роутов:
/health,/ready - Добавлены ready route
- Для сущности
JwtInvalidationIdреализована стандартная ошибка в случае если значение отличается отstring
- Добавлено описание для роутов:
alexandrina
- Добавлен
/readyроут
- Добавлен
alexandrina-client
- Документация приведена к best practice
apigateway
- Добавлен
/readyроут
- Добавлен
archiver
- Добавлен
/readyроут
- Добавлен
attila
- Добавлен
/readyроут
- Добавлен
buzzer
- Добавлен
/readyроут
- Добавлен
buzzer-email
- Добавлен
/readyроут - изменено значение по умолчанию для
VERDI_KAFKA_TOPIC. Теперь оно равноcommandevents. - изменено значение по умолчанию в документации для
VERDI_KAFKA_TOPIC.
- Добавлен
buzzer-personal-page
- Добавлен
/readyроут - изменено значение по умолчанию для
VERDI_KAFKA_TOPIC. Теперь оно равноcommandevents. - изменено значение по умолчанию в документации для
VERDI_KAFKA_TOPIC.
- Добавлен
buzzer-subscription
- Добавлен
/readyроут - изменено поле name публикуемых констант в соответствии с https://confluence.dev.embedika.ru/pages/viewpage.action?pageId=39617917.
- Добавлен
commandstatus
- Добавлен
/readyроут - Изменено значение по умолчанию для
COMMAND_STATUS_SERVICE_STATUS_TOPIC. Теперь оно равноcommandevents.
- Добавлен
data-model
- Добавлен
/readyроут - Исправлено описание команды
updateKeywordsв документации
- Добавлен
erika
- Добавлен
/readyроут - изменено значение по умолчанию в документации для
VERDI_KAFKA_TOPIC.
- Добавлен
event-status
- Добавлен
/readyроут
- Добавлен
intergration
- Добавлен
/readyроут
- Добавлен
indexation
- Добавлен
/readyроут - Изменено значение по умолчанию для
VERDI_KAFKA_TOPIC. Теперь оно равноcommandevents. - Изменено значение по умолчанию в документации для
VERDI_KAFKA_TOPIC. - Добавлена документация для шага индексации Keyword
- Добавлены условия успешного прохождения шага индексации Plugin
- Добавлен
lamp-client
- Добавлен
/readyроут - Изменено значение по умолчанию для
VERDI_KAFKA_TOPIC. Теперь оно равноcommandevents. - Изменено значение по умолчанию в документации для
VERDI_KAFKA_TOPIC.
- Добавлен
plagiarismPlugin
- Добавлена документация для core-части плагинов, согласно Best practice для plagiarismPlugin, добавлена документация некоторых моделей в commonDocs, описание модели entityObject перенесено из dataModel.md в commonDocs.md
similarityPlugin
- Добавлена документация для similarityPlugin
- В документации сервиса indexation добавлена ссылка на документацию по similarityPlugin
tagging-plugin
- Добавлена документация к tagging-plugin и ссылка на эту документацию в документации сервиса indexation
mon
- Добавлен
/readyроут - Поле
newDeactivateAtмоделиUpdateDeactivationTimeInputтеперь опциональное. - Удалены неиспользуемые переменные MON_KAFKA_CONSUMER_GROUP, MON_JWT_ENCRYPTION.
- Переменной MON_JWT_SIGNATURE установлено значение по умолчанию аналогичное тому,
- Добавлен
nestor
- Добавлен
/readyроут - Исправлен текст ошибки валидации
- изменено значение по умолчанию в документации для
VERDI_KAFKA_TOPIC.
- Добавлен
oberto
- Добавлен
/readyроут
- Добавлен
tech-constants
- Добавлен
/readyроут
- Добавлен
ui-storage
- Добавлен
/readyроут - Расширена логика миграции, которая удаляет FormType, не входящие в базовый набор. При удалении настроек EntityFormSettings, связанных с удаленными FormType, будет создана копия данных в в таблице OldEntityFormSettings. Это сделано для простоты добавления настроек, если они понадобятся.
- Добавлены переменные UI_STORAGE_ADDITIONAL_FORM_TYPES, UI_STORAGE_ADDITIONAL_FORM_TYPES_MODE и логика добавления дополнительных форм тайпов на старте сервиса
- Добавлен
user-profile
- Добавлен
/readyроут - Изменено значение по умолчанию для
VERDI_KAFKA_TOPIC. Теперь оно равноcommandevents. - Изменено значение по умолчанию в документации для
VERDI_KAFKA_TOPIC.
- Добавлен
v1.12
Ломающие изменения
ApiGateway
- Перед выполнением команд была добавлена проверка срока действия пароля. Если срок действия истек, то вместо выполнения команды будет возвращена ошибка с требованием сменить пароль (businessError=PWD001) и HTTP Stratus 401.
Mon-core
- MainAppModule теперь требует наличия инстансов FromCompletableFuture и ToCompletableFuture
- пример добавления требуемых инстансов в gitlab
- MainAppModule теперь требует наличия инстансов FromCompletableFuture и ToCompletableFuture
Mon
- В mon-core был добавлен тип "ProviderKey" для передачи идентификатора пользователя в провайдере пользовательских данных. Ранее это значение пеередавалось как тип "String".
Nestor
- Добавлена проверка прав для команды updateEventsTemplate
Прочие изменения
verdi-libs
- В структуру UserContext добавлено новое поле "passwordExpirationDateOpt" с типом Option[TimeStamp]. Поле содержит опциональную дату завершения действия пароля.
Mon-models
- Добавлен object notificationLimitError
Mon-core
- Команда RegisterUser теперь учитывает присланные пользователем заголовки
- Добавлены классы NotificationSettings, NotificationService и NotificationServiceImpl
- Добавлены izumi модули DummyNotificationSettingsModule, NotificationSettingsModule, NotificationModule
- Объект EncryptionOps добавлены методы getSipHashKey, encryptWithSipHash и encryptBytesWithSipHash
Mon
- Изменено формирование и проверка хеша пароля пользователя
- Добавлено опциональная подтверждение почты при регистрации
- Добавлены переменные окружения
- MON_EXTERNAL_VERIFY_ENABLED
- MON_EXTERNAL_VERIFY_URL
- Добавлены переменные окружения
- Добавлена опциональная переменная окружения MON_KRB_LDAP_USER_OBJECT_ID для получения SID при выполнении команды "mon_http_LoginByKerberos".
- Теперь при выполнении команды "mon_http_LoginByKerberos" будет использоваться SID пользователя. Если SID получить не удалось или такой пользователь не найден в Mon, то будет использован "логин" для поиска пользователя пользователя.
- Из-за изменения структуры UserContext в verdi-libs, также изменились ответы команд "mon_http_UserCommandContextData" и "mon_http_UserCommandContextData_OauthAccessToken": было добавлено поле "passwordExpirationDateOpt".
- Добавлены переменные MON_EMAIL_NOTIFICATION_DELAY_PER_USER, MON_EMAIL_NOTIFICATION_LIMIT_ENABLE, MON_EMAIL_NOTIFICATION_ADDITIONAL_IDENTITY_HEADERS.
Mon-client
- Добавлен клиент сервиса Mon
Tech-constants
- Добавлено поле modified с датой последнего изменения константы в ответ команд techConstants_GetConstant, techConstants_ListAllConstants, techConstants_ListConstantsByType
Nestor
- Добавлено журналирование команды updateEventsTemplate
- Теперь при вызове updateEventsTemplate обращения к БД не происходит для событий, у которых не изменилось поле renderedData
- Исправлен баг - теперь поле updated в результате вызова команды updateEventsTemplate равно настоящему количеству обновленных записей
- Удален файл mustache для события OldestIndexDeleted
v1.11.7
Прочие изменения
Oberto
- Исправлена проблема, когда в контексте для AttributeProvider не передавались атрибуты с несколькими значениями.
Buzzer-core
- Исправлена проблема отправки уведомлений, когда в передаваемых данных для шаблона уведомления был null. Если вместо ожидаемого значения в поле будет передан null, то теперь уведомление все равно будет отправлено, но при отрисовки шаблона будет подставлена пустая строка вместо ожидаемого значения поля.
- Изменена версия для публикации: теперь версия соответствует версии релиза verdi.
v1.11.6
- DesignSystem/web
- В компонент "Календарь" добавлены новые input-ы для использования произвольных шаблонов отображения дней и footer-а.
v1.11.5
verdi-libs
- в FilterQueryHelper добавлены встроенные запросы AllInSetQuery, InSetQuery, LikeQuery, RangeQuery, TsQuery для произвольной jsonb-колонки в postgresql. Реализация содержится в классе JsonbColumnWithSearchQuery.
- Добавлен вывод CEF логов в формате JSON.
Alexandrina
- Добавлена поддержка фильтров AllInSetQuery, InSetQuery, LikeQuery, RangeQuery для вложенных полей metadata.
Oberto
- Исправлена проблема с зависанием при отправке большого количества одновременных запросов авторизации с использованием внешного attribute-provider.
Tech-constants
- Добавлены внутренние команды, которые не требуют авторизации:
- techConstants_UpsertAutoConstant_Internal
- techConstants_GetConstant_Internal
- techConstants_ListConstantsByType_Internal
- techConstants_ListAllConstants_Internal
- Добавлены внутренние команды, которые не требуют авторизации:
Ломающие изменения
Alexandrina
- Теперь в командах, поддерживающих фильтрацию по Search, в случае применения к полю неподдерживаемого фильтра возвращается ошибка "ERROR: Incorrect Search query: some message" с кодом 400
Tech-constants
- Добавлены проверки прав для получения и редактирования констант.
- Чтобы использовать сервис после обновления нужно или добавить политику на нужные команды (данные для политики указаны в документации сервиса) или использовать внутренние команды
- Проверка была добавлена для следующих команд
- techConstants_ListAllConstants
- techConstants_GetConstant
- techConstants_ListConstantsByType
- techConstants_UpsertAutoConstant
- techConstants_UpsertManualConstant
- techConstants_DeleteManualConstant
- techConstants_DeleteAutoConstant
- Добавлены проверки прав для получения и редактирования констант.
v1.11.4
Ломающие изменения
- verdi-libs
- Исправлен баг при аутентификации через Kerberos: теперь в kafka producer'е для отправки тестовых сообщений используется топик, для которого указаны настройки аутентификации.
- Из-за использования других топиков, теперь в них нужно будет обрабатывать события с "пустым ключем" (record.key = null) при аутентификации через Kerberos.
- Пример:
- Настроена аутентификация через Kerberos для кафка и для всех топиков свои параметры для аутентификации (authMode = mapping).
- Есть топик "Topic1" для которого создается KafkaProducer в каком-то из сервисов.
- Все кто читают топик "Topic1" (в том числе другие сервисы) должны уметь игнорировать входящие сообщения с "пустым ключем" (record.key = null).
Прочие изменения
Erika
- Для существующих команд были добавлены асинхронные версии:
- convertToPdfAsync
- createReportAsync
- extractVarsAsync
Nestor
- Добавлена команда "updateEventsTemplate" для обновления шаблона в ранее сохраненных событиях журнала.
v1.11.3
Ломающие изменения
- Nestor
- Новое поле "renderedData" заполняется при сохранении в хранилище журнала. Из-за этого для уже сохраненных записей это поле будет пустым.
Прочие изменения
Erika
- Добавлена проверка загрузки шрифтов из удаленного хранилища.
- Если не все шрифты были загружены, то сервис помечается "нездоровым" в ответе по роуту /health.
Nestor
- Добавлено новое поле "renderedData", которое зависит от "data" и содержит примененный шаблон для события.
- Для нового поля были добавлены фильтры "LikeQuery" (поиск по подстроке) и "TsQuery" (полнотекстовый поиск).
v1.11.2
Прочие изменения
Применены изменения из v1.10.1:
- verdi-libs
- исправлен баг: теперь значение переменной VERDI_KAFKA_CONNECTION_CHECK_FAILED_AFTER_INTERVAL учитывается и при использовании zio-kafka producer'a
v1.11.1
Прочие изменения
Ссылки в изменениях v1.11 теперь кликабельны.
Mon
- Для команд "mon_http_ListGroups" и "mon_http_ListGroupsByUserId" был добавлен фильтр "LikeQuery" для поля "groupId".
v1.11
Ломающие изменения
verdi-libs
- Из-за добавления класса KafkaClientProperties (для передачи произвольных параметров kafka клиентов) расширены:
- конструктор класса SimpleStreamingKafkaProducer
- метод VerdiFactory.create
- merge request с обновлением: https://gitlab.dev.embedika.ru/verdi/verdi/-/merge_requests/923/diffs
- Для решения проблемы с разлогином в Kafka были добавлены настройки "KafkaConnectionCheckConfig":
- VerdiTF.make и VerdiFactory.create теперь требуют передавать им идентификатор в поле "serviceId"
- Теперь для использования kerberos в producer при создании нужно будет передать класс "KafkaConnectionCheckConfig"
- merge request с обновлением: https://gitlab.dev.embedika.ru/verdi/verdi/-/merge_requests/871/diffs
- Изменен tech-constant-client
- Сделан единый интерфейс "TechConstantsClient"
- merge request с обновлением: https://gitlab.dev.embedika.ru/verdi/verdi/-/merge_requests/912/diffs
Alexandrina
- Добавлено новое поле "isProtected" в несколько команд и его обработка
- Для команды "ImportCatalogs" добавлено новое поле во входные параметры "CatalogExchangeDTO": поле "ignoreProtection" (по умолчанию "false") - признак игнорирования защиты от изменений при импорте.
- Изменен результат команды "ImportCatalogs". Новая модель "ImportResultDTO" содержит информацию о кодах данных которые не получилось загрузить.
- В команды "CreateCatalog", "UpdateCatalog", "CreateCatalogItem", "UpdateCatalogItem", "ArchiveCatalogItem", "ImportCatalogs" добавлен флаг "isProtected" (по умолчанию "true") защищающий данные от изменений.
- Обновленная логика импорта:
- При вызове ImportCatalogs ищем справочник/элемент по code:
- Если объект отсутствует - производим импорт (заменяем metadata и поля объекта);
- Если объект присутствует, и protected = false - производим импорт;
- Если объект присутствует, protected = true и ignoreProtection = false:
- Данные из БД должны остаться неизменными, не заменяются (поля "code", "title" для каталога и "code", "title", "archived" для Item);
- Новые "items" для каталога импортируются и создаются;
- Если в данных импорта для поля "metadata" (для каталога и его item) есть новые атрибуты, которых нет в БД - выполнить json merge (объединение полей) без замены уже существующих в БД полей
- Если объект присутствует, protected = true и ignoreProtection = true
- Производим импорт (заменяем metadata и поля объекта)
- Если в данных поля "metadata" (для каталога и его item) в БД есть атрибуты, которых нет в данных импорта то они должны сохраниться - выполнить json merge с заменой уже существующих в БД полей
ApiGateway
- Изменена структура конфига для настроек кеша UserInfo: теперь используется "VerdiCacheConfig" из "verdi-cache"; в application.conf были изменены названия полей "app.userInfoCache.maxCapacity" -> "app.userInfoCache.maxSize" и "app.userInfoCache.duration" -> "app.userInfoCache.elementTTL"
CommandStatus
- Для переменной окружения "COMMAND_STATUS_SERVICE_STATUS_CACHE_CLEAN_CHECK" изменено значение по умолчанию: вместо 10 мс, теперь 100 мс.
Nestor
- Изменены названия переменных окружения:
- "EVENTSTORAGE_MEMORY_ALERT_PERCENT" => "EVENTSTORAGE_MEMORY_WARNING_PERCENT"
- "EVENTSTORAGE_MEMORY_REWRITE_PERCENT" => "EVENTSTORAGE_MEMORY_CRITICAL_PERCENT"
Прочие изменения
verdi-libs
- Добавлен класс KafkaClientProperties для передачи произвольных параметров в kafka клиенты
- Исправление проблемы с разлогином Kafka при использовании Kerberos
Все сервисы
- Добавлено логирование используемой лицензии
- Добавлены константы для уведомления о лицензионных ограничениях (передаются в поле ErrorResponse.businessError)
- Обновлен tech-constant-client
ApiGateway
- Добавлены настройки для работы с AccessToken: можно указывать HTTP заголовки, cookie и команды, которые обрабатывают запрос на получение UserContext
CommandStatus
- Изменен механизм подписки на события команд при выполнении команды "pollStatus". Теперь подписки проверяются принудительно, а не при обновлении статуса.
- Добавлены новые переменные окружения:
- COMMAND_STATUS_SERVICE_STATUS_CACHE_SUBSCRIPTION_CHECK
- COMMAND_STATUS_SERVICE_AKKA_DEFAULT_DISPATCHER_EXECUTOR
- COMMAND_STATUS_SERVICE_AKKA_DEFAULT_DISPATCHER_THROUGHPUT
- COMMAND_STATUS_SERVICE_AKKA_FJP_PARALLELISM_MIN
- COMMAND_STATUS_SERVICE_AKKA_FJP_PARALLELISM_MAX
- COMMAND_STATUS_SERVICE_AKKA_FJP_PARALLELISM_FACTOR
- COMMAND_STATUS_SERVICE_AKKA_FJP_PARALLELISM_QUEUE_MODE
- COMMAND_STATUS_SERVICE_AKKA_DEFAULT_DISPATCHER_EXECUTOR
- COMMAND_STATUS_SERVICE_AKKA_DEFAULT_DISPATCHER_THROUGHPUT
- COMMAND_STATUS_SERVICE_AKKA_DEFAULT_BLOCKING_FIXED_POOL_SIZE
Nestor
- Изменено поведение Nestor при недостатке места: вместо удаления старых записей, новые не добавляются.
Mon
- Добавлена аутентификация внешних систем через Mon.
Mon-core
- Новая библиотека, которая предоставляет базовый функционал сервиса Mon
- Нужна для создания custom реализации сервиса Mon
v1.10.2
Ломающие изменения
- Nestor
- Новое поле "renderedData" заполняется при сохранении в хранилище журнала. Из-за этого для уже сохраненных записей это поле будет пустым.
Прочие изменения
- Nestor
- Добавлено новое поле "renderedData", которое зависит от "data" и содержит примененный шаблон для события.
- Для нового поля были добавлены фильтры "LikeQuery" (поиск по подстроке) и "TsQuery" (полнотекстовый поиск).
v1.10.1
Прочие изменения
- verdi-libs
- исправлен баг: теперь значение переменной VERDI_KAFKA_CONNECTION_CHECK_FAILED_AFTER_INTERVAL учитывается и при использовании zio-kafka producer'a
v1.10
Ломающие изменения
verdi-libs
- Исправление timeout в serviceDiscovery.startServiceHealthChecking (CURS-2749)
- Изменены сообщения для актора "ServiceHealthActor": теперь сообщения Cure и Fall требуют "replyTo: ActorRef[HealthStatus]"
- Добавлен стандартный таймаут для всех методов в trait-е "ServiceHealthApi": implicit timeout: Timeout = Timeout(1.second)
- Исправление разлогина Kafka при аутентификации через Kerberos (CURS-2780)
- VerdiTF.make и VerdiFactory.create теперь требуют передавать им serviceId
- Теперь для использования kerberos в SimpleStreamingKafkaProducer при создании нужно будет передать класс KafkaConnectionCheck
- Примеры изменений https://gitlab.dev.embedika.ru/cursor/cursor/-/merge_requests/1875/diffs
- Исправление timeout в serviceDiscovery.startServiceHealthChecking (CURS-2749)
ApiGateway
- Добавление возможности выполнения команд с access token, вместо JWT (CURS-2778)
- Изменена структура конфига для настроек кеша UserInfo: теперь используется "VerdiCacheConfig" из " verdi-cache"; в application.conf были изменены названия полей "app.userInfoCache.maxCapacity" -> " app.userInfoCache.maxSize" и "app.userInfoCache.duration" -> "app.userInfoCache.elementTTL"
- Добавление возможности выполнения команд с access token, вместо JWT (CURS-2778)
Buzzer-Subscription
- Исправлена проблема с журналированием событий по групповым подпискам createGroupSubscription,
deleteGroupSubscription (CURS-2622)
- В конструкторе case class-а LiveCache появился дополнительный аргумент "absenceCaseChunkHandler: Option[ Set[Key] => F[Map[Key, Option[Value]]]] = None"
- Замечание: Если создавать LiveCache не напрямую через конструктор, а через объект CacheApi, то ничего не сломается
- Исправлена проблема с журналированием событий по групповым подпискам createGroupSubscription,
deleteGroupSubscription (CURS-2622)
Прочие изменения
verdi-libs
- Добавлены вспомогательные методы для создания типовых ошибок (CURS-69)
Все сервисы
- Добавлен вывод в лог сообщения, что сервис не здоров (CURS-80)
- Убрано логирование конфига на старте микросервисов (CURS-2540)
- Добавлена возможность записи логов в syslog (CURS-2596)
- Исправлены настройки соединения с БД в конфигурационных файлах (CURS-2716)
- добавлены настройки: autoCommit, schema, isolateInternalQueries, initializationFailTimeout
- добавлены комментарий по поводу initializationFailFast (Deprecated in slick 3.3.0)
- Исправлены проблемы с фазами выключения сервиса при использовании TerminationCoordinator (CURS-2750)
Alexandrina
- Для команд с Search добавилена информацию в документацию Slate про доступные фильтры и сортировки (CURS-85)
- Команды по работе с элементами справочников теперь возвращают стандартные ошибки (CURS-2128)
ApiGateway
- Добавлены переменные окружения для настройки размеров входящих HTTP запросов
- APIGATEWAY_AKKA_HTTP_PARSING_MAX_BYTES
- APIGATEWAY_AKKA_HTTP_PARSING_MAX_HEADER_COUNT
- APIGATEWAY_AKKA_HTTP_PARSING_MAX_HEADER_NAME_SIZE
- APIGATEWAY_AKKA_HTTP_PARSING_MAX_HEADER_VALUE_SIZE
- Добавлены переменные окружения для настройки размеров входящих HTTP запросов
Buzzer
- Исправлена обработка событий из kafka, для которых нет созданных настроек (CURS-2714)
Buzzer-personal-page
- Исправлен рендер сообщений с данными со значением null в команде searchPPNotifications (CURS-2772)
Buzzer-email
- Добавлено получение email (через сервис Mon) во время отправки уведомления по почте (CURS-262)
- Добавлены стандартный шаблон письма для восстановления пароля и настройки для отправки письма (CURS-2605)
Buzzer-subscription
- Добавлена команда для создания подписки на уведомления для группы пользователей createGroupSubscriptionBuzzer-subscription (CURS-2622)
- Добавлена команда для получения информации о групповой подписке getGroupSubscriptionBuzzer-subscription ( CURS-2625)
- Добавлена команда для обновления информации о групповой подписке updateGroupSubscriptionBuzzer-subscription ( CURS-2626)
- Добавлена команда для удаления подписки на уведомления для группы пользователей deleteGroupSubscriptionBuzzer-subscription (CURS-2633)
- Добавлена команда для получения списка подписок для групп listGroupSubscriptionBuzzer-subscription (CURS-2639)
CommandStatus
- Исправлены ошибки при запуске нескольких инстансев сервиса (CURS-2734)
Erika
- Реализована версия 2 генерации отчёта по шаблону (CURS-2582)
- Добавлена переменная окружения "PROCESSING_GENERATION_VERSION". По умолчанию имеет значение "1".
- Обновлен гайд по шаблонам https://confluence.dev.embedika.ru/pages/viewpage.action?pageId=579239989
- Реализована версия 2 генерации отчёта по шаблону (CURS-2582)
Mon
- Исправлена ошибка, когда команда mon_http_LoginByKerberos не журналировалась, если завершалась с кодом 409 ( CURS-2539)
- Добавлена генерация ссылки для письма во время выполнения mon_http_PasswordRecoverRequest (CURS-2605)
- Добавлена команда для получения списка групп пользователей со списком групп mon_http_ListUsersWithGroups ( CURS-2643)
- Добавлена возможность сортировки по полю "modified" для команды mon_http_ListUsers (CURS-2708)
- Теперь можно указывать поле data у объекта UserInfo при вызове команды mon_http_RegisterUser (CURS-2751)
- Добавлена команда для редактирования данных пользователя (CURS-2753)
- Добавлена возможность указывать срок действия для учетных записей (CURS-2767)
- Добавлена команда для редактирование срока действия учетных записей (CURS-2769)
- Добавлена возможность получения UserContext по access token для аутентификации внешних систем (CURS-2778)
- Исправлены мелкие проблемы с отображением пользователя в событиях журнала в зависимости от JWT (CURS-2676)
Nestor
- Добавлена поддержка Clickhouse в качестве хранилища журналов (CURS-2713)
v1.9.1
Исправлена логика работы health-роутов в большинстве сервисов
Mon
- Исправлены баги:
- При аутентификации привилегированных лицензией пользователей - меняется состояние пользователей Mon ( CURS-2723)
- Исправлены баги:
v1.9
В данном релизе есть ломающие изменения (смотри ниже)
verdi-libs
- Переписан fsclient. Отказались от использования zio-s3. (CURS-2475)
- Начали использовать логи в формате CEF не только при логировании в консоль, но и при логировании в файл ( CURS-2229)
- Заменен backend для логгера в сервисах с zio-logging (CURS-2437)
- Актуализированы настройки senderlib в сервисах (CURS-2438)
- Добавлена поддержку массивов в Search (CURS-2440)
- Из verdi-zio выделили библиотеку verdi-zio-test (CURS-2538)
- Добавлена возможность использования Kerberos keytab для логина в Kafka (CURS-2473)
Mon
- Реализована часть задач для восстановления пароля пользователя (CURS-193,CURS-2588,CURS-2589,CURS-2591)
- Добавлены Action на команды сервиса аутентификации Mon (CURS-2201)
- Журналируются изменения групп пользователя при аутентификации через Kerberos (CURS-2579)
- Лицензионное ограничение на проверку количества активных пользователей в сервисе Mon (CURS-2586)
- Команда создания подписки на уведомления для группы пользователей createGroupSubscription (CURS-2622)
- Исправлены баги:
- Не учитываются значения переменных окружения MON_KEYCLOAK_USER_* при регистрации/обновлении данных пользователя при аутентификации через Keycloak (CURS-2680)
- Не работает сортировка по полю description у команды ListGroups (CURS-2282)
Alexandrina
- Добавить Action на команды сервиса справочников Alexandrina (CURS-2200)
- Исправлены баги:
- Команда GetCatalogItemBatch возвращает все элементы всех справочников, если в теле запроса пустой массив ( CURS-2592)
Buzzers
- Исправлены переменные окружения для настройки работы buzzer-email с почтовым сервером (CURS-2627)
Oberto
- Доработан AttributeProvider (CURS-2637) (возможность подключать новые роуты для получения атрибутов)
Erika
- Исправлены баги:
- Erika не конвертирует некоторые файлы, сохраненные через LibreOffice 97-2003 (CURS-617)
- Сервис erika с настройкой VERDI_ALLOWED : false - не разворачивается без подключения к Consul (CURS-2521])
- При конвертации файла - не сохраняются шрифты исходного документа и заменяются на шрифты семейства DejaVu ( CURS-2562)
- Исправлены баги:
Ломающие изменения:
- Библиотека senderlib:
Удалена зависимость для log4j: slf4j-log4j12 Удален layout для логов в формате CEF: CEFLog4jLayout
- Микросервис Alexandrina:
Команда "GetCatalogItemBatch" теперь возвращает пустой список, если на вход был передан пустой список ID
v1.8
Важные изменения
- Добавлен функционал лицензирования (сервисы apigateway и oberto)
- В verdi-libs добавлен фильтр для поиска по нескольким значениям (CURS-2433)
Исправлены разнообразные баги.
Mon
- Добавлен фильтр для полнотекстового поиска по ФИО пользователя (CURS-2246)
- добавлено разлогинивание пользователя при его блокировке (CURS-149)
- Подняты версии библиотек (CURS-2474)
Oberto
- Добавлены политики "по умолчанию" (CURS-111)
v1.7.1
Важные изменения
- Добавлены параметры подключения к базе данных в шаблон конфигурации и во все релевантные конфигурации сервисов ( CURS-2415, SUP-118)
- Для лога реализована возможность отключения вывода в файл (CURS-2430, SUP-151)
v1.7
Важные изменения
Verdi-libs
- В целом по системе были подняты версии библиотек, чтобы избавиться от некоторых уязвимостей
- В senderlib реализован ретраер при синхронном обращении напрямую к сервису (CURS-163, SUP-10)
Mon
- Добавлена настройка использования атрибутов пользователя из Keycloak в атрибутах пользователя сервиса Mon ( CURS-2358, SUP-81)
- Добавлена команда осуществляющая завершение сеансов пользователя (CURS-2331, SUP-135)
- Журналируются изменения пользователя или его групп при аутентификации через Keycloak (CURS-2368, SUP-137)
v1.6.1
Важные изменения
Verdi-libs
- Добавлена возможность разделить учётные данные кафки для доступов producer и consumer (SUP-132, CURS-2307)
Mon
- Возможность завершить сеанс пользователя (SUP-135, CURS-2331)
Oberto (и другие микросервисы)
- Реализованы доработки позволяющие работать в системе без развернутого authzforce
v1.6
Важные изменения
Verdi-libs
- Изменена работа с топиками в Kafka (аутентификация) (CURS-294)
- Сервисы теперь падают с ошибкой если на старте не смогли зарегистрироваться в консуле (CURS-303)
- Добавлены логи в формате CEF в сервисы Cursor/Verdi (CURS-36, SUP-98)
Erika
- Erika теперь умеет работать с файлами, у которых расширение в верхнем регистре (CURS-301)
Mon
- Переработана схема авторизации пользователя через AD (CUR-2157)
- Команда для получения групп ролей пользователей одним запросом (CURS-70, SUP-99)
Nestor
- Поддержка OpenSearch в Nestor (SUP-97)
Oberto
- Перенос функционала authzforze в сервис Oberto (CURS-2123) подзадачи (CURS-365, CURS-364, CURS-366)
UI
- Angular обновлен до 16 версии в Verdi в webclients, apigatewayclient, graph, ui-plugins и vespa (CUR-2083)
- Создана библиотека "Конструктор схем" (CUR-2137)
Исправлены множественные недочеты в Slate
Полный список задач релиза зафиксирован в Confluence
v1.5.3
Verdi-libs
- StoredFile перенесен в fsClient (SUP-66)
Erika
- Исправлены ошибки при генерации документов с метками в таблицах (SUP-67)
Mon
- Содержимое jwt токена теперь генерируется корректно (SUP-100)
- Значительное улучшение функционала связанного с логином через AD (SUP-59, CUR-2158)
Oberto
- XML для операции ActivateRoot теперь формируется правильно (CUR-2130)
В нескольких сервисах выставлено дефолтное значение allowInternalCommands=true (SUP-77)
Исправлены различные недочеты в Slate
v1.5.2
Технический хотфикс
v1.5.1
Версия от 27.06.2023. Список изменений:
Verdi-libs
- Исправлена работа с бакетами S3 (авторизация, алиасы)
UI
- Добавлена возможность конфигурации компонента cor-select (SUP-69)
v1.5
Версия от 06.06.2023. Список изменений:
Общее
- Исправлена и дополнена документация в различных разделах Verdi
Verdi-libs
- Изменена работа с бакетами S3 (авторизация) (SUP-50)
ApiGateway
- Настройки Akka HTTP связанные с таймаутами вынесены в переменные окружения (SUP-51)
UI
- Доработан компонент многострочного ввода (SUP-38)
- Доработан компонент выпадающего списка (SUP-43)
- Добавлена поддержка long-polling (SUP-55)
v1.4.1
Версия от 03.05.2023. Список изменений:
- Alexandrina:
- Добавлен http-route для проверки жизни сервиса с помощью ServiceHealthApi
- Attila:
- Добавлен http-route для проверки жизни сервиса с помощью ServiceHealthApi
- Mon:
- Добавлен http-route для проверки жизни сервиса с помощью ServiceHealthApi
- Tech-constants:
- Добавлен http-route для проверки жизни сервиса с помощью ServiceHealthApi
v1.4
Версия от 22.03.2023. Список изменений:
- Verdi-libs:
- Переработан механизм создания Kafka-консьюмеров. Они принимают на вход актор для управления состоянием консьюмера. Актор отслеживает состояние консьюмера, выполняет перезапуск при ошибках
- Добавлен
ServiceHealthApiдля отслеживания текущего статуса сервиса. Может интегрироваться с управляющим актором для Kafka-консьюмеров, в этом случае при падении консьюмера будет остановлен и сам сервис - Исправлена ошибка фильтрации открытых диапазонов
- Добавлена библиотека
validationдля валидации входных данных команд и обработки ошибок в общем формате
- ApiGateway:
- Добавлена обязательность настроек для подключения к S3-хранилищу. Теперь сервис падает, если не может подключиться, а не просто выводит ошибку в логах и 404 по url для файлов
- CommandStatus:
- Увеличена надежность Kafka-консьюмера. Добавлено управление состоянием и перезапуски (аналогично verdi-libs)
- Erika:
- Исправлена ошибка, из-за которой слова дробились на несколько спанов
- Добавлена возможность использовать условную метку внутри абзаца
- Mon:
- Добавлена команда смены пароля
- Команды для списков пользователей теперь принимают
Search - Добавлена поддержка kerberos-аутентификации
- Команда верификации регистрации теперь не возвращает
null - Исправлены ошибки в документации
- Buzzer-*:
- Исправлена документация по buzzer-personal-page и buzzer-email
- Команда для получения своих уведомлений в ЛК теперь принимает
Search - Добавлена команда для получения уведомлений в ЛК для любых пользователей
- Добавлена команда для отметки уведомлений прочитанными
- Добавлена команда для получения списка ошибок отправки почтовых уведомлений
- Alexandrina:
- Добавлено журналирование ошибок при вызове команд
- Attila:
- Добавлена поддержка полей для
ResourceType. Их должен публиковать сервис, отвечающий за соответствующийResourceType. Добавлены команды для такой публикации.
- Добавлена поддержка полей для
- Oberto:
- Исправлены ошибки с неотображением условий в политиках
- Исправлены ошибки с журналированием операций обновления и удаления политик
Общие типы данных
Search
Для некоторых команд предусматривается фильтрация, сортировка и пагинация результата. Для этих целей был добавлен объект Search, который передается в качестве параметров к команде. Также в этот объект можно преобразовать фильтры из ответа авторизации AuthorizationResult.
Search - универсальный тип параметров списочного запроса. Он состоит из полей
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
| query | string | да | Строка с запросом, в котором указывается комбинация фильтров. Для запросов без фильтрации - пустая строка | Значения в строке должны быть указаны в поле context |
| context | json object | да | Контекст фильтров запроса. Объект, в котором ключ - это название фильтра, а значение - это значение фильтра. Для запросов без фильтрации - пустой объект | |
| sorting | Sorting | нет | Параметры сортировки данных | |
| paging | Paging | нет | Параметры пейджинга. В случае отсутствия данного поля, считается что пейджинг указан как "Номер страницы - 1, число элементов - 10". |
Filter query
Является строкой с запросом для фильтрации при выполнении команды. Запрос состоит из названий атрибутов фильтруемого ресурса и способов их комбинирования:
- "фильтр для поля" = название атрибута у ресурса, по которому предполагается поиск. Обычно это ресурс из результата команды.
- "комбинация фильтров" = бинарные операции
||и&&с возможностью группировки через круглые скобки(и).
Filter context
С помощью контекста передаются параметры для фильтрации полей из query.
Контекст является JSON объектом, который представляет собой тип Map[String, Json], где
- поле JSON объекта является ключом для
Map[String, Json]и должно быть упомянуто в поле query ( т.е. иметь название атрибута ресурса). - значение поля JSON объекта является контекстом для фильтра FilterQueryContext. Каждый фильтр имеет свой формат.
FilterQueryContext
Общий тип для всех видов фильтров. Существует несколько реализаций, у которых может поддерживаться несколько форматов для записи условия. Рекомендуется передавать все условия фильтрации в виде JSON объекта, как более очевидный формат.
InSetQuery
Фильтрация атрибута ресурса по списку значений.
Если значение атрибута ресурса является массивом, то условие фильтрации возвращает TRUE, если этот массив и список
значений для условия фильтрации пересекаются хотя бы по одному элементу.
Иначе условие фильтрации возвращает TRUE, если одиночное значение из атрибута соответствует хотя бы *одному значению
* из фильтра.
| Поле | Тип | Обязательное | Описание | Значение по умолчанию | Ограничения |
|---|---|---|---|---|---|
| values | List[string] | да | Список значений для условия фильтрации. | ||
| kind | "any" | да | Тип фильтра. Может принимать только значение "any". | ||
| negation | bool | нет | Необходимость отрицания результата фильтрации: FALSE -> TRUE. |
false |
Возможные форматы:
"some value"- строка из одного значения, которая преобразуется в объект{"values": ["some value"], "kind": "any", "negation": false}.- JSON объект, который содержит, как минимум, обязательные поля. Необязательные поля могут принимать значение null.
В формат с одной строкой нельзя добавить отрицание (negation), т.к. вся строка является значением для фильтра.
Например, "not some value" будет преобразовано в {"values": ["not some value"], "kind": "any", "negation": false}.
AllInSetQuery
Фильтрация массива из атрибута ресурса по списку значений. Условие фильтрации возвращает TRUE, если массив из
атрибута содержит все значения из фильтра.
Работает только для полей, являющихся массивом.
| Поле | Тип | Обязательное | Описание | Значение по умолчанию | Ограничения |
|---|---|---|---|---|---|
| values | List[string] | да | Список значений для условия фильтрации. | ||
| kind | "all" | да | Тип фильтра. Может принимать только значение "all". | ||
| negation | bool | нет | Необходимость отрицания результата фильтрации: FALSE -> TRUE. |
false |
Возможные форматы:
- JSON объект, который содержит, как минимум, обязательные поля. Необязательные поля могут принимать значение null.
LikeQuery
Фильтрация атрибута ресурса по шаблону. Условие фильтрации возвращает TRUE, если значение из атрибута соотвествует
шаблону.
Данный фильтр соответствует фильтру like из SQL.
Например, like в PostgreSQL.
| Поле | Тип | Обязательное | Описание | Значение по умолчанию | Ограничения |
|---|---|---|---|---|---|
| likequery | string | да | Шаблон для условия фильтрации. | ||
| kind | "like" | да | Тип фильтра. Может принимать только значение "like". | ||
| negation | bool | нет | Необходимость отрицания результата фильтрации: FALSE -> TRUE. |
false |
В поле likequery, помимо слов для условия, поддерживаются символы % - неограниченное кол-во любых символов, _ -
только один любой символ, которые можно использовать несколько раз подряд. Например, "%s_me thi__%".
Возможные форматы:
"like %some%value%"- строка из одного значения с указанием типа фильтра, которая преобразуется в объект{"likequery": "%some%value%", "kind": "like", "negation": false}.- JSON объект, который содержит, как минимум, обязательные поля. Необязательные поля могут принимать значение null.
Чтобы добавить отрицание (negation) в формат со строкой, нужно перед условием фильтрации добавить not, разделив
условие и отрицание пробелом. Например, "not like %anything%".
TsQuery
Фильтрация атрибута ресурса по условие
для полнотекстового поиска PostgreSQL. Условие
фильтрации возвращает TRUE, если значение из атрибута соотвествует условию.
Операторы: '&' - И, '|' - ИЛИ, ':*' - начало слова, также возможно отрицание через добавление '!'. Допустимо
использование логического объединения с помощью скобок '(' и ')'.
| Поле | Тип | Обязательное | Описание | Значение по умолчанию | Ограничения |
|---|---|---|---|---|---|
| tsquery | string | да | Условия полнотекстового поиска для фильтрации. | ||
| kind | "ts" | да | Тип фильтра. Может принимать только значение "ts". | ||
| negation | bool | нет | Необходимость отрицания результата фильтрации: FALSE -> TRUE. |
false |
В поле tsquery, помимо слов для условия, поддерживаются следующие операторы: & - И, | - ИЛИ, :* - начало слова,
также возможно отрицание через добавление ! перед словом.
Допустимо использование логического объединения с помощью скобок ( и ).
Возможные форматы:
"ts (Олег | Ольга | Wolfg:*) & !Игорь"- строка из одного значения с указанием типа фильтра, которая преобразуется в объект{"tsquery": "(Олег | Ольга | Wolfg:*) & !Игорь", "kind": "ts", "negation": false}.- JSON объект, который содержит, как минимум, обязательные поля. Необязательные поля могут принимать значение null.
Чтобы добавить отрицание (negation) в формат со строкой, нужно перед условием фильтрации добавить not, разделив
условие и отрицание пробелом. Например, "not ts !Митя".
RangeQuery
Фильтрация атрибута ресурса по условию вхождения в интервал из значения фильтра. Условие
фильтрации: from <= targetValue <= to.
| Поле | Тип | Обязательное | Описание | Значение по умолчанию | Ограничения |
|---|---|---|---|---|---|
| from | long | нет | Значение, с которого начинается интервал для фильтрации (входит в интервал). | ||
| to | long | нет | Значение, с которым заканчивается интервал для фильтрации (входит в интервал). | ||
| kind | "range" | да | Тип фильтра. Может принимать только значение "range". | ||
| negation | bool | нет | Необходимость отрицания результата фильтрации: FALSE -> TRUE. |
false |
Если поля from и to не указаны, то условие всегда вернет true.
Возможные форматы:
"10_20"- строка с двумя значениями интервала, которая преобразуется в объект{"from": 10, "to": 20, "kind": "range", "negation": false}."10_"- строка только с началом интервала, которая преобразуется в объект{"from": 10, "to": null, "kind": "range", "negation": false}."_20"- строка только с окончанием интервала, которая преобразуется в объект{"from": null, "to": 20, "kind": "range", "negation": false}."_"- строка без значений интервала, которая преобразуется в объект{"from": null, "to": null, "kind": "range", "negation": false}.- JSON объект, который содержит, как минимум, обязательные поля. Необязательные поля могут принимать значение null.
Чтобы добавить отрицание (negation) в формат со строкой, нужно перед условием фильтрации добавить not, разделив
условие и отрицание пробелом. Например, "not _12".
Sorting
Sorting - параметры сортировки
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| fieldName | String | Да | Название поля для сортировки |
| order | String | Да | Направление сортировки. Допустимые значения: asc и desc для сортировки по возрастанию и убыванию соответственно |
Paging
Paging - параметры пейджинга
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| page | Integer | Да | Номер запрашиваемой страницы. Страницы нумеруются с 1 |
| count | Integer | Да | Количество элементов на странице |
Page
Страница списка элементов (часть списка с примененным пейджингом)
| Поле | Тип | Описание |
|---|---|---|
| items | Array of objects | Список элементов на запрошенной странице |
| total | Integer | Общее количество объектов в БД |
AuthorizationResult
Результат выполнения запроса авторизации
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| allow | Bool | Да | Разрешен ли доступ |
| entityFilters | String | Нет | Фильтры для сущности, которые нужно применить если "allow = true". Формат фильтров описан на странице Condition |
AttributeWithValues
Результат выполнения запроса авторизации
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | String | Да | Идентификатор атрибута |
| cat | String | Да | Идентификатор категории атрибута |
| values | List[String] | Да | Список значений атрибута |
В качестве значения поля "cat" может быть использована любая строка (нет ограничений), но в данный момент мы используем только следующие значения:
- "urn:oasis:names:tc:xacml:3.0:attribute-category:action"
- "urn:oasis:names:tc:xacml:3.0:attribute-category:environment"
- "urn:oasis:names:tc:xacml:3.0:attribute-category:resource"
- "urn:oasis:names:tc:xacml:1.0:subject-category:access-subject"
UserId
ID пользователя. Соответствует типу UUID.
GroupId
ID группы. Соответствует типу String.
UserStatus
Список вариантов статуса пользователя в системе. Имеет тип String.
| Название | Описание |
|---|---|
| Pending | Пользователь, ожидающий подтверждения регистрации |
| Activated | Обычный пользователь системы (выполнивший все условия/требования после регистрации) |
| Deactivated | Заблокированный пользователь системы |
CommandRequest
Структура для описания запроса на выполнение команды
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| commandName | CommandName | Да | Название команды |
| context | RequestContext | Да | Контекст запроса. Содержит информацию о пользователе, который отправил запрос, и другие дополнительные параметры |
| payload | Json | Нет | Данные для команды, которые она получит в качестве аргументов. Обычно идентично содержимому body запроса. |
RequestContext
Контекст запроса выполнения команды.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| commandId | CommandId | Да | ID связанной команды |
| tracing | TracingContext | Нет | Данные для логирования |
| parameters | Map[String, String] | Да | Дополнительные параметры. Значение по ключу может быть в любом формате, но должно передаваться как String. Сейчас используется для передачи данных о пользователе, которые затем можно превратить в UserContext |
| isInternal | boolean | Да | Флаг, указывающий, что данный вызов команды внутренний (т.е. не требует авторизации). Значение по умолчанию false. |
UserContext
Данные пользователя необходимые для передачи в контексте запроса каждой команды
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | UserId | Да | Идентификатор пользователя. |
| emailOpt | String | Нет | Уникальный email пользователя (опционален, т.к. отсутствует у анонимного пользователя). |
| groupIds | List[GroupId] | Да | Список идентификаторов групп пользователя. |
| passwordExpirationDateOpt | TimeStamp | Нет | Опциональная дата завершения действия пароля от учетной записи пользователя. Если значение не установлено, то пароль считается бессрочным. |
UserContextWithInvalidations
Данные пользователя необходимые для обработки запроса каждой команды
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| userContext | UserContext | Да | Контекст пользователя |
| userStatus | UserStatus | Да | Статус пользователя |
| jwtInvalidation | List[JwtInvalidation] | Да | Список правил для инвалидации JWT пользователя |
| deactivateAt | TimeStamp | Нет | Ограничение на срок действия учетной записи пользователя |
EntityObjectEventAdditionalData
Один из нескольких вариантов:
- UpdateAdditionalData - данные передаваемые при обновлении сущности в data-model
- PluginBackLinksAdditionalData - данные передаваемые при запросе на переиндексацию объектов без поиска backlinks
PluginBackLinksAdditionalData
| Поле | Тип | Обязательное | Значение по умолчанию | Описание | Ограничения |
|---|---|---|---|---|---|
| topic | String | Да | Нет | Топик для шага Plugin | |
| fieldId | String | Да | Нет | Поле сущности, где хранится файл для индексации |
EntityObjectEvent
| Поле | Тип | Обязательное | Значение по умолчанию | Описание | Ограничения |
|---|---|---|---|---|---|
| entityObject | EntityObject | Да | Нет | Передаваемая сущность из data-model | |
| additionalData | Option[EntityObjectEventAdditionalData] | Нет | нет | Дополнительные данные, передаваемые с событием |
EntityTypeId
Соответствует типу String. Содержит идентификатор, который, чаще всего, имеет формат UUID, но это не является обязательным требованием.
FieldId
Соответствует типу String.
ObjectFileId
Соответствует типу UUID.
AdditionalFieldName
Соответствует типу String.
StepProgress
| Поле | Тип | Обязательное | Значение по умолчанию | Описание | Ограничения |
|---|---|---|---|---|---|
| step | Step c payload Plugin | Шаг сервиса индексации | |||
| entityObject | EntityObject | Сущность сервиса data-model, обработка полей которой происходит | |||
| files | Map[FieldId, Seq[ObjectFile]] | Соответствие между полем в entityObject, которое нужно обработать, и описанием файла, который хранится в этом поле. | StepProgress, попадающий в plugin, содержит в files только те поля, которые содержатся в step.payload.fields | ||
| generated | Map[AdditionalFieldName\, Seq[GeneratedFile]] | Соответствие между полем, сгенерированным предыдущими шагами, и описанием сгенерированного файла, который хранится в этом поле. | StepProgress, попадающий в plugin, содержит в generated только те поля, которые содержатся в step.payload.fields | ||
| attempts | Int | Количество попыток, которое было сделано для обработки данного шага индексации. | Всегда меньше APP_MAX_STEP_ATTEMPTS (переменная окружения сервиса indexation) | ||
| correlationId | String | Id индексации, породившей этот StepProgress: UUID в виде строки(массовая индексация) или строка "event"+UUID(индексация события из data-model) | |||
| level | Int | Уровень, на котором находится step в индексации. Для индексации события из data-model всегда равен 0. | |||
| skipped | Seq[ObjectFile] | Описание файлов, которые были исключены из обработки с помощью ExtensionFilter. Сюда будут добавлены все файлы с неподходящим расширением, даже те, которые не содержатся в step.payload.fields. При это файлы с верным расширением, которые исключены из обработки плагинами, потому что их нет в step.payload.fields сюда включены не будут. |
ObjectFile
| Поле | Тип | Обязательное | Значение по умолчанию | Описание | Ограничения |
|---|---|---|---|---|---|
| fileId | ObjectFileId | Да | Нет | Идентификатор файла | |
| additional | JsonObject | Нет | Нет | Дополнительная информация по файлу. Сейчас здесь хранится JsonObject, представляющий из себя Map[additionalFileFieldName, url], где хранятся ссылки на файлы, сгенерированные в результате индексации. Сохраняется эта информация с помощью команды saveFilesAdditionalInfo | |
| name | String | Да | Нет | Имя файла с расширением | |
| url | String | Да | Нет | Url, по которому можно найти этот файл в s3 |
GeneratedFile
| Поле | Тип | Обязательное | Значение по умолчанию | Описание | Ограничения |
|---|---|---|---|---|---|
| originField | FieldId | Да | Нет | Название файлового поля сущности, в котором хранится файл, на основе которого был сгенерирован текущий | |
| originFileId | ObjectFileId | Да | Нет | Id файла на основе которого был сгенерирован текущий(описание сгенерированного файла хранится в объекте оригинального файла в поле additional, не additionalData) | |
| file | String | Нет | Нет | Url в s3 для содержимого сгенерированного файла |
Настройка StreamingKafkaConsumer
StreamingKafkaConsumer предоставляет возможность создавать kafka-consumer и обрабатывать входящие сообщения
с помощью передаваемой пользовательской функции.
При этом один StreamingKafkaConsumer может обрабатывать сообщения из нескольких топиков с разными настройками и
функциями-обработчиками.
Для каждого вызова consumeWithFlow создается отдельный org.apache.kafka.clients.consumer.KafkaConsumer,
а также akka-граф получения и обработки сообщений указанного топика.
Эти графы запускаются независимо, но делят между собой один KafkaConsumerControlActor.
StreamingKafkaConsumer может вести себя по-разному и для настройки его поведения нужно использовать
KafkaConsumerSettings
KafkaConsumerSettings
| Поле | Тип | Обязательное | Описание | Значение по умолчанию | Ограничения |
|---|---|---|---|---|---|
| group | string | да | Название группы потребителей, к которой принадлежит данный экземпляр сервиса | ||
| topic | KafkaTopicSettings | да | Настройки для топика | ||
| restart | RestartConfiguration | нет | Настройки перезапуска потребителя Kafka | ||
| perMessageRestart | PerMessageRestartConfiguration | нет | Настройки перепрочтения сообщений, обработка которых завершается ошибкой |
Иногда в процессе применения пользовательской функции к сообщению может быть выброшено исключение и тогда, то как поведет себя стрим, определяется настройками KafkaConsumerSettings.restart и KafkaConsumerSettings.perMessageRestart. KafkaConsumerSettings.restart используется в общем KafkaConsumerControlActor, поэтому они всегда будут общими для всех вызовов consumeWithFlow, а KafkaConsumerSettings.perMessageRestart, KafkaConsumerSettings.group, KafkaConsumerSettings.topic принимаются в вызове consumeWithFlow, поэтому можно сделать их разными для разных вызовов consumeWithFlow.
RestartConfiguration
KafkaConsumerSettings.restart отвечает за то, сколько раз в случае возникновения исключения во время обработки стоит перезапустить консьюмер и связанный с ним akka-граф, прежде чем объявить сервис больным. Если настройки не указаны, то в KafkaConsumerControlActor используются значения по умолчанию. Задержка перед перезапуском увеличивается пропорционально количествам перезапусков начиная от minBackoff вплоть до maxBackoff.
| Поле | Тип | Обязательное | Описание | Значение по умолчанию (в сервиса verdi-cursor) | Значение по умолчанию (в KafkaConsumerControlActor) | Ограничения |
|---|---|---|---|---|---|---|
| minBackoff | FiniteDuration | да | Минимальная задержка перед перезапуском. | 1 second | 3.seconds | меньше или равно maxBackoff |
| maxBackoff | FiniteDuration | да | Максимально возможная задержка перед перезапуском. | 30 seconds | 1.minute | больше или равно minBackoff |
| randomFactor | double | нет | Коэффициент величины дополнительной случайной задержки (jitter) относительно основной задержки:0.0 - без случайной задержки, 1.0 - до 100% задержки. Если после умножения задержки на randomFactor получится меньше 1 миллисекунды, то jitter будет приравнен к нулю. | 0.2 | 0 | от 0 до 1 |
| maxRestarts | int | да | Максимальное количество перезапусков в заданный период времени. После превышения этого числа сервис будет объявлен больным | 5 | 20 | больше 0 и больше perMessageRestart.maxRestarts |
| maxRestartsWithin | FiniteDuration | да | Период времени, в течении которого копится счетчик перезапусков | 5 minutes | 2 * maxBackoff |
PerMessageRestartConfiguration
Иногда нам хочется в таком случае не объявлять сервис больным, а вместо этого спустя несколько перезапусков пропустить сообщение kafka, обработка которого вызывает ошибку. Именно за такое поведение отвечает PerMessageRestartConfiguration. Если PerMessageRestartConfiguration не указаны или PerMessageRestartConfiguration.maxRestarts < 0, то вызывающие ошибку сообщения не будут пропущены, а сервис просто будет объявлен больным в соответствии с RestartConfiguration. Для каждого сообщения счетчик перепрочтений хранится в кэше.
| Поле | Тип | Обязательное | Описание | Значение по умолчанию (в сервиса verdi-cursor) | Ограничения |
|---|---|---|---|---|---|
| failureCacheCapacity | long | да | Максимальное количество значений в кэше. | 1 second | меньше или равно maxBackoff |
| failureCacheTTL | FiniteDuration | нет | Максимальное время жизни элемента в кэше. В случае отсутствия значения время жизни элемента не будет ограничено. | 30 seconds | больше или равно minBackoff |
| maxRestarts | int | да | Максимальное количество раз, которое консьюмер перезапустится прежде чем проигнорировать сообщение, при чтении которого происходит ошибка | 5 | больше 0 |
Счетчики рестартов
Для того чтобы обеспечить функционал рестартов консьюмера в ходе работы поддерживается 2 вида счетчиков:
- Счетчик рестартов, индивидуальный для каждого сообщения. Этот счетчик реализован через кэш CacheApi и поддерживается только при наличии настроек KafkaConsumerSettings.perMessageRestart. Кэш этих счетчиков является индивидуальным для каждого запуска consumeFlow. Он считает сколько раз сервис был перезапущен из-за возникновения ошибки в ходе обработки конкретного сообщения.
- Глобальный счетчик рестартов. Этот счетчик является индивидуальным для каждого запуска consumeFlow, но увеличивается при ЛЮБОМ рестарте, а не только в случае если сообщение было пропущено. То есть даже при наличии настроек KafkaConsumerSettings.perMessageRestart, КАЖДЫЙ перезапуск из-за определенного сообщения будет увеличивать глобальный счетчик. При достижении этим счетчиком значения KafkaConsumerSettings.restart.maxRestarts сервис будет объявлен больным вне зависимости от наличия настроек KafkaConsumerSettings.perMessageRestart. Поэтому при использовании perMessageRestart нужно указывать KafkaConsumerSettings.restart.maxRestarts > KafkaConsumerSettings.perMessageRestart.maxRestarts или не указывать KafkaConsumerSettings.perMessageRestart.maxRestarts совсем.
Периоды
Оба вида счетчиков дают возможность обнулить их после прошествия определенного периода времени. Глобальный счетчик рестартов обнуляется после прошествия maxRestartsWithin, а счетчик рестартов, индивидуальный для каждого сообщения, спустя failureCacheTTL. При этом failureCacheTTL никак не влияет на глобальный счетчик. То есть даже если индивидуальный счетчик сообщения уже обнулен, глобальный счетчик НЕ будет уменьшен на то количество перезапусков, которые произошли из-за этого сообщения.
Особенности произведения рестарта
- В случае возникновения исключения рестарт не будет произведен, пока не закончится обработка всех сообщений, чья обработка уже начата (даже если эти сообщения были получены после ошибочного). При этом может произойти так, что к тому моменту партиции будут уже отозваны и эти сообщения не успеют закоммититься. Оффсеты таких сообщений накапливаются в состоянии приложения и будут закоммичены после перезапуска. Повторной обработки сообщений при этом не произойдет.
- В случае исключения в потоке обработки одной партиции, будет перезапущена обработка всех партиций. Повторной обработки обработанных сообщений при этом не произойдет.
- В случае исключения в одном вызове consumeWithFlow(1) рестарта в других вызовах consumeWithFlow(2) не произойдет. Если консьюмеры созданные в результате этих вызовов состояли в одной группе, то при рестарте несколько раз произойдет ребаланс. Поэтому часть сообщений в consumeWithFlow(2) могут обработаться, но не быть закоммиченными. Оффсеты таких сообщений накапливаются в состоянии приложения и будут закоммичены после перезапуска.
Роуты для информирования статусов сервисов
Для получения информации о статусе сервиса существует интерфейс com.embedika.verdi.senderlib.ServiceHealthApi.
Сервис позволяет хранить и обрабатывать текущий статус сервиса. Есть 2 состояния которые можно узнать у сервиса:
isHealth и isReady.
Статус Health сообщает о том что сервис работает и у него нет проблем. По умолчанию статус считается Health и в
случае технических проблем он изменяется на Ill.
Cтатус Ready сообщает о том что сервис готов принимать команды и обрабатывать их. Статус по умолчанию NotReady и
необходимо установить его вручную на последней стадии инициализации проекта методом ServiceHealthApi::markReady().
Для Akka
scala HealthRouteImpl.route(healthApi)()Для Tapir / ZIO
scala val makeAPI: URIO[Env, List[ZServerEndpoint[Clock, _, _, _]]] = for { serviceHealthApi <- ZIO.service[ServiceHealthApi] serviceAPI <- serviceAPI } yield { implicit val ff: FromFuture[RIO[Clock, *]] = new FromFuture[RIO[Clock, *]] { override def apply[A](futureMaking: => Future[A]): RIO[Clock, A] = ZIO.fromFuture(_ => futureMaking) } serviceAPI ++ HealthRoute.route[RIO[Clock, *]](serviceHealthApi) }
val makeAPI: URIO[Env, List[ZEndpoint]] = for {
serviceHealthApi <- ZIO.service[ServiceHealthApi]
serviceAPI <- serviceAPI
} yield {
implicit val ff: FromFuture[Task] = new FromFuture[Task] {
override def apply[A](futureMaking: => Future[A]): Task[A] = ZIO.fromFuture(_ => futureMaking)
}
serviceAPI ++ HealthRoute.route[Task](serviceHealthApi)
}
Для добавления в проект достаточно добавить роуты с помощью метода HealthRoute::route:
- Для Akka это
com.embedika.verdi.senderlib.akkahttp.HealthRoute. ПринимаетServiceHealthApiи возвращает роут. - Для Tapir / ZIO это
com.embedika.verdi.tapir.HealthRoute. ПринимаетServiceHealthApiи возвращает список роутов.
Функционал фильтров и сортировки
Для некоторых команд можно передавать параметры запроса в виде объекта Search, который содержит информацию о том как нужно отфильтровать, отсортировать запрос и как разделить его на страницы.
Фильтрация
{
"query": "count && (created || modified)",
"context": {
"count": "1_1000",
"created": "1630326000_",
"modified": "_1630327000"
}
}
Фильтрация состоит из двух полей:
queryописывает условие для фильтрации с использованием названий полейcontextописывает значение для полей, указанных вquery
Query поддерживает операторы && и || + скобки.
В Context-е можно описать несколько видов проверок для полей:
1) Условие равенства переданному значению.
{
"context": {
"fieldName": "какое-то значение"
}
}
2) Условие равенства какому-то одному значению из предоставленного списка.
{
"context": {
"fieldName": "[первое значение, второе, другое]"
}
}
или
{
"context": {
"fieldName": "any[первое значение, второе, другое]"
}
}
3) Условие наличия всех значений из предоставленного списка в массиве всех значений objectFieldName, которые присутствуют в объектах поля arrayFieldName. Работает только для полей arrayFieldName, содержащих массив. Предоставленный в запросе список должен содержать не менее двух значений.
{
"context": {
"arrayFieldName.objectFieldName": "all[первое значение, второе, другое]"
}
}
4) Условие соответствия паттерну
Значение поля обязательно должно начинаться со слова like.
{
"context": {
"fieldName": "like какое%значен__"
}
}
5) Условие вхождения значения в заданный диапазон. В данный момент, поддерживаются только целые числа.
Начало и конец диапазона разделяются знаком _. Оба конца диапазона опциональны и они включаются в диапазон.
Если передать просто _, то результатом будет пустой диапазон, в который не входит ни один элемент и ответ тоже
будет пустой.
6) Условие текствого поиска PGSQL
Значение поля обязательно должно начинаться со слова ts.
{
"context": {
"fieldName": "ts (this | that) & the:*"
}
}
Сортировка
{
"sorting": {
"fieldName": "number",
"order": "desc"
}
}
Сортировка определяется двумя полями:
fieldNameназвание поля, по которому будет производиться сортировкаorderнаправление сортировки. Бывает двух видов:asc,desc.
Настройки логеров
Конфигурация для логера указывается в файле src/main/resources/logback.xml (или logback-test.xml). Если такого файла
нет, то будет использована "базовая" конфигурация с выводом лога в консоль (stdout) в следующем формате:
%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} -%kvp- %msg%n.
Некоторые параметры из файла конфигурации можно задать через переменные окружения. Ниже приведен список общих переменных
окружения, которые есть почти в каждом сервисе, но конфигурация не ограничивается только ими.
У каждого сервиса свой набор переменных и может присутствовать префикс у каждой переменной (например, MON_
или TOLKA_). В таком случае, префикс должен быть добавлен и к переменным окружения для логеров.
Пример:
В документации приведена общая переменная окружения для уровня логирования LOG_LEVEL, но у сервиса "Oberto" для всех
переменных окружения используется префикс OBERTO_. Поэтому, чтобы настроить общий уровень логирования для сервиса "
Oberto", нужно использовать переменную OBERTO_LOG_LEVEL вместо LOG_LEVEL.
Чтобы узнать, используется ли какой-то префикс в сервисе, можно посмотреть на список переменных в документации к
сервису.
Натуральная сортировка (natural sorting)
Некоторые поля сортируются с использованием натуральной сортировки. Натуральная сортировка позволяет упорядочить строки таким образом, чтобы числа внутри строк упорядочивались как числа.
Сортировка осуществляется с помощью локали en@colNumeric=yes.
Примеры результатов сортировки:
| Описание | Пример |
|---|---|
| Строки с числами | 032156123 |
| Числами внутри слов | a2ba10ba20b |
| Версия некоторых библиотек | v2.5.0v2.10.0v10.1.0v10.12.0 |
| Главы книг | Глава 2Глава 2.2Глава 2.012Глава 13Глава 13.1 |
LOG_OUTPUT
Задает, куда будет выводиться сообщения лога. Может принимать следующие значения:
STDOUT - обычный лог в консоль.
STDOUT_CEF - лог в формате CEF в консоль.
STDOUT_CEF_JSON - лог в формате JSON в консоль, но со структурой сообщений CEF.
FILE - обычный лог в файл.
FILE_CEF - лог в формате CEF в файл.
FILE_CEF_JSON - лог в формате JSON в файл, но со структурой сообщений CEF.
SYSLOG - обычный лог в SYSLOG.
SYSLOG_CEF - лог в формате CEF в SYSLOG.
SYSLOG_CEF_JSON - лог в формате JSON в SYSLOG, но со структурой сообщений CEF.
Данный параметр может принимать несколько значений через любой разделитель (например, через пробел "STDOUT FILE_CEF").
Если указано несколько значений с одним типом вывода, то будет учитываться только вывод в формате CEF.
Например: если присутствуют "STDOUT" + "STDOUT_CEF", то учитывается только "STDOUT_CEF"; "FILE" + "FILE_CEF" = "
FILE_CEF"; "SYSLOG" + "SYSLOG_CEF" = "SYSLOG_CEF".
LOG_LEVEL
Стандартный уровень логирования, который будет считаться значением по умолчанию для логеров, у которых уровень
логирования не задается в отдельной переменной.
Значения в переменной характеризуют, насколько детальными будут сообщения в логе.
Может принимать следующие значения:
TRACE - максимально подробные сообщения.
DEBUG - менее подробные сообщения, чем в TRACE, но достаточные для debug-а.
INFO - логирование основных событий во время работы приложения. Считается стандартным уровнем логирования.
WARN - логирование только важных событий.
ERROR - логирование только сообщений об ошибках.
OFF - отключение лога.
Каждый уровень включает в себя все последующие, поэтому TRACE наиболее подробный, т.к. содержит все возможные
сообщения, а WARN менее подробный, т.к. содержит только сообщения об ошибках и других важных событиях, но не
содержит "стандартные" события из уровня INFO.
Если у конкретного логера есть отдельная настройка для уровня логирования, то она будет перекрывать общую настройку из
LOG_LEVEL.
Переменные для указания уровня логирования конкретных логеров
В каждом сервисе/приложении по своему настроены логеры, которые будут привязаны к какой-то из переменных. Далее будут
описаны лишь общий смысл переменных и какого вида сообщения можно ожидать от привязанных логеров.
LOG_LEVEL_HTTP - логер для HTTP сервера/клиента, отображающий события во время обработки HTTP вызова. Значение по
умолчанию "INFO".
LOG_LEVEL_NIOSOCKET - логер для бекенда HTTP сервера/клиента, отображающий низкоуровневые события во время обработки
HTTP вызова. Значение по умолчанию "WARN".
LOG_LEVEL_AKKA - логер для системы акторов, отображающий специфичные для Akka сообщения (из тред пула, из стримов,
из акторов). Значение по умолчанию "INFO".
LOG_LEVEL_LIQUIBASE - логер для liquibase (миграции БД). Почти не используются, только если миграции не вызываются
во время работы сервиса (как в data-model). Значение по умолчанию "INFO".
LOG_LEVEL_SLICK_STATEMENT - логер для slick (вывод sql запросов). Значение по умолчанию "WARN".
LOG_LEVEL_SLICK_BENCHMARK - логер для slick (вывод времени подготовки sql запросов). Значение по умолчанию "
OFF".
DATA_MODEL_LOG_LEVEL_SLICK_QUERY_COMPILER - логер для slick (вывод времени подготовки sql запросов с разделением по
стадиям). Значение по умолчанию "OFF".
Обычно, в Kafka логерах отображается низкоуровневая информация о полученных или отправленных сообщениях, текущее
состояние и настройки клиентов, логирование протокола общения между клиентом и брокером.
LOG_LEVEL_KAFKA, LOG_LEVEL_KAFKA_PRODUCER, LOG_LEVEL_KAFKA_CONSUMER - логер для Kafka клиентов (продюсер и
консьюмер). Обычно используется или общая переменная, или по одной для консьюмера и продюсера. Значение по умолчанию "
WARN".
LOG_LEVEL_KAFKA_HTTP - логер для HTTP бекенда Kafka клиентов. Значение по умолчанию "WARN".
LOG_LEVEL_KAFKA_INTERNAL - логер для внутренних сообщений Kafka клиентов (metadata). Значение по умолчанию "
INFO".
LOG_LEVEL_KAFKA_SELECTOR - логер для общего сетевой библиотеки всех клиента Kafka (логирует SSL handshake). Значение
по умолчанию "INFO".
LOG_LEVEL_KAFKA_NETWORK_CLIENT - логер для общего сетевой библиотеки всех клиента Kafka (низкоуровневый клиент).
Значение по умолчанию "INFO".
LOG_LEVEL_KAFKA_STREAMING_PRODUCER - логер для Kafka producer. Значение по умолчанию "INFO".
LOG_LEVEL_ZIO_KAFKA - логер для ZIO версии Kafka producer. Значение по умолчанию "INFO".
LOG_LEVEL_AKKAHTTPSENDER - логер для отправки команд по HTTP. Значение по умолчанию "WARN".
LOG_LEVEL_KAFKASENDER - логер для отправки команд по Kafka. Значение по умолчанию "TRACE".
LOG_LEVEL_COMMANDSTATUS_CLIENT - логер для клиента CommandStatus. Значение по умолчанию "WARN".
LOG_LEVEL_AUTHZCLIENT - логер для клиента авторизации (к authzfroce или oberto). Значение по умолчанию "ERROR".
LOG_LEVEL_LICENSE - логер для операций проверки лицензий.
Параметр применим к сервисам Oberto, Mon, Api Gateway.
На уровне логирования DEBUG логируется информация об используемой лицензии.
Значение по умолчанию "INFO".
LOG_LEVEL_COMMANDLOGGER - логер для трассировки запросов, класс com.embedika.verdi.CommandLogger.
Логируется информация о текущем запросе.
Значение по умолчанию "INFO".
LOG_JSON_SPACES - определяет форматирование JSON-а в сообщениях логера:
noSpaces - без переносов строк и отступов,
spaces2 - с переносами строк и с отступами в два пробела.
Значение по умолчанию "noSpaces".
Параметры для настройки логирования в формате CEF.
У логов есть возможность включить формат CEF для
логирования по следующему шаблону:
2022-12-14T16:56:31+0500 CEF:Version|Device Vendor|Device Product|Device Version|EventClassId|Message|Severity|src=? dst=? shost=? suid=? suser=? msg=? end=currentTimeMillis|.
Чтобы включить логирование в формате CEF, нужно задать в переменной LOG_OUTPUT значение с постфиксом, который содержит _CEF (
например, LOG_OUTPUT = STDOUT_CEF или LOG_OUTPUT = FILE_CEF_JSON).
В каждом logback.xml файле есть свойство, которое задает "main class" всего приложения. Этот класс нужен для получения
параметров записи сообщений в формате CEF.
У данного свойства нет переменной окружения, но его можно поменять прямо в файле.
Значение (value) свойства зависит от сервиса, но обычно оно задано как
<property scope="context" name="projectMainClassPath" value="com.embedika.Main"/>
В каждом application.conf файле указаны параметры для логирования в формате CEF, которые по умолчанию не заданы.
Если логи пишутся в формате CEF, то необходимо задать следующие переменные:
LOGGING_SRC_IP Параметр
SRC(источник/source, на который ссылается событие) для логов в формате CEF. Если не установлена,src=notFound. Требуемый формат: IPv4, например "192.168.10.1".LOGGING_SRC_HOST Параметр
SHOST(источник/source, на который ссылается событие) для логов в формате CEF. Если не установлена,shost=notFound. Требуемый формат: fully qualified domain name (FQDN), например "host" или " host.domain.com".LOGGING_DST_IP Параметр
DST(получатель/destination, на который ссылается событие) для логов в формате CEF. Если не установлена,dst=notFound. Требуемый формат: IPv4, например "192.168.10.1".LOGGING_CEF_VER Версия формата CEF: либо
0, либо1. Рекомендуется использовать0.
Значение по умолчанию "0".
Параметры для настройки логирования в формате SYSLOG
В конфиге есть возможность настроить отправку логов в какой-нибудь SYSLOG
сервер. Для отправки логов используется Syslog4j.
Чтобы включить логирование в SYSLOG, нужно задать в переменной LOG_OUTPUT значение с префиксом SYSLOG_ (
например, LOG_OUTPUT = SYSLOG_CEF).
LOG_SYSLOG_TYPE Протокол взаимодействия с SYSLOG сервером. Может принимать значения "UDP", "TCP" или "TLS".
Значение по умолчанию "UDP".
Значения из переменнойLOG_SYSLOG_TYPEконвертируются в классы Syslog4j:
TSL ->org.productivity.java.syslog4j.impl.net.tcp.ssl.SSLTCPNetSyslogConfig
TCP ->org.productivity.java.syslog4j.impl.net.tcp.TCPNetSyslogConfig
UDP ->org.productivity.java.syslog4j.impl.net.udp.UDPNetSyslogConfig
Если задано значение TLS, то необходимо еще настроить и параметры для SSL
Документацию по Java KeyStore и Truststore https://docs.oracle.com/cd/E19509-01/820-3503/ggffo/index.html
LOG_SYSLOG_KEYSTORE
Путь до файла KEYSTORE
LOG_SYSLOG_KEYSTORE_PASS
Пароль для файла в LOG_SYSLOG_KEYSTORE
LOG_SYSLOG_TRUSTSTORE
Путь до файла TRUSTSTORE
LOG_SYSLOG_TRUSTSTORE_PASS
Пароль для файла в LOG_SYSLOG_TRUSTSTORELOG_SYSLOG_PATTERN
Шаблон для сообщений. Не учитывается для "LOG_OUTPUT = SYSLOG_CEF", т.к. используется шаблон для CEF.
Документация по шаблонам https://logback.qos.ch/manual/layouts.html#ClassicPatternLayout.
Значение по умолчанию[%level] [%logger] [%thread] - %msg%n.LOG_SYSLOG_HOST
Хост SYSLOG сервиса в формате IPv4. Требуемый формат: IPv4.
Значение по умолчанию "127.0.0.1".LOG_SYSLOG_PORT
Порт SYSLOG сервиса. Может принимать любое положительное число.
Значение по умолчанию "514".LOG_SYSLOG_FACILITY
К сожалению, LOG_SYSLOG_FACILITY задается только через int код, а не string.
Список кодов для переменной:
KERN= 0
USER= 8
MAIL= 16
DAEMON= 24
AUTH= 32
SYSLOG= 40
LPR= 48
NEWS= 56
UUCP= 64
CRON= 72
AUTHPRIV= 80
FTP= 88
LOCAL0= 128
LOCAL1= 136
LOCAL2= 144
LOCAL3= 152
LOCAL4= 160
LOCAL5= 168
LOCAL6= 176
LOCAL7= 184
Значение по умолчанию "8".LOG_SYSLOG_IDENT
Идентификатор SYSLOG клиента. Может принимать любую строку.
Значение по умолчанию зависит от сервиса и обычно является названием сервиса ("mon", "oberto" и т.п.).LOG_SYSLOG_MAX_MSG_SIZE
Максимальны размер одного сообщения лога в байтах. Может принимать любое число.
Значение по умолчанию "65536".
Скрипт для формирования ROOT logger-а для logback.xml
В репозитории сервисов Verdi был добавлен скрипт "logback_config_generation.sc" для формирования ROOT логера. Этот
скрипт можно запустить, например,
в scala worksheet.
Объявление root логера в конфиге может быть достаточно большим, если количество уникальных вариантов вывода лога больше
трех или четырех, т.к. мы должны учитывать все способы вывода из переменной LOG_OUTPUT.
В таком случае, добавление новых опций для вывода становится проблематичным (требует какого-то времени), тогда и может
пригодиться данный скрипт.
В конце выполнения, скрипт делает println с получившимся XML-ом, который можно просто вставить в файл с конфигом.
Внутренние команды (Internal command)
Любая команда может быть указанна внутренней (т.е. не требующей авторизации) при задании признака
isInternal в передаваемом контексте RequestContext. Механизм обеспечивается логикой LiveObertoClient,
поэтому при использовании кастомной имплементации Authorizer стоит обратить внимание на корректность учитывания атрибута.
Задать атрибут isInternal можно 2 способами:
- Для конкретного случая отправки команды, напрямую проинициализировав RequestContext и отправив команду через апи VerdiDispatcherImpl
Инициализация RequestContext
val dispatcher: VerdiDispatcherImpl = ???
val cmdName: CommandName = ???
val payload: Json = ???
implicit val internalCtx = RequestContext.builder().withIsInternal(isInternal = true).build()
dispatcher.sendCommandSync(cmdName, payload)
- Глобально для всего приложения: необходимо задать в конфиге приложения параметр
senderlib.considerAllCommandsAsInternal=trueи стандартно проинициализировать VerdiFactory/VerdiTF[F[_]], которые создадут Dispatcher, автоматически устанавливающий атрибутisInternal=trueдля контекстов всех отправляемых комманд.
ВАЖНО: В реальной инсталляции мы считаем все сервисы (кроме api-gateway) недоступными из публичной сети. Т.е. обращения внешних клиентов обязательно должны проходить авторизацию.
Adapter-folder: адаптер сетевой папки
Основное
Адаптер сетевой папки позволяет экспортировать в систему на основе Verdi (используя data-model) все содержимое указанной папки и в дальнейшем синхронизировать состояние (удалять из Verdi удаленные из папки файлы, доэкспортировать новые и обновлять измененные).
Экспорт осуществляется в виде объекта для сервиса data-model указанного в конфигурации вида, который должен содержать обязательное поле бинарного файла (тип file), а также может содержать часть (или все) из нижеперечисленных полей:
- Наименование файла (string/text)
- Путь до файла относительно корня папки (string/text)
- Владелец файла в файловой системе (string/text)
- Дата создания файла (dateTime)
- Дата редактирования файла (dateTime)
Поддерживаются:
- локальные папки
- протокол сетевых папок SMB
Экспорт происходит при старте адаптера, и далее перезапускается через указанный промежуток времени. Кроме того, адаптер предоставляет HTTP API для вызова внепланового экспорта и восстановления.
Конфигурирование адаптера сетевой папки
Требования к запуску адаптера сетевой папки
Для корректной минимальной работы адаптера требуется:
- Развернутый стенд Verdi, включая:
- Доступ из адаптера к HTTP API интеграций Verdi (например https://verdiapp/integration/api/external)
- Настроенный data-model (см. шапку документации).
- Зарегистрированный клиент адаптера, имеющий доступ к настроенной модели данных.
- Доступ из адаптера к папке, из которой будут выгружаться файлы
- Подключение к PostgreSQL для хранения состояния выгрузки (см. соответствующий раздел)
Список переменных окружения адаптера сетевой папки
Обязательные параметры выделены жирным
Настройки PostgreSQL:
| Переменная | Описание | Значение по умолчанию |
|---|---|---|
| ADAPTER_FOLDER_DB_THREADS | Количество потоков в пуле потоков для соединения с БД | 10 |
| ADAPTER_FOLDER_DB_QUEUE_SIZE | Размер очереди для действий базы данных, которые не могут быть выполнены немедленно, когда все потоки заняты. За пределами этого значения новые действия немедленно завершаются неудачей | 300 |
| ADAPTER_FOLDER_DB_CONN_MAX | Максимальное количество одновременных подключений к БД | 10 |
| ADAPTER_FOLDER_DB_CONN_TIMEOUT | Максимальное время ожидания ответа для соединения к БД. Если это время превышено, а соединение не становится доступным, будет брошено исключение SQLException. 1000 мс — минимальное значение. | 20 second |
| ADAPTER_FOLDER_DB_ISOLATION | Уровень изоляции транзакций для новых подключений. Допустимые значения: NONE, READ_COMMITTED, READ_UNCOMMITTED, REPEATABLE_READ, SERIALIZABLE. |
"READ_COMMITTED" |
| ADAPTER_FOLDER_DB_READONLY | Read-only SQL транзакция может изменять только временные таблицы. Этот параметр управляет статусом «только для чтения» по умолчанию для каждой новой транзакции. | false |
| ADAPTER_FOLDER_DB_CONN_MIN | Минимальное количество одновременных подключений к БД | = DB_THREADS |
| ADAPTER_FOLDER_DB_VALIDATION_TIMEOUT | Максимальное время, в течение которого соединение будет проверяться на работоспособность. 1000 мс — минимальное значение. | 1 seconds |
| ADAPTER_FOLDER_DB_IDLE_TIMEOUT | Максимальное время, в течение которого соединению разрешено простаивать в пуле. Значение 0 означает, что простаивающие соединения никогда не удаляются из пула. | 10 minutes |
| ADAPTER_FOLDER_DB_MAX_LIFETIME | Максимальное время жизни соединения в пуле. Когда простаивающее соединение достигает этого времени ожидания, даже если оно недавно использовалось, оно будет удалено из пула. Значение 0 указывает на отсутствие максимального срока службы. | 30 minutes |
| ADAPTER_FOLDER_DB_INITIALIZATION_FAIL_FAST | Deprecated, начиная с версии Slick 3.3.0. Определяет, будет ли пул «быстро выходить из строя», если пул не может быть успешно заполнен начальными соединениями. Если соединения не могут быть созданы во время запуска пула, будет выдано исключение RuntimeException. Это свойство не имеет никакого эффекта, если minConnections равно 0. | false |
| ADAPTER_FOLDER_DB_LEAK_DETECTION_THRESHOLD | Время, в течение которого соединение может находиться вне пула, прежде чем будет зарегистрировано сообщение, указывающее на возможную утечку соединения. Значение 0 означает, что обнаружение утечек отключено. Наименьшее приемлемое значение для включения обнаружения утечек составляет 10 с. | 0 |
| ADAPTER_FOLDER_DB_CONNECTION_TEST_QUERY | Выражение, которое будет выполнено непосредственно перед получением соединения из пула для проверки того, что соединение с базой данных все еще активно. Оно зависит от базы данных и должно представлять собой запрос, требующий минимальной обработки базой данных (например, «VALUES 1»). Если этот параметр не установлен, вместо него используется метод JDBC4 Connection.isValid(). |
"SELECT 1" |
| ADAPTER_FOLDER_DB_AUTO_COMMIT | Это свойство определяет то, как будут вести себя по умолчанию возвращаемые соединения относительно autocommit-а. | true |
| ADAPTER_FOLDER_DB_SCHEMA | Устанавливает schema по умолчанию | "public" |
| ADAPTER_FOLDER_DB_ISOLATE_INTERNAL_QUERIES | Определяет то, изолируются ли с помощью транзакций внутренние запросы пула(например запрос connection alive test). Свойство применяется только если autoCommit выключен. | false |
| ADAPTER_FOLDER_DB_INITIALIZATION_FAIL_TIMEOUT | Работает, начиная с версии Slick 3.3.0. Определяет, будет ли пул «быстро выходить из строя», если пул не может быть успешно заполнен начальными соединениями. Любое положительное число считается числом миллисекунд для попытки получить начальное соединение;поток приложения будет заблокирован в течение этого периода. Если соединение не может быть получено до истечения этого времени,будет брошено исключение. Данный таймаут применяется после периода connectionTimeout. Если значение равно нулю (0),HikariCP попытается получить и проверить подключение. Если соединение получено,но проверка не пройдена, будет брошено исключение, и пул не будет запущен. Однако,если соединение не может быть получено, пул запустится,но последующие попытки получить соединение могут потерпеть неудачу.Значение меньше нуля пройдет любую первоначальную попытку подключения, и пул немедленно запустится,пытаясь получить соединения в фоновом режиме.Следовательно, последующие попытки получить соединение могут потерпеть неудачу. | 1 |
| ADAPTER_FOLDER_DB_REGISTER_MBEANS | Зарегистрированы ли JMX Management Beans («MBeans») | false |
Настройки адаптера:
| Переменная | Описание | Значение по умолчанию |
|---|---|---|
| ADAPTER_FOLDER_HTTP_HOST | Хост для API адаптера | "0.0.0.0" |
| ADAPTER_FOLDER_HTTP_PORT | Порт для API адаптера | 9515 |
| ADAPTER_FOLDER_SOURCE_IDENTITY | Любой (свой) ID адаптера. Если используется несколько адаптеров, их ID должны различаться | - |
| ADAPTER_FOLDER_EXPORT_DELAY | Время между окончанием предыдущей синхронизации и запуском следующей | 24 hours |
| ADAPTER_FOLDER_RECOVER_ON_START | Нужен ли запуск восстановления состояния; см. соответствующий раздел | false |
Настройки рабочей папки:
| Переменная | Описание | Значение по умолчанию |
|---|---|---|
| ADAPTER_FOLDER_SOURCE_URI | URI до рабочей папки. См формат ниже | - |
| ADAPTER_FOLDER_SOURCE_LOGIN | Логин для сетевой папки, если требуется | - |
| ADAPTER_FOLDER_SOURCE_PASSWORD | Пароль для сетевой папки, если требуется | - |
| ADAPTER_FOLDER_SOURCE_DOMAIN | Домен (WORKGROUP) для сетевой папки, если требуется | - |
| ADAPTER_FOLDER_SOURCE_SMB_MIN_VER | Минимальная версия используемого клиентом протокола SMB. См ниже | SMB1 |
| ADAPTER_FOLDER_SOURCE_SMB_MAX_VER | Максимальная версия используемого клиентом протокола SMB. См ниже | SMB210 |
Настройки обработки файлов:
| Переменная | Описание | Значение по умолчанию |
|---|---|---|
| ADAPTER_FOLDER_SOURCE_FILE_ALLOW_HIDDEN | Использовать ли скрытые файлы | false |
| ADAPTER_FOLDER_SOURCE_FILE_PRESERVE_EXTENSION | Оставлять ли расширение в имени файла | false |
| ADAPTER_FOLDER_SOURCE_FILE_SIZE_LIMIT_KB | Максимальный размер отправляемых файлов (не должен превышать INTEGRATION_FS_SIZE_LIMIT_KB сервиса импорта) | - |
Общие настройки взаимодействия с Verdi:
| Переменная | Описание | Значение по умолчанию |
|---|---|---|
| ADAPTER_FOLDER_VERDI_URI | Полная ссылка на HTTP API интеграций Verdi (например https://verdiapp/integration/api/external) | - |
| ADAPTER_FOLDER_VERDI_AUTH_TOKEN | Токен доступа клиента, от которого используется адаптер | - |
| ADAPTER_FOLDER_VERDI_MAXCON | Максимальное количество одновременных запросов от адаптера к Verdi. Максимум - 64. | 16 |
| ADAPTER_FOLDER_VERDI_RETRY_MAX_COUNT | Максимальное количество ретраев одного запроса к Verdi в случае ошибки | 10 |
| ADAPTER_FOLDER_VERDI_RETRY_DELAY | Задержка между ретраями запросов к Verdi | 10 second |
| ADAPTER_FOLDER_AKKA_HTTP_CLIENT_IDLE_TIMEOUT | Время ожидания ответа от Verdi | 5 minutes |
| ADAPTER_FOLDER_VERDI_TEMP_BINARY_EXPIRATION | Время жизни бинарных файлов, не связанных ни с одним объектом, в Verdi | 24 hours |
Настройки модели данных файла и взаимодействия с Verdi по данной модели (если код какого-либо поля не указан, и настройка этого кода является необязательной, поле не используется в объекте):
| Переменная | Описание | Значение по умолчанию |
|---|---|---|
| ADAPTER_FOLDER_FILE_ENTITY_TYPE | Код вида сущности из data-model, которая описывает файл | - |
| ADAPTER_FOLDER_FILE_SEND_PER_REQUEST | Количество создаваемых (обновляемых, удаляемых) объектов за один запрос | 10 |
| ADAPTER_FOLDER_FILE_GET_PER_REQUEST | Количество запрашиваемых объектов за раз (в режиме восстановления) | 50 |
| ADAPTER_FOLDER_FILE_MAPPING_BINARY_FILE | Код поля бинарного файла в модели данных | - |
| ADAPTER_FOLDER_FILE_MAPPING_PATH | Код поля пути до файла в модели данных | - |
| ADAPTER_FOLDER_FILE_MAPPING_NAME | Код поля названия файла в модели данных | - |
| ADAPTER_FOLDER_FILE_MAPPING_CREATED | Код поля времени создания файла в модели данных | - |
| ADAPTER_FOLDER_FILE_MAPPING_MODIFIED | Код поля времени изменения файла в модели данных | - |
| ADAPTER_FOLDER_FILE_MAPPING_OWNER | Код поля владельца файла в модели данных | - |
| ADAPTER_FOLDER_FILE_MAPPING_OWNER_UNKNOWN_PLACEHOLDER | Значение "по умолчанию" для поля владельца файла; используется если владелец неизвестен | - |
Формат ADAPTER_FOLDER_SOURCE_URI
Для локальных папок используется формат File URI. Примеры:
file:///C:/users/ivanov%20ivan/dir/в Windowsfile:///home/ivanov%20ivan/dirв Linux
Для папок, доступных по протоколу сетевых папок SMB, используется следующий формат: smb://server[:port]/share/[path/].
Примеры:
smb://127.0.0.1/MyShare- все файлы конкретного sharesmb://127.0.0.1/MyShare/my%20directory/- все файлы внутри определенной папки
Версии SMB
При использовании протокола SMB, из-за разницы между используемыми клиентом и сервером версий протокола, может
возникнуть ошибка подключения.
Переменные ADAPTER_FOLDER_SOURCE_SMB_MIN_VER (по умолчанию SMB1) и ADAPTER_FOLDER_SOURCE_SMB_MAX_VER (по
умолчанию SMB2.1) позволяют изменить используемые версии протокола на стороне клиента.
Поддерживаемые значения: SMB1, SMB202, SMB210, SMB300, SMB302, SMB311
Состояние и восстановление состояния
В целях оптимизации количества сетевых запросов, адаптер хранит текущее состояние экспорта по каждому из файлов в базе
данных.
В случаях сбоев (отсутствия соединения с БД, неожиданный перезапуск адаптера, потери данных БД или хранилища временных
файлов и пр.)
состояние иногда может перестать соответствовать действительности, что, в свою очередь, может значительно замедлить
последующий экспорт
и/или привести к артефактам синхронизации (когда удаленный из рабочей папки файл не будет удален из data-model
автоматически).
Для восстановления состояния при перезапуске используется "режим восстановления".
Если переменная ADAPTER_FOLDER_RECOVER_ON_START будет указана как true, то при запуске адаптера сначала (
единоразово) будет выполнена синхронизация состояния файлов с состянием в data-model, и только потом запущен плановый экспорт.
Кроме того, режим восстановления может быть запущен в любой момент (когда адаптер не выполняет других
задач).
Внеплановый запуск
Адаптер предоставляет HTTP API для внепланового запуска задач (при условии, что в данный момент адаптер не занят другой задачей):
POST /export- запуск экспортаPOST /recover- запуск режима восстановления
Хост и порт сервера API указываются в конфигурации (см. выше).
Каждый запрос может либо вернуть 423 Locked, если адаптер сейчас занят другой задачей, либо запустить задачу и сразу
вернуть 202 Accepted.
Alexandrina-client: клиент для сервиса Alexandrina
Библиотека предоставляет интерфейс и реализацию клиента для сервиса Alexandrina.
Пример создания Alexandrina-client
Пример внедрения зависимости:
make[AlexandrinaClient[F]].from {
(dispatcher: Dispatcher, ec: ExecutionContext @Id("ec-services"), fromFuture: FromFuture[F]) =>
implicit val implicitEc: ExecutionContext = ec
implicit val implicitFf: FromFuture[F] = fromFuture
new AlexandrinaClientImpl[F](dispatcher)
}
Для того чтобы использовать библиотеку alexandrina-client, нужно добавить зависимость
"com.embedika.verdi" %% "alexandrina-client" % verdiVersion.
Все классы находятся в пакете com.embedika.verdi.alexandrina.client.
Основной интерфейс для взаимодействия AlexandrinaClient[F[_]].
Реализация интерфейса AlexandrinaClientImpl[F[_]: FromFuture].
Предоставляемый функционал Alexandrina-client
Alexandrina-client предоставляет методы вызова соответствующих команд сервиса Alexandrina. Формат входных и выходных данных методов Alexandrina-client аналогичен формату входных и выходных данных команд сервиса Alexandrina.
Изменение справочников
Получение справочников
Изменение элементов справочников
Получение элементов справочников
- listItemsByCatalog
- internalListItemsByCatalog
- listItemsByCatalogCode
- internalListItemsByCatalogCode
- getCatalogItem
- internalGetCatalogItem
- getCatalogItemBatch
- internalGetCatalogItemBatch
- getCatalogItemByCode
- internalGetCatalogItemByCode
Парсинг, импорт и экспорт справочников
Alexandrina: сервис справочников
Сервис справочников.
Bibliotheca Alexandrina (лат.) - Александрийская библиотека.
Команды могут приходить как по HTTP, так и через Kafka в топик alexandrina_commands.
В сервисе реализованы следующие команды:
- Создать справочник
- Изменить справочник
- Удалить справочник
- Список справочников
- Список справочников по заданным фильтрам
- Получить данные справочника
- Получить данные справочника (внутренняя)
- Получить справочник по коду
- Получить справочник по коду (внутренняя)
- Экспорт справочников
- Экспорт справочников в формате xls
- Парсинг справочников
- Импорт справочников
- Ииформация о справочниках xls из zip-файла
- Создать элемент справочника
- Изменить элемент справочника
- Архивировать элемент справочника
- Удалить элемент справочника
- Удалить все элементы из справочника
- Список элементов справочника
- Список элементов справочника (внутренняя)
- Список элементов справочника по коду
- Список элементов справочника по коду (внутренняя)
- Получить данные элемента справочника
- Получить данные элемента справочника (внутренняя)
- Получить элемент справочника по его коду
- Получить элемент справочника по его коду (внутренняя)
- Получить данные элементов справочников по списку id
- Получить данные элементов справочников по списку id (внутренняя)
Optimistic Lock
У многих команд реализован механизм оптимистичных блокировок. Для этого в данных присутствует поле version.
Задача оптимистичных блокировок - предотвратить одновременное редактирование объекта из двух открытых форм.
Сначала фронтэнд запрашивает данные объекта и получает в ответе версию данных - поле version.
Он прикладывает эту версию в ответе. Если на бэкэнде она совпадает с исходной (не было других модификаций),
тогда данные сохраняются, а версия поднимается. Иначе сохранения не происходит, данные не перетираются.
Конфигурирование Alexandrina
Требования к запуску Alexandrina
Запуск сервиса осуществляется локально через sbt, на стенде в docker на jvm.
Для корректной минимальной работы сервиса требуется обязательное подключение к PostgreSQL, Kafka, Consul. Для настройки подключения к ним нужно заполнить обязательные переменные окружения из раздела ниже.
Для нормальной работы сервису дополнительно требуется окружение Verdi: CommandStatus и ApiGateway. В этом случае нужно уделить внимание настройкам, связанным с ServiceDiscovery и CommandDiscovery.
Список переменных окружения Alexandrina
Все доступные переменные окружения для настройки сервиса модели данных.
| Переменная | Тип | Обяза-тельная | Значение по умолчанию | Описание |
|---|---|---|---|---|
| ALEXANDRINA_HTTP_HOST | string | нет | "0.0.0.0" | Хост, на котором слушает HTTP-сервер |
| ALEXANDRINA_HTTP_PORT | int | нет | 8192 | Порт, на котором слушает HTTP-сервер |
| ALEXANDRINA_KAFKA_SERVERS | string | да | "localhost:9092" | Адрес Kafka |
| ALEXANDRINA_KAFKA_TOPIC | string | нет | "alexandrina_commands" | Название кафка-топика для получения команд. Сервис получает кафка-команды по нему, но и также сам публикует это название в CommandDiscovery. |
| ALEXANDRINA_CATALOG_EVENTS_TOPIC | string | нет | "catalogEvents" | Название кафка-топика для публикации событий над каталогами |
| ALEXANDRINA_KAFKA_CONSUMER_GROUP | string | нет | "alexandrina" | Имя consumer-группы для чтения из кафка-топика команд. Не должна меняться и не должна быть пустой, иначе сервис перечитает свои команды при перезапуске. |
| ALEXANDRINA_KAFKA_COMMANDEVENT_TOPIC | string | да | "commandevents" | Название кафка-топика для отправки сообщений со статусами выполняемых команд. ОБЯЗАТЕЛЬНО должно соответствовать названию этого топика в сервисе статуса команд. |
| ALEXANDRINA_KAFKA_PARTITIONS | int | да | 10 | Количество партиций в топике команд. |
| ALEXANDRINA_KAFKA_CONSUMER_RESTART_MIN_BACKOFF | duration string | нет | 1 second | Минимальная задержка перед перезапуском. |
| ALEXANDRINA_KAFKA_CONSUMER_RESTART_MAX_BACKOFF | duration string | нет | 30 seconds | Максимально возможная задержка перед перезапуском. |
| ALEXANDRINA_KAFKA_CONSUMER_RESTART_RANDOM_FACTOR | double | нет | 0.2 | Коэффициент величины дополнительной случайной задержки(jitter) относительно основной задержки (При значении 0.2 задержка может быть до 20% больше, чем при 0). Если после умножения задержки на ALEXANDRINA_KAFKA_CONSUMER_RESTART_RANDOM_FACTOR получится меньше 1 миллисекунды, то jitter будет приравнен к нулю. |
| ALEXANDRINA_KAFKA_CONSUMER_RESTART_MAX_RESTARTS | int | нет | 5 | Максимальное количество перезапусков в заданный период времени. .После превышения этого числа сервис будет объявлен больным. Все рестарты для каждого отдельного сообщения увеличивают и общий счетчик рестартов консьюмера, поэтому при использовании ALEXANDRINA_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS нужно указывать ALEXANDRINA_KAFKA_CONSUMER_RESTART_MAX_RESTARTS > ALEXANDRINA_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS или не указывать ALEXANDRINA_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS совсем |
| ALEXANDRINA_KAFKA_CONSUMER_RESTART_MAX_RESTARTS_WITHIN | duration string | нет | 5 minutes | Период времени для ограничения перезапусков. |
| ALEXANDRINA_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS | int | нет | 2 | Максимальное количество раз, которое консьюмер перезапустится с неизменной очередью сообщений(в пределах DATA_MODEL_KAFKA_CONSUMER_RESTART_MAX_RESTARTS_WITHIN), прежде чем проигнорировать сообщение, на котором происходит ошибка (Указано количество рестартов, а не прочтений. Если ALEXANDRINA_KAFKA_CONSUMER_RESTART_MAX_RESTARTS = 2, то ошибочное сообщение будет обработано 3 раза, после чего произойдет 3ий рестарт и оно будет проигнорировано). Если указать 0, то перезапуск произойдет, но сообщение будет обработано только в первый раз, когда произошла ошибка. Если указать значение меньше 0, то перезапуски все равно будут происходить, но игнорирование сообщений, вызывающих ошибку, будет отключено. |
| ALEXANDRINA_KAFKA_CONSUMER_PER_MESSAGE_RESTART_CACHE_SIZE | int | нет | 100 | Для каждого сообщения счетчик перепрочтений хранится в кэше. Максимальное количество значений в этом кэше. |
| ALEXANDRINA_KAFKA_CONSUMER_PER_MESSAGE_RESTART_CACHE_TTL | duration string | нет | 5 minutes | Для каждого сообщения счетчик перепрочтений хранится в кэше.Максимальное время жизни элемента в этом кэше. В случае отсутствия значения время жизни элемента не будет ограничено. |
| ALEXANDRINA_KAFKA_CONSUMER_POLL_TIMEOUT | duration string | нет | 10 milliseconds | timeout запроса poll для kafka consumer |
| ALEXANDRINA_KAFKA_CONSUMER_POLL_INTERVAL | duration string | нет | 100 milliseconds | интервал между запросами poll для kafka consumer |
| ALEXANDRINA_KAFKA_CONSUMER_PROPS | string | нет | "max.poll.records=500;max.partition.fetch.bytes=524288" | дополнительные параметры для kafka consumer в формате "key1=value1;key2=value2" |
| ALEXANDRINA_KAFKA_PRODUCER_MESSAGE_MAX_BYTES | int | нет | 1048576 | Лимит в байтах для Kafka сообщений |
| ALEXANDRINA_KAFKA_AUTH_USER | string | нет | "" | Название учетной записи Kafka(в случае аутентификации в kafka с помощью пароля). |
| ALEXANDRINA_KAFKA_AUTH_PASSWORD | string | нет | "" | Пароль учетной записи Kafka(в случае аутентификации в kafka с помощью пароля). |
| ALEXANDRINA_KAFKA_AUTH_PRINCIPAL | string | нет | "" | Principal учетной записи Kafka в Kerberos(в случае аутентификации в kafka через Kerberos). |
| ALEXANDRINA_KAFKA_AUTH_KEYTAB_PATH | string | нет | "" | Путь до keytab-файла(в случае аутентификации в kafka через Kerberos). |
| ALEXANDRINA_KAFKA_AUTH_TRUSTSTORE_LOCATION | string | нет | "" | Путь до хранилища сертификатов (Java key store). Если путь не указан, то сертификат применяться не будет. |
| ALEXANDRINA_KAFKA_AUTH_TRUSTSTORE_PASSWORD | string | нет | "" | Пароль к хранилищу сертификатов. |
| ALEXANDRINA_KAFKA_AUTH_MODE | string | нет | "" | Режим аутентификации: static - одна учетная запись на все запросы, mapping - учетная запись зависит от запроса |
| ALEXANDRINA_KAFKA_AUTH_CONFIG | string | нет | "" | Настройки для аутентификации: если AuthMode = mapping, то необходим JSON с List[KafkaAuthConfig]. Переменная соответствует полю authConfig из KafkaAuthSettings. |
| ALEXANDRINA_KAFKA_AUTH_CACHE_SIZE | int | нет | Максимальный размер кеша для Kafka producer (количество активных соединений). | |
| ALEXANDRINA_KAFKA_CONNECTION_CHECK_TEST_MESSAGES_INTERVAL | duration string | нет | 4 minutes | Применяется только для producer-ов со способом аутентификации kerberos. Интервал отправки тестовых сообщений кафки в топик connectionCheck.testMessagesTopicName. Тестовые сообщения (null, service producer test) отправляются регулярно с этим интервалом. |
| ALEXANDRINA_KAFKA_CONNECTION_CHECK_INTERVAL | duration string | нет | 60 seconds | Применяется только для producer-ов со способом аутентификации kerberos. Интервал проверки того, сколько тестовых сообщений было отправлено за данный период. Если количество сообщений за этот период равно количеству сообщений за прошлый период, то начинается отсчет периода без сообщений. |
| ALEXANDRINA_KAFKA_CONNECTION_CHECK_FAILED_AFTER_INTERVAL | duration string | нет | 5 minutes | Применяется только для producer-ов со способом аутентификации kerberos. Максимальная продолжительность периода без успешно отправленных тестовых сообщений. По ее достижении сервис будет объявлен больным. |
| ALEXANDRINA_KAFKA_AUTH_CACHE_TTL | duration string | нет | Время жизни Kafka producer в кеше. | |
| ALEXANDRINA_CONSUL_ADDR | url string | да | "http://localhost:8500" | Адрес Сonsul. |
| ALEXANDRINA_CONSUL_AUTH_USER | string | нет | "" | Название учетной записи Сonsul. Если название не указано, то настройки авторизации не будут применены. |
| ALEXANDRINA_CONSUL_AUTH_PASSWORD | string | нет | "" | Пароль учетной записи Сonsul. |
| ALEXANDRINA_TRACE_DURATION | boolean | нет | false | Признак необходимости трассировки выполнения команд |
| ALEXANDRINA_DISCOVERABLE_ID | string | нет | "alexandrina_instance" | ID сервиса в ServiceDiscovery |
| ALEXANDRINA_DISCOVERABLE_NAME | string | нет | "alexandrina" | Имя сервиса в ServiceDiscovery |
| ALEXANDRINA_DISCOVERABLE_HOST | string | да | "localhost" | Хост, публикуемый в ServiceDiscovery. По нему на данный сервис будут обращаться другие через HTTP. Указанный адрес должен быть виден другим сервисам. Пример: имя kubernetes/docker_swarm service |
| ALEXANDRINA_DISCOVERABLE_PORT | int | нет | Порт, публикуемый в ServiceDiscovery. По нему на данный сервис будут обращаться другие через HTTP. По умолчанию указывается порт, который слушает HTTP-сервер. | |
| ALEXANDRINA_DISCOVERABLE_LIVETIME | duration string | нет | 2 minutes | Период после последней отправки health check, в течение которого ServiceDiscovery считает данный сервис живым. |
| ALEXANDRINA_DISCOVERABLE_HEALTHPASS | string | нет | 1 minute | Периодичность отправки health check в ServiceDiscovery |
| ALEXANDRINA_AKKA_HTTP_CLIENT_MAXCON | int | нет | 512 | Максимальное число одновременных исходящих HTTP-соединений |
| ALEXANDRINA_AKKA_HTTP_CLIENT_MAXREQ | int | нет | 1024 | Максимальное число одновременных исходящих HTTP-запросов |
| ALEXANDRINA_AKKA_HTTP_SERVER_MAXCON | int | нет | 1024 | Максимальное число одновременных входящих HTTP-соединений |
| ALEXANDRINA_INTERNALCMD_ALLOW | bool | нет | false | Можно ли сервису отправлять внутрисистемные команды |
| ALEXANDRINA_SENDERLIB_COMMANDS_CACHE_UPDATEPERIOD | duration string | нет | 10 minutes | Время кэширования данных по командам из CommandDiscovery |
| ALEXANDRINA_SENDERLIB_SERVICES_CACHE_UPDATEPERIOD | duration string | нет | 30 seconds | Время кэширования данных по сервисам из ServiceDiscovery |
| ALEXANDRINA_DB_HOST | string | да | Хост БД | |
| ALEXANDRINA_DB_PORT | int | да | Порт БД | |
| ALEXANDRINA_DB_NAME | string | да | Имя базы в БД | |
| ALEXANDRINA_DB_URL | jdbc url string | нет | JDBC-url для соединения с БД. По умолчанию собирается из других обязательных переменных. Можно указать только его, если не хочется отдельно указывать хост/порт/имя базы. | |
| ALEXANDRINA_DB_USER | string | да | Пользователь БД | |
| ALEXANDRINA_DB_PASSWORD | string | да | Пароль пользователя БД | |
| ALEXANDRINA_DB_THREADS | int | нет | 10 | Количество потоков в пуле потоков для соединения с БД |
| ALEXANDRINA_DB_QUEUE_SIZE | int | нет | 300 | Размер очереди для действий базы данных, которые не могут быть выполнены немедленно, когда все потоки заняты. За пределами этого значения новые действия немедленно завершаются неудачей |
| ALEXANDRINA_DB_CONN_MAX | int | нет | 10 | Максимальное количество одновременных подключений к БД |
| ALEXANDRINA_DB_CONN_TIMEOUT | duration string | нет | 20 second | Максимальное время ожидания ответа для соединения к БД. Если это время превышено, а соединение не становится доступным, будет брошено исключение SQLException. 1000 мс — минимальное значение. |
| ALEXANDRINA_DB_ISOLATION | string | нет | "READ_COMMITTED" | Уровень изоляции транзакций для новых подключений. Допустимые значения: NONE, READ_COMMITTED, READ_UNCOMMITTED, REPEATABLE_READ, SERIALIZABLE. |
| ALEXANDRINA_DB_READONLY | boolean | нет | false | Read-only SQL транзакция может изменять только временные таблицы. Этот параметр управляет статусом «только для чтения» по умолчанию для каждой новой транзакции. |
| ALEXANDRINA_DB_CONN_MIN | int | нет | = DB_THREADS | Минимальное количество одновременных подключений к БД |
| ALEXANDRINA_DB_VALIDATION_TIMEOUT | duration string | нет | 1 seconds | Максимальное время, в течение которого соединение будет проверяться на работоспособность. 1000 мс — минимальное значение. |
| ALEXANDRINA_DB_IDLE_TIMEOUT | duration string | нет | 10 minutes | Максимальное время, в течение которого соединению разрешено простаивать в пуле. Значение 0 означает, что простаивающие соединения никогда не удаляются из пула. |
| ALEXANDRINA_DB_MAX_LIFETIME | duration string | нет | 30 minutes | Максимальное время жизни соединения в пуле. Когда простаивающее соединение достигает этого времени ожидания, даже если оно недавно использовалось, оно будет удалено из пула. Значение 0 указывает на отсутствие максимального срока службы. |
| ALEXANDRINA_DB_INITIALIZATION_FAIL_FAST | string | нет | false | Deprecated, начиная с версии Slick 3.3.0. Определяет, будет ли пул «быстро выходить из строя», если пул не может быть успешно заполнен начальными соединениями. Если соединения не могут быть созданы во время запуска пула, будет выдано исключение RuntimeException. Это свойство не имеет никакого эффекта, если minConnections равно 0. |
| ALEXANDRINA_DB_LEAK_DETECTION_THRESHOLD | int | нет | 0 | Время, в течение которого соединение может находиться вне пула, прежде чем будет зарегистрировано сообщение, указывающее на возможную утечку соединения. Значение 0 означает, что обнаружение утечек отключено. Наименьшее приемлемое значение для включения обнаружения утечек составляет 10 с. |
| ALEXANDRINA_DB_CONNECTION_TEST_QUERY | string | нет | "SELECT 1" | Выражение, которое будет выполнено непосредственно перед получением соединения из пула для проверки того, что соединение с базой данных все еще активно. Оно зависит от базы данных и должно представлять собой запрос, требующий минимальной обработки базой данных (например, «VALUES 1»). Если этот параметр не установлен, вместо него используется метод JDBC4 Connection.isValid(). |
| ALEXANDRINA_DB_AUTO_COMMIT | boolean | нет | true | Это свойство определяет то, как будут вести себя по умолчанию возвращаемые соединения относительно autocommit-а. |
| ALEXANDRINA_DB_SCHEMA | string | нет | "public" | Устанавливает schema по умолчанию |
| ALEXANDRINA_DB_ISOLATE_INTERNAL_QUERIES | boolean | нет | false | Определяет то, изолируются ли с помощью транзакций внутренние запросы пула(например запрос connection alive test). Свойство применяется только если autoCommit выключен. |
| ALEXANDRINA_DB_INITIALIZATION_FAIL_TIMEOUT | int | нет | 1 | Работает, начиная с версии Slick 3.3.0. Определяет, будет ли пул «быстро выходить из строя», если пул не может быть успешно заполнен начальными соединениями. Любое положительное число считается числом миллисекунд для попытки получить начальное соединение;поток приложения будет заблокирован в течение этого периода. Если соединение не может быть получено до истечения этого времени,будет брошено исключение. Данный таймаут применяется после периода connectionTimeout. Если значение равно нулю (0),HikariCP попытается получить и проверить подключение. Если соединение получено,но проверка не пройдена, будет брошено исключение, и пул не будет запущен. Однако,если соединение не может быть получено, пул запустится,но последующие попытки получить соединение могут потерпеть неудачу.Значение меньше нуля пройдет любую первоначальную попытку подключения, и пул немедленно запустится,пытаясь получить соединения в фоновом режиме.Следовательно, последующие попытки получить соединение могут потерпеть неудачу. |
| ALEXANDRINA_DB_REGISTER_MBEANS | boolean | нет | false | Зарегистрированы ли JMX Management Beans («MBeans») |
| ALEXANDRINA_TEMP_BUCKET | string | нет | temp | Бакет в файловом хранилище для временных файлов, загружаемых на gateway |
| ALEXANDRINA_EXPORT_BUCKET | string | нет | export | Бакет в файловом хранилище для генерируемых экспортом файлов |
| ALEXANDRINA_READABLE_NAME | string | нет | "Сервис справочников" | Читаемое название этого сервиса |
| ALEXANDRINA_DESCRIPTION | string | нет | "Сервис хранения данных справочников" | Читаемое описание этого сервиса |
| ALEXANDRINA_FS_URI | url string | нет | "http://localhost:9000" | Адрес для подключения к хранилищу файлов по S3-API |
| ALEXANDRINA_FS_ACCESS_KEY_ID | string | нет | minioadmin | Ключ доступа для хранилища файлов (aka логин) |
| ALEXANDRINA_FS_SECRET_ACCESS_KEY | string | нет | minioadmin | Секретный ключ для хранилища файлов (aka пароль) |
| ALEXANDRINA_FS_UPLOAD_PARALLELISM | int | нет | 4 | Параллелизм для загрузки файлов |
| ALEXANDRINA_FS_AUTH_MODE | string | нет | static | Режим аутентификации: static - одна учетная запись на все запросы, mapping - учетная запись зависит от запроса |
| ALEXANDRINA_FS_AUTH_CONFIG | string | нет | "" | Настройки для аутентификации: если AuthMode = mapping, то необходим JSON с маппингом учетных записей |
| ALEXANDRINA_FS_CACHE_SIZE | int | нет | 1 | Максимальный размер кеша клиентов для хранилища файлов (количество активных соединений). |
| ALEXANDRINA_FS_CACHE_TTL | duration string | нет | Время жизни клиента в кеше | |
| ALEXANDRINA_FS_RETRY_ATTEMPTS | int | нет | 5 | Количество ретраев, которое будет произведено в случае Exception-а в операции FSClient-а и при вычитывании стрима в get операциях FSClient-а. |
| ALEXANDRINA_FS_RETRY_DELAY | duration string | нет | 10 millis | Задержка между ретраями операций FSClient-а. |
| ALEXANDRINA_FS_ZIO_SHORT_MESSAGE_MODE | boolean | нет | false | Флаг включения режима сохранения ошибок работы с файловым хранилищем в сервисе журналирования nestor. При включении режима ошибки в логах будут отображаться в сокращенном формате: Short zio message mode. ExceptionType: ТИП ОШИБКИ, Exception id: 'СГЕНЕРИРОВАННЫЙ UUID' added to journal. Указанный id будет фиксироваться в event записи nestor'а в поле data.id |
| ALEXANDRINA_SENDERLIB_COMMANDS_HTTP_RETRY_ATTEMPTS | int | нет | 5 | Поле attempts из RetrySettings |
| ALEXANDRINA_SENDERLIB_COMMANDS_HTTP_RETRY_DELAY | duration string | нет | "5 seconds" | Поле delay из RetrySettings |
| ALEXANDRINA_SENDERLIB_COMMANDS_HTTP_RETRY_KIND | string | нет | "OnSomeExceptions(ConnectException)" | CommandResultRetryConditionKind |
| ALEXANDRINA_SENDERLIB_CONSUL_CONNECTION_RETRY_MAX | int | нет | 5 | Количество попыток переподключения к Consul |
| ALEXANDRINA_SENDERLIB_CONSUL_CONNECTION_RETRY_DELAY | duration string | нет | "1 second" | Задержка при попытках переподключения к Consul |
| ALEXANDRINA_JOURNAL_MODE | string | нет | WriteToJournal |
Режим журналирования Nestor. Допустимые значения: WriteToJournal (Отправка в сервис журналирования), WriteToTopic (Отправка события в очередь) |
| ALEXANDRINA_JOURNAL_TOPIC | string | да, если переменная ALEXANDRINA_JOURNAL_MODE = WriteToTopic |
"" | Название очереди журналирования. Для режима WriteToJournal значение игнорируется. |
Команды для сервиса Alexandrina
Список реализованных в сервисе команд, моделей EntityType и действий Actions, которые можно использовать при настройке авторизации. Не все поля EntityType доступны для использования в настройке авторизации. Если указан прочерк "-", то данное значение не влияет на авторизацию:
- если не указан Action, то никакой Action не проверяется (= без авторизации)
- если не указан EntityType, то на авторизацию влияет только Action
| Название команды | EntityType | Actions |
|---|---|---|
| createCatalog | Catalog | CreateCatalog |
| updateCatalog | Catalog | UpdateCatalog |
| removeCatalog | Catalog | DeleteCatalog |
| listCatalogs | Catalog | ReadCatalogs |
| searchCatalogs | Catalog | ReadCatalogs |
| getCatalog | Catalog | ReadCatalog |
| internalGetCatalog | - | - |
| getCatalogByCode | Catalog | ReadCatalog |
| internalGetCatalogByCode | - | - |
| exportCatalogs | Catalog | CatalogsExport |
| exportCatalogsXls | Catalog | CatalogsExport |
| parseCatalogs | Catalog | CatalogsParse |
| parseCatalogsXls | Catalog | CatalogsParse |
| importCatalogs | Catalog | CatalogsImport |
| createCatalogItem | CatalogItem | CreateCatalogItem |
| updateCatalogItem | CatalogItem | UpdateCatalogItem |
| archiveCatalogItem | CatalogItem | ArchiveCatalogItem |
| removeCatalogItem | CatalogItem | DeleteCatalogItem |
| removeItemsFromCatalog | CatalogItem | DeleteCatalogItems |
| listItemsByCatalog | CatalogItem | ReadCatalogItems |
| internalListItemsByCatalog | - | - |
| listItemsByCatalogCode | CatalogItem | ReadCatalogItems |
| internalListItemsByCatalogCode | - | - |
| getCatalogItem | CatalogItem | ReadCatalogItem |
| internalGetCatalogItem | - | - |
| getCatalogItemByCode | CatalogItem | ReadCatalogItem |
| internalGetCatalogItemByCode | - | - |
| getCatalogItemBatch | CatalogItem | ReadCatalogsItems |
| internalGetCatalogItemBatch | - | - |
CreateCatalog (Alexandrina)
На входе данные справочника
{
"code": "cities",
"title": "Города",
"metadata": {},
"isProtected": false
}
На выходе строка с id созданного справочника
"0effa436-06c2-42cc-befe-8ebec417fc5a"
Создание справочника. Отправляет событие о создании справочника.
Имя вызова команды: createCatalog.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
- На входе: CreateCatalogDTO
- На выходе: UUID string
UpdateCatalog (Alexandrina)
На входе данные справочника
{
"id": "0effa436-06c2-42cc-befe-8ebec417fc5a",
"code": "cities",
"title": "Города",
"metadata": {},
"version": 2,
"isProtected": false
}
На выходе количество обновленных записей
0
Изменение данных справочника. Использует оптимистичную блокировку. Если изменяемый справочник был изменен параллельно, тогда вернется 0, показывающий, что не произошло обновления из-за некорректной версии. Отправляет событие об обновлении справочника.
Имя вызова команды: updateCatalog.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
- На входе: UpdateCatalogDTO
- На выходе: integer - количество обновленных записей (0 - не было успешного обновления, 1 - было)
RemoveCatalog (Alexandrina)
На входе ID справочника
"0effa436-06c2-42cc-befe-8ebec417fc5a"
На выходе признак успешности
true
Удаление справочника и всех его элементов. Отправляет событие об удалении справочника и всех его элементов.
Имя вызова команды: removeCatalog.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
- На входе: UUID string
- На выходе: boolean. True - удаление успешно, false - неуспешно.
ListCatalogs (Alexandrina)
Входных данных нет
На выходе список справочников
[
{
"id": "0effa436-06c2-42cc-befe-8ebec417fc5a",
"code": "cities",
"title": "Города",
"metadata": {},
"modified": 1632978484446,
"version": 1,
"items": 4,
"isProtected": false
}
]
Получение списка всех справочников. Пока без пейджинга, сортировки, и т.п.
Имя вызова команды: listCatalogs.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Команда не принимает параметров
- На выходе: List[Catalog]
SearchCatalogs (Alexandrina)
На входе параметры для поиска справочников
{
"query": "",
"context": {},
"sorting": {
"fieldName": "title",
"order": "asc"
},
"paging": {
"page": 1,
"count": 10
}
}
На выходе список справочников в структуре Page
{
"items": [
{
"id": "0effa436-06c2-42cc-befe-8ebec417fc5a",
"code": "cities",
"title": "Города",
"metadata": {},
"modified": 1632978484446,
"version": 1,
"items": 4,
"isProtected": false
}
],
"total": 1
}
Получение списка справочников с возможностью фильтрации, сортировки и пагинации.
Имя вызова команды: searchCatalogs.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
По умолчанию сортировка производится по полю code.
Запрос принимает параметры сортировки, фильтров и пейджинга в параметре search с типом Search. Применяется к полям модели Catalog.
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров |
|---|---|
| code | InSetQuery, LikeQuery |
| title | InSetQuery, LikeQuery |
Доступные поля для сортировки:
| Поле |
|---|
| code |
| title |
GetCatalog (Alexandrina)
На входе ID справочника
"0effa436-06c2-42cc-befe-8ebec417fc5a"
На выходе данные справочника
{
"id": "0effa436-06c2-42cc-befe-8ebec417fc5a",
"code": "cities",
"title": "Города",
"metadata": {},
"modified": 1632978484446,
"version": 1,
"items": 4,
"isProtected": false
}
Получение данных справочника по ID.
Имя вызова команды: getCatalog.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: UUID string
- На выходе: Catalog
InternalGetCatalog (Alexandrina)
На входе ID справочника
"0effa436-06c2-42cc-befe-8ebec417fc5a"
На выходе данные справочника
{
"id": "0effa436-06c2-42cc-befe-8ebec417fc5a",
"code": "cities",
"title": "Города",
"metadata": {},
"modified": 1632978484446,
"version": 1,
"items": 4,
"isProtected": false
}
Получение данных справочника по ID.
Имя вызова команды: internalGetCatalog.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
Внутренняя команда не требующая авторизацию.
- На входе: UUID string
- На выходе: Catalog
GetCatalogByCode (Alexandrina)
На входе код справочника
"cities"
На выходе данные справочника
{
"id": "0effa436-06c2-42cc-befe-8ebec417fc5a",
"code": "cities",
"title": "Города",
"metadata": {},
"modified": 1632978484446,
"version": 1,
"items": 4,
"isProtected": false
}
Получение данных справочника по коду.
Имя вызова команды: getCatalogByCode.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: string
- На выходе: Catalog
InternalGetCatalogByCode (Alexandrina)
На входе код справочника
"cities"
На выходе данные справочника
{
"id": "0effa436-06c2-42cc-befe-8ebec417fc5a",
"code": "cities",
"title": "Города",
"metadata": {},
"modified": 1632978484446,
"version": 1,
"items": 4,
"isProtected": false
}
Получение данных справочника по коду.
Имя вызова команды: internalGetCatalogByCode.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
Внутренняя команда не требующая авторизацию.
- На входе: string
- На выходе: Catalog
ExportCatalogs (Alexandrina)
На входе ID справочников и признак исключения из выгрузки (опциональный)
{
"ids": [
"ac94000f-3b61-4327-b2db-2ed0c2f01b38",
"0c69afa4-2a1f-45ad-8269-a9d14d7b7a7d"
],
"exclude": false
}
На выходе URL сформированного JSON-файла
"export/71ab0531-f916-4b46-9bb5-e7684940d3df"
Выгрузка массива справочников в хранилище файлов в формате JSON. Результат команды - url этого файла,
который можно передать в метод /download.
Параметр exclude: false позволяет выгрузить справочники с переданными ID (по умолчанию), true - все справочники,
кроме справочников с переданными ID.
Имя вызова команды: exportCatalogs.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: ExportParams
- На выходе: file URL string
ExportCatalogsXls (Alexandrina)
На входе ID справочников и признак исключения из выгрузки (опциональный)
{
"ids": [
"ac94000f-3b61-4327-b2db-2ed0c2f01b38",
"0c69afa4-2a1f-45ad-8269-a9d14d7b7a7d"
],
"exclude": false
}
На выходе URL сформированного zip-файла
"export/71ab0531-f916-4b46-9bb5-e7684940d3df"
Выгрузка массива справочников (в виде xls файлов) в хранилище файлов в формате Zip. Результат команды - url этого файла,
который можно передать в метод /download.
Параметр exclude: false позволяет выгрузить справочники с переданными ID (по умолчанию), true - все справочники,
кроме справочников с переданными ID.
Имя вызова команды: exportCatalogsXls.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: ExportParams
- На выходе: file URL string
ParseCatalogs (Alexandrina)
На входе ID файла
"71ab0531-f916-4b46-9bb5-e7684940d3df"
Пример JSON файла с указанным ID
{
"version": "1.0",
"dataType": "catalogs",
"data": [
{
"code": "cities",
"title": "Города",
"metadata": {},
"items": [
{
"code": "Moscow",
"title": "Москва",
"archived": false,
"metadata": {
"status": "federal"
},
"isProtected": false
},
{
"code": "Tyumen",
"title": "Тюмень",
"archived": false,
"metadata": {},
"isProtected": false
}
],
"isProtected": false
},
{
"code": "countries",
"title": "Страны",
"metadata": {},
"items": [],
"isProtected": false
}
]
}
На выходе массив справочников с элементами и признаком наличия
[
{
"code": "cities",
"title": "Города",
"metadata": {},
"items": [
{
"code": "Moscow",
"title": "Москва",
"archived": false,
"metadata": {
"status": "federal"
}
},
{
"code": "Tyumen",
"title": "Тюмень",
"archived": false,
"metadata": {}
}
],
"present": true
},
{
"code": "countries",
"title": "Страны",
"metadata": {},
"items": [],
"present": false
}
]
Парсинг JSON-файла со справочниками.
Параметр present: true - справочник с таким кодом существует, false - отсутствует.
Имя вызова команды: parseCatalogs.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: UUID string - ID json-файла со справочниками из временного бакета temp
- Формат файла: ExchangeTemplate
- На выходе: CatalogParseDTO array
ImportCatalogs (Alexandrina)
На входе массив справочников с элементами
[
{
"code": "countries",
"title": "Страны",
"metadata": {},
"isProtected": false,
"ignoreProtection": true,
"items": [
{
"code": "Russia",
"title": "Россия",
"archived": false,
"metadata": {},
"isProtected": false
}
]
}
]
На выходе количество обновленных/добавленных справочников
{
"failedImport": [
{
"code": "countries",
"items": [
{
"code": "Russia"
}
]
}
]
}
Импорт массива справочников и массивов их элементов. Если справочник или элемент с таким кодом существует, он будет обновлен, если нет - будет создан новый. Допускается наличие посторонних полей, при импорте они будут игнорироваться. Отправляет события о созданных/обновленных справочниках и элементах.
Имя вызова команды: importCatalogs.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
- На входе: CatalogExchangeDTO array
- На выходе: ImportResultDTO
ParseCatalogsXls (Alexandrina)
На входе
{
"fileUrl": "export/241f94cd-e4ef-4191-a7c9-c96352eeb5dc",
"startRow": 2,
"targetFileNames": [
"Профессия.xls"
]
}
На выходе содержимое zip файла
{
"importData": [
{
"fileName": "Профессия.xls",
"extension": "xls",
"title": "Профессия",
"code": "proffff",
"present": true,
"metadata": {},
"items": [
{
"code": "proffff-1",
"title": "Аналитик",
"archived": false,
"metadata": {},
"isProtected": true
},
{
"code": "proffff-2",
"title": "Разработчик",
"archived": false,
"metadata": {},
"isProtected": true
},
{
"code": "proffff-3",
"title": "Тестировщик",
"archived": false,
"metadata": {},
"isProtected": true
}
]
}
],
"rejectedFiles": []
}
Структура обязательного содержимого в таблице xls.
Колонка 1 - Код - string.
Колонка 2 - Наименование - string.
Колонка 3 - Метаданные - json.
Колонка 4 - Архивирован - "Да", "Нет", "ЛОЖЬ", "ИСТИНА", "Актуально", "Неактуально".
Колонка 5 - Защищен - "Да", "Нет", "ЛОЖЬ", "ИСТИНА", "Актуально", "Неактуально".
Колонки могут быть в разных позициях, информация считывается не по позиции в таблице, а по имени колонки.
Пример содержимого таблицы в xls файле.
| Код | Наименование | Метаданные | Архивирован | Защищен | Создан | Изменен | ID |
|---|---|---|---|---|---|---|---|
| proffff-1 | Аналитик | object[] | Да | Нет | 1,72891E+12 1,72891E+12 | 0ea026f1-d065-47e4-9dbf-5a4555c6247e | |
| proffff-2 | Разработчик | object[] | Да | Нет | 1,72891E+12 | 1,72891E+12 | 0ea026f1-d065-47e4-9dbf-5a4555c6247e |
| proffff-3 | Тестировщик | object[] | Да | Нет | 1,72891E+12 | 1,72891E+12 | 0ea026f1-d065-47e4-9dbf-5a4555c6247e |
Другие варианты структур будут парситься неверно.
Роут работает в связке с роутом ExportCatalogsXls, который формирует zip с xls файлом внутри.
Задача команды - предоставить информацию о содержимом файлов, что содержатся в переданном zip-архиве, либо содержимом переданного файла xls или xlsx. Файлы других расширений игнорируются. Если в строчках xls/xlsx данные не распарсились, берем информацию из базы данных.
Имя вызова команды: parseCatalogsXls.
Поддерживается синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: ParseCatalogsXlsDTO
- На выходе: ParseCatalogsXlsResultDTO
CreateCatalogItem (Alexandrina)
На входе данные элемента справочника
{
"catalogId": "0effa436-06c2-42cc-befe-8ebec417fc5a",
"code": "moscow",
"title": "Москва",
"metadata": {},
"isProtected": false
}
На выходе строка с ID созданного элемента справочника
"cee05b97-ca41-4355-8565-d667c6807cbd"
Создание элемента справочника. Отправляет событие о создании элемента справочника, а также событие об обновлении справочника, так как изменилось количество элементов.
Имя вызова команды: createCatalogItem.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
- На входе: CreateCatalogItemDTO
- На выходе: UUID string
UpdateCatalogItem (Alexandrina)
На входе данные элемента справочника
{
"id": "cee05b97-ca41-4355-8565-d667c6807cbd",
"code": "moscow",
"title": "Москва",
"metadata": {},
"version": 2,
"isProtected": false
}
На выходе количество измененных записей
0
Изменение элемента справочника. Использует оптимистичную блокировку. Если изменяемый элемент был изменен параллельно, тогда вернется 0, показывающий, что не произошло обновления из-за некорректной версии. Отправляет событие об обновлении элемента справочника.
Имя вызова команды: updateCatalogItem.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
- На входе: UpdateCatalogItemDTO
- На выходе: integer - количество обновленных записей (0 - не было успешного обновления, 1 - было)
ArchiveCatalogItem (Alexandrina)
На входе ID элемента справочника и признак архивности
{
"id": "cee05b97-ca41-4355-8565-d667c6807cbd",
"archived": true
}
На выходе признак успешности
true
Архивирование элемента справочника. Отправляет событие об обновлении элемента справочника.
Имя вызова команды: archiveCatalogItem.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: ArchiveCatalogItemDTO
- На выходе: boolean. True - признак архивности изменен успешно, false - признак архивности не изменен.
RemoveCatalogItem (Alexandrina)
На входе ID элемента справочника
"cee05b97-ca41-4355-8565-d667c6807cbd"
На выходе признак успешности
true
Удаление элемента справочника. Отправляет событие об удалении элемента справочника, а также об обновлении справочника, так как количество элементов изменилось.
Имя вызова команды: removeCatalogItem.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
- На входе: UUID string
- На выходе: boolean. True - удаление успешно, false - неуспешно.
RemoveItemsFromCatalog (Alexandrina)
На входе ID справочника
"0effa436-06c2-42cc-befe-8ebec417fc5a"
На выходе количество удаленных элементов справочника
15
Удаление всех элементов из справочника.
Имя вызова команды: removeItemsFromCatalog.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
- На входе: UUID string
- На выходе: integer
ListItemsByCatalog (Alexandrina)
На входе параметры для поиска элементов справочника, ID которого указан
{
"data": "0effa436-06c2-42cc-befe-8ebec417fc5a",
"search": {
"query": "",
"context": {},
"sorting": {
"fieldName": "title",
"order": "asc"
},
"paging": {
"page": 1,
"count": 10
}
}
}
На выходе список элементов справочника
{
"items": [
{
"id": "cee05b97-ca41-4355-8565-d667c6807cbd",
"catalogId": "0effa436-06c2-42cc-befe-8ebec417fc5a",
"code": "moscow",
"title": "Москва",
"archived": false,
"metadata": {},
"created": 1632978484446,
"modified": 1632979205601,
"version": 2,
"isProtected": false
}
],
"total": 1
}
Получение списка всех элементов указанного справочника.
Имя вызова команды: listItemsByCatalog.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: ListBy[CatalogId]
- На выходе: Page[CatalogItem]
По умолчанию сортировка производится по полю title.
Запрос принимает параметры сортировки, фильтров и пейджинга в параметре search с типом Search. Применяется к полям модели CatalogItem.
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров |
|---|---|
| id | InSetQuery, LikeQuery |
| catalogId | InSetQuery, LikeQuery |
| code | InSetQuery, LikeQuery |
| title | InSetQuery, LikeQuery |
| archived | InSetQuery |
| created | InSetQuery, LikeQuery, RangeQuery |
| modified | InSetQuery, LikeQuery, RangeQuery |
Если поле для фильтрации имеет вид metadata.something,
то фильтрация идет по содержимому соответствующего поля в metadata. Для этих фильтров
поддерживаются виды AllInSetQuery (только для вложенных полей-массивов), InSetQuery, LikeQuery, RangeQuery (только для
вложенных полей-чисел).
В случае если название поля не совпадает с одним из названий из таблицы выше и не имеет префикса metadata (например,
поле something), будет возвращена ошибка.
В случае если запрос InSetQuery или LikeQuery производится по содержимому поля json-объекта, которое не является строкой, то объект будет приведен к строке, содержащей json, и поиск будет произведен по ней.
В случае если запрос AllInSetQuery производится по содержимому поля json-объекта, которое не является массивом, то вернется ошибка. В случае если запрос RangeQuery производится по содержимому поля json-объекта, которое не является числом, то вернется ошибка.
Доступные поля для сортировки:
| Поле |
|---|
code |
created |
modified |
metadata.* |
Для полей metadata.* реализована натуральная сортировка.
InternalListItemsByCatalog (Alexandrina)
На входе параметры для поиска элементов справочника, ID которого указан
{
"data": "0effa436-06c2-42cc-befe-8ebec417fc5a",
"search": {
"query": "",
"context": {},
"sorting": {
"fieldName": "title",
"order": "asc"
},
"paging": {
"page": 1,
"count": 10
}
}
}
На выходе список элементов справочника
{
"items": [
{
"id": "cee05b97-ca41-4355-8565-d667c6807cbd",
"catalogId": "0effa436-06c2-42cc-befe-8ebec417fc5a",
"code": "moscow",
"title": "Москва",
"archived": false,
"metadata": {},
"created": 1632978484446,
"modified": 1632979205601,
"version": 2,
"isProtected": false
}
],
"total": 1
}
Получение списка всех элементов указанного справочника.
Имя вызова команды: internalListItemsByCatalog.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway), не требует аутентификации.
- На входе: ListBy[CatalogId]
- На выходе: Page[CatalogItem]
По умолчанию сортировка производится по полю title.
Запрос принимает параметры сортировки, фильтров и пейджинга в параметре search с типом Search. Применяется к полям модели CatalogItem.
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров |
|---|---|
| id | InSetQuery, LikeQuery |
| catalogId | InSetQuery, LikeQuery |
| code | InSetQuery, LikeQuery |
| title | InSetQuery, LikeQuery |
| archived | InSetQuery |
| created | InSetQuery, LikeQuery, RangeQuery |
| modified | InSetQuery, LikeQuery, RangeQuery |
Если поле для фильтрации имеет вид metadata.something,
то фильтрация идет по содержимому соответствующего поля в metadata. Для этих фильтров
поддерживаются виды AllInSetQuery (только для вложенных полей-массивов), InSetQuery, LikeQuery, RangeQuery (только для
вложенных полей-чисел).
В случае если название поля не совпадает с одним из названий из таблицы выше и не имеет префикса metadata (например,
поле something), будет возвращена ошибка.
В случае если запрос InSetQuery или LikeQuery производится по содержимому поля json-объекта, которое не является строкой, то объект будет приведен к строке, содержащей json, и поиск будет произведен по ней.
В случае если запрос AllInSetQuery производится по содержимому поля json-объекта, которое не является массивом, то вернется ошибка. В случае если запрос RangeQuery производится по содержимому поля json-объекта, которое не является числом, то вернется ошибка.
Доступные поля для сортировки:
| Поле |
|---|
code |
created |
modified |
metadata.* |
Для полей metadata.* реализована натуральная сортировка.
ListItemsByCatalogCode (Alexandrina)
На входе параметры для поиска элементов справочника, код которого указан
{
"data": "cities",
"search": {
"query": "",
"context": {},
"sorting": {
"fieldName": "title",
"order": "asc"
},
"paging": {
"page": 1,
"count": 10
}
}
}
На выходе список элементов справочника
{
"items": [
{
"id": "cee05b97-ca41-4355-8565-d667c6807cbd",
"catalogId": "0effa436-06c2-42cc-befe-8ebec417fc5a",
"code": "moscow",
"title": "Москва",
"archived": false,
"metadata": {},
"created": 1632978484446,
"modified": 1632979205601,
"version": 2,
"isProtected": false
}
],
"total": 1
}
Получение списка всех элементов указанного справочника по коду справочника.
Имя вызова команды: listItemsByCatalogCode.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: ListBy[CatalogCode]
- На выходе: Page[CatalogItem]
По умолчанию сортировка производится по полю title.
Запрос принимает параметры сортировки, фильтров и пейджинга в параметре search с типом Search. Применяется к полям модели CatalogItem.
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров |
|---|---|
| id | InSetQuery, LikeQuery |
| catalogId | InSetQuery, LikeQuery |
| code | InSetQuery, LikeQuery |
| title | InSetQuery, LikeQuery |
| archived | InSetQuery |
| created | InSetQuery, LikeQuery, RangeQuery |
| modified | InSetQuery, LikeQuery, RangeQuery |
Если поле для фильтрации имеет вид metadata.something,
то фильтрация идет по содержимому соответствующего поля в metadata. Для этих фильтров
поддерживаются виды AllInSetQuery (только для вложенных полей-массивов), InSetQuery, LikeQuery, RangeQuery (только для
вложенных полей-чисел).
В случае если название поля не совпадает с одним из названий из таблицы выше и не имеет префикса metadata (например,
поле something), будет возвращена ошибка.
В случае если запрос InSetQuery или LikeQuery производится по содержимому поля json-объекта, которое не является строкой, то объект будет приведен к строке, содержащей json, и поиск будет произведен по ней.
В случае если запрос AllInSetQuery производится по содержимому поля json-объекта, которое не является массивом, то вернется ошибка. В случае если запрос RangeQuery производится по содержимому поля json-объекта, которое не является числом, то вернется ошибка.
Доступные поля для сортировки:
| Поле |
|---|
code |
created |
modified |
metadata.* |
Для полей metadata.* реализована натуральная сортировка.
InternalListItemsByCatalogCode (Alexandrina)
На входе параметры для поиска элементов справочника, код которого указан
{
"data": "cities",
"search": {
"query": "",
"context": {},
"sorting": {
"fieldName": "title",
"order": "asc"
},
"paging": {
"page": 1,
"count": 10
}
}
}
На выходе список элементов справочника
{
"items": [
{
"id": "cee05b97-ca41-4355-8565-d667c6807cbd",
"catalogId": "0effa436-06c2-42cc-befe-8ebec417fc5a",
"code": "moscow",
"title": "Москва",
"archived": false,
"metadata": {},
"created": 1632978484446,
"modified": 1632979205601,
"version": 2,
"isProtected": false
}
],
"total": 1
}
Получение списка всех элементов указанного справочника по коду справочника.
Имя вызова команды: internalListItemsByCatalogCode.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway), не требует аутентификации.
- На входе: ListBy[CatalogCode]
- На выходе: Page[CatalogItem]
По умолчанию сортировка производится по полю title.
Запрос принимает параметры сортировки, фильтров и пейджинга в параметре search с типом Search. Применяется к полям модели CatalogItem.
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров |
|---|---|
| id | InSetQuery, LikeQuery |
| catalogId | InSetQuery, LikeQuery |
| code | InSetQuery, LikeQuery |
| title | InSetQuery, LikeQuery |
| archived | InSetQuery |
| created | InSetQuery, LikeQuery, RangeQuery |
| modified | InSetQuery, LikeQuery, RangeQuery |
Если поле для фильтрации имеет вид metadata.something,
то фильтрация идет по содержимому соответствующего поля в metadata. Для этих фильтров
поддерживаются виды AllInSetQuery (только для вложенных полей-массивов), InSetQuery, LikeQuery, RangeQuery (только для
вложенных полей-чисел).
В случае если название поля не совпадает с одним из названий из таблицы выше и не имеет префикса metadata (например,
поле something), будет возвращена ошибка.
В случае если запрос InSetQuery или LikeQuery производится по содержимому поля json-объекта, которое не является строкой, то объект будет приведен к строке, содержащей json, и поиск будет произведен по ней.
В случае если запрос AllInSetQuery производится по содержимому поля json-объекта, которое не является массивом, то вернется ошибка. В случае если запрос RangeQuery производится по содержимому поля json-объекта, которое не является числом, то вернется ошибка.
Доступные поля для сортировки:
| Поле |
|---|
code |
created |
modified |
metadata.* |
Для полей metadata.* реализована натуральная сортировка.
GetCatalogItem (Alexandrina)
На входе ID элемента справочника
"cee05b97-ca41-4355-8565-d667c6807cbd"
На выходе данные элемента
{
"id": "cee05b97-ca41-4355-8565-d667c6807cbd",
"catalogId": "0effa436-06c2-42cc-befe-8ebec417fc5a",
"code": "moscow",
"title": "Москва",
"archived": false,
"metadata": {},
"created": 1632979205601,
"modified": 1632979205601,
"version": 1,
"isProtected": false
}
Получение данных по элементу справочника.
Имя вызова команды: getCatalogItem.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: UUID string
- На выходе: CatalogItem
InternalGetCatalogItem (Alexandrina)
На входе ID элемента справочника
"cee05b97-ca41-4355-8565-d667c6807cbd"
На выходе данные элемента
{
"id": "cee05b97-ca41-4355-8565-d667c6807cbd",
"catalogId": "0effa436-06c2-42cc-befe-8ebec417fc5a",
"code": "moscow",
"title": "Москва",
"archived": false,
"metadata": {},
"created": 1632979205601,
"modified": 1632979205601,
"version": 1,
"isProtected": false
}
Получение данных по элементу справочника.
Имя вызова команды: internalGetCatalogItem.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
Внутренняя команда не требующая авторизацию.
- На входе: UUID string
- На выходе: CatalogItem
GetCatalogItemByCode (Alexandrina)
На входе код справочника и элемента
{
"catalogCode": "cities",
"itemCode": "moscow"
}
На выходе данные элемента
{
"id": "cee05b97-ca41-4355-8565-d667c6807cbd",
"catalogId": "0effa436-06c2-42cc-befe-8ebec417fc5a",
"code": "moscow",
"title": "Москва",
"archived": false,
"metadata": {},
"created": 1632979205601,
"modified": 1632979205601,
"version": 1,
"isProtected": false
}
Получение элемента справочника по коду.
Имя вызова команды: getCatalogItemByCode.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: GetCatalogItemDTO
- На выходе: CatalogItem
InternalGetCatalogItemByCode (Alexandrina)
На входе код справочника и элемента
{
"catalogCode": "cities",
"itemCode": "moscow"
}
На выходе данные элемента
{
"id": "cee05b97-ca41-4355-8565-d667c6807cbd",
"catalogId": "0effa436-06c2-42cc-befe-8ebec417fc5a",
"code": "moscow",
"title": "Москва",
"archived": false,
"metadata": {},
"created": 1632979205601,
"modified": 1632979205601,
"version": 1,
"isProtected": false
}
Получение элемента справочника по коду.
Имя вызова команды: internalGetCatalogItemByCode.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
Внутренняя команда не требующая авторизацию.
- На входе: GetCatalogItemDTO
- На выходе: CatalogItem
GetCatalogItemBatch (Alexandrina)
На входе список ID элементов справочников
[
"cee05b97-ca41-4355-8565-d667c6807cbd",
"4a2424df-acf2-410f-8ed5-65b90675d5f1"
]
На выходе список запрашиваемых элементов
[
{
"id": "cee05b97-ca41-4355-8565-d667c6807cbd",
"catalogId": "0effa436-06c2-42cc-befe-8ebec417fc5a",
"code": "moscow",
"title": "Москва",
"archived": false,
"metadata": {},
"created": 1632979205601,
"modified": 1632979205601,
"version": 1,
"isProtected": false
},
{
"id": "4a2424df-acf2-410f-8ed5-65b90675d5f1",
"catalogId": "0effa436-06c2-42cc-befe-8ebec417fc5a",
"code": "Tyumen",
"title": "Тюмень",
"archived": false,
"metadata": {},
"created": 1632979205601,
"modified": 1632979205601,
"version": 1,
"isProtected": false
}
]
Получение данных по элементам справочников по их id. Батчевая версия простого вызова данных одного элемента. При переданном пустом списке вернет все элементы всех справочников в базе.
Имя вызова команды: getCatalogItemBatch.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: List[UUID string]
- На выходе: List[CatalogItem]
InternalGetCatalogItemBatch (Alexandrina)
На входе список ID элементов справочников
[
"cee05b97-ca41-4355-8565-d667c6807cbd",
"4a2424df-acf2-410f-8ed5-65b90675d5f1"
]
На выходе список запрашиваемых элементов
[
{
"id": "cee05b97-ca41-4355-8565-d667c6807cbd",
"catalogId": "0effa436-06c2-42cc-befe-8ebec417fc5a",
"code": "moscow",
"title": "Москва",
"archived": false,
"metadata": {},
"created": 1632979205601,
"modified": 1632979205601,
"version": 1
},
{
"id": "4a2424df-acf2-410f-8ed5-65b90675d5f1",
"catalogId": "0effa436-06c2-42cc-befe-8ebec417fc5a",
"code": "Tyumen",
"title": "Тюмень",
"archived": false,
"metadata": {},
"created": 1632979205601,
"modified": 1632979205601,
"version": 1
}
]
Получение данных по элементам справочников по их id. Батчевая версия простого вызова данных одного элемента. При переданном пустом списке вернет все элементы всех справочников в базе.
Имя вызова команды: internalGetCatalogItemBatch.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
Внутренняя команда не требующая авторизацию.
- На входе: List[UUID string]
- На выходе: List[CatalogItem]
Публикуемые события
События публикуются в ALEXANDRINA_CATALOG_EVENTS_TOPIC.
| eventType | payloadType | payloadId | Описание |
|---|---|---|---|
| catalogUpsert | catalog | Id каталога | Каталог создан или обновлен |
| catalogItemUpsert | catalogItem | Id элемента каталога | Элемент каталога создан или обновлен |
| catalogRemoval | removeCatalog | Id каталога | Каталог удален |
| catalogItemRemoval | removeCatalogItem | Id элемента каталога | Элемент каталога удален |
Модели сервиса Alexandrina
Типы данных, которые принимает на вход команд сервис справочников или возвращает в результате работы команды.
- CreateCatalogDTO
- UpdateCatalogDTO
- Catalog
- CreateCatalogItemDTO
- UpdateCatalogItemDTO
- CatalogItem
- GetCatalogItemDTO
- ArchiveCatalogItemDTO
- ExportParams
- CatalogItemExchangeDTO
- CatalogExchangeDTO
- CatalogParseDTO
- ExchangeTemplate
- ImportResultDTO
- FailedImportResultDTO
- FailedImportItemResultDTO
- ListBy[CatalogId]
- ListBy[CatalogCode]
- ParseCatalogsXlsDTO
- ParseCatalogsXlsResultDTO
CreateCatalogDTO (Alexandrina)
Создание справочника
| Поле | Тип | Обязательное | Значение по умолчанию | Описание |
|---|---|---|---|---|
| code | string | да | Строковый код справочника (32 символов) | |
| title | string | да | Человекочитаемое название справочника (200 символов) | |
| metadata | json object | да | Дополнительные данные справочника - объект JSON | |
| isProtected | boolean | нет | true |
Признак защиты записи от изменений |
UpdateCatalogDTO (Alexandrina)
Обновление справочника
| Поле | Тип | Обязательное | Значение по умолчанию | Описание |
|---|---|---|---|---|
| id | uuid string | да | ID справочника | |
| code | string | да | Строковый код справочника (32 символов) | |
| title | string | да | Человекочитаемое название справочника (10000 символов) | |
| metadata | json object | да | Дополнительные данные справочника - объект JSON | |
| version | integer | да | Версия, полученная при запросе данных справочника. Нужна для оптимистичных блокировок | |
| isProtected | boolean | нет | true |
Признак защиты записи от изменений |
Catalog (Alexandrina)
Справочник
| Поле | Тип | Обязательное | Значение по умолчанию | Описание |
|---|---|---|---|---|
| id | uuid string | да | ID справочника | |
| code | string | да | Строковый код справочника (32 символов) | |
| title | string | да | Человекочитаемое название справочника (200 символов) | |
| metadata | json object | да | Дополнительные данные справочника - объект JSON | |
| modified | TimeStamp | нет | TimeStamp.now |
Дата последнего изменения справочника |
| version | integer | нет | 1 | Версия данных. Нужна для оптимистичных блокировок |
| items | integer | нет | 0 | Количество элементов справочника (вычисляемое) |
| isProtected | boolean | нет | false |
Признак защиты записи от изменений |
CreateCatalogItemDTO (Alexandrina)
Создание элемента справочника
| Поле | Тип | Обязательное | Значение по умолчанию | Описание |
|---|---|---|---|---|
| catalogId | uuid string | да | ID справочника | |
| code | string | да | Строковый код элемента (32 символов) | |
| title | string | да | Человекочитаемое название элемента (10000 символов) | |
| metadata | json object | да | Дополнительные данные справочника - объект JSON | |
| isProtected | boolean | нет | true |
Признак защиты записи от изменений |
UpdateCatalogItemDTO (Alexandrina)
Обновление элемента справочника
| Поле | Тип | Обязательное | Значение по умолчанию | Описание |
|---|---|---|---|---|
| id | uuid string | да | ID элемента справочника | |
| code | string | да | Строковый код элемента (32 символов) | |
| title | string | да | Человекочитаемое название элемента (10000 символов) | |
| metadata | json object | да | Дополнительные данные справочника - объект JSON | |
| version | integer | да | Версия данных элемента. Нужна для оптимистичных блокировок | |
| isProtected | boolean | нет | true |
Признак защиты записи от изменений |
CatalogItem (Alexandrina)
Элемент справочника
| Поле | Тип | Обязательное | Значение по умолчанию | Описание |
|---|---|---|---|---|
| id | uuid string | да | ID элемента справочника | |
| catalogId | uuid string | да | ID справочника | |
| code | string | да | Строковый код элемента (32 символов) | |
| title | string | да | Человекочитаемое название элемента (10000 символов) | |
| archived | boolean | да | Признак архивности | |
| metadata | json object | да | Дополнительные данные справочника - объект JSON | |
| created | TimeStamp | нет | TimeStamp.now |
Дата создания элемента справочника |
| modified | TimeStamp | нет | TimeStamp.now |
Дата последнего изменения элемента справочника |
| version | integer | нет | 1 | Версия данных элемента. Нужна для оптимистичных блокировок |
| isProtected | boolean | нет | false |
Признак защиты записи от изменений |
GetCatalogItemDTO (Alexandrina)
Получение элемента справочника по коду
| Поле | Тип | Обязательное | Значение по умолчанию | Описание |
|---|---|---|---|---|
| catalogCode | string | да | Код справочника | |
| itemCode | string | да | Код элемента справочника |
ArchiveCatalogItemDTO (Alexandrina)
Данные для архивации/разархивации элемента справочника
| Поле | Тип | Обязательное | Значение по умолчанию | Описание |
|---|---|---|---|---|
| id | uuid string | да | ID элемента справочника | |
| archived | boolean | да | Признак архивности | |
| isProtected | boolean | нет | true |
Признак защиты записи от изменений |
ExportParams (Alexandrina)
Данные для экспорта справочника
| Поле | Тип | Обязательное | Значение по умолчанию | Описание |
|---|---|---|---|---|
| ids | uuid array | да | Массив ID справочников | |
| exclude | boolean | нет | false |
Признак исключения из выгрузки (опциональный, по умолчанию - false) |
CatalogExchangeDTO (Alexandrina)
Данные справочника для обмена
| Поле | Тип | Обязательное | Значение по умолчанию | Описание |
|---|---|---|---|---|
| code | string | да | Строковый код справочника (32 символов) | |
| title | string | да | Человекочитаемое название справочника (200 символов) | |
| metadata | json object | да | Дополнительные данные справочника - объект JSON | |
| items | CatalogItemExchangeDTO array | да | Массив элементов справочника | |
| isProtected | boolean | нет | true |
Признак защиты записи от изменений |
| ignoreProtection | boolean | нет | false |
Игнорировать признак защиты записи от изменений при загрузке данных |
CatalogItemExchangeDTO (Alexandrina)
Данные элемента справочника для обмена
| Поле | Тип | Обязательное | Значение по умолчанию | Описание |
|---|---|---|---|---|
| code | string | да | Строковый код элемента (32 символов) | |
| title | string | да | Человекочитаемое название элемента (10000 символов) | |
| archived | boolean | да | Признак архивности | |
| metadata | json object | да | Дополнительные данные справочника - объект JSON | |
| isProtected | boolean | нет | true |
Признак защиты записи от изменений |
CatalogParseDTO (Alexandrina)
Данные парсинга справочника
| Поле | Тип | Обязательное | Значение по умолчанию | Описание |
|---|---|---|---|---|
| code | string | да | Строковый код справочника (32 символов) | |
| title | string | да | Человекочитаемое название справочника (200 символов) | |
| metadata | json object | да | Дополнительные данные справочника - объект JSON | |
| items | CatalogItemExchangeDTO array | да | Массив элементов справочника | |
| present | boolean | да | Признак наличия справочника | |
| isProtected | boolean | нет | true |
Признак защиты записи от изменений |
| ignoreProtection | boolean | нет | false |
Игнорировать признак защиты записи от изменений при загрузке данных |
ExchangeTemplate (Alexandrina)
Данные JSON-файла со справочниками
| Поле | Тип | Обязательное | Значение по умолчанию | Описание |
|---|---|---|---|---|
| version | string | да | Версия файла | |
| dataType | string | да | Тип данных файла (всегда catalogs) | |
| data | CatalogParseDTO array | да | Массив справочников |
ImportResultDTO (Alexandrina)
Результат импорта данных
| Поле | Тип | Обязательное | Значение по умолчанию | Описание |
|---|---|---|---|---|
| failedImport | FailedImportResultDTO array | да | Список сущностей |
FailedImportResultDTO (Alexandrina)
Провальный импорт каталога
| Поле | Тип | Обязательное | Значение по умолчанию | Описание |
|---|---|---|---|---|
| code | string | да | Строковый код справочника (32 символов) | |
| items | FailedImportItemResultDTO array | да | Массив элементов справочника |
FailedImportItemResultDTO (Alexandrina)
Провальный импорт каталога
| Поле | Тип | Обязательное | Значение по умолчанию | Описание |
|---|---|---|---|---|
| code | string | да | Строковый код элемента (32 символов) |
ListBy[CatalogId] (Alexandrina)
Параметры для запроса списка элементов по идентификатору каталога
| Поле | Тип | Обязательное | Значение по умолчанию | Описание |
|---|---|---|---|---|
| data | String | да | Идентификатор каталога | |
| search | Search | да | Параметры поиска для списка элементов. |
ListBy[CatalogCode] (Alexandrina)
Параметры для запроса списка элементов по коду каталога
| Поле | Тип | Обязательное | Значение по умолчанию | Описание |
|---|---|---|---|---|
| data | String | да | Код каталога | |
| search | Search | да | Параметры поиска для списка элементов. |
ParseCatalogsXlsDTO (Alexandrina)
Параметры для запроса информации о справочниках xls
| Поле | Тип | Обязательное | Значение по умолчанию | Описание |
|---|---|---|---|---|
| fileUrl | string | да | Путь до файла в s3 | |
| startRow | int | нет | 2 | Строка, с которой начинаются данные в файлах (строчки начинаются с 1) |
| targetFileNames | string array | нет | Название конкретного файла из zip, данные которого хотим получить |
ParseCatalogsXlsResultDTO (Alexandrina)
Ответ запроса информации о справочниках xls
| Поле | Тип | Обязательное | Значение по умолчанию | Описание |
|---|---|---|---|---|
| importData | ImportDataEntity array | да | Информация о файлах | |
| rejectedFiles | string array | да | Названия файлов, с которыми не смогли работать |
ImportDataEntity (Alexandrina)
Структура для ответа в ParseCatalogsXlsResultDTO
| Поле | Тип | Обязательное | Значение по умолчанию | Описание |
|---|---|---|---|---|
| fileName | string | да | Название файла | |
| extension | string | да | Расширение файла | |
| title | string | да | Имя файла (без расширения) | |
| code | string | да | Код каталога | |
| present | boolean | да | Существует ли каталог с code | |
| metadata | json object | да | Метадата каталога | |
| items | CatalogItemExchangeDTO | да | Содержимое файла |
Api-gateway: сервис маршрутизации
Сервис является точкой входа в систему. Все общение между front-end и back-end происходит через этот сервис. Выполняет маршрутизацию команды в нужный сервис, а также обеспечивает извлечение из запроса необходимых данных, например, для авторизации.
Выполняет отправку команд в систему синхронным или асинхронным способом. Большинство команд может быть выполнено как синхронно, так и асинхронно. Для команды, выполняемой асинхронно, нужно запрашивать ее статус. Только так можно понять, закончила она свое выполнение или нет. Если команда еще не закончена, нужно попробовать запросить ее статус позднее.
Имеет следующие URL для взаимодействия с системой и командами:
- Синхронный запрос
- Асинхронный запрос
- Получение статуса
- Open API
- Загрузка файла в систему
- Скачивание файла из системы
- Метаданные файла
Конфигурирование Api Gateway
Требования к запуску Api Gateway
Запуск сервиса осуществляется локально через sbt, на стенде в docker на jvm.
Для корректной минимальной работы сервиса требуется обязательное подключение к Kafka и Consul. Для настройки подключения к ним нужно заполнить обязательные переменные окружения из раздела ниже.
Обеспечивает работу окружения Verdi. Требует еще CommandStatus для работы этого окружения.
Список переменных окружения Api Gateway
| Переменная | Тип | Обязательная | Значение по умолчанию | Описание |
|---|---|---|---|---|
APIGATEWAY_HTTP_HOST |
String |
Нет | "0.0.0.0" | Хост, на котором слушает HTTP-сервер |
APIGATEWAY_HTTP_PORT |
Int |
Нет | 8080 | Порт, на котором слушает HTTP-сервер |
APIGATEWAY_KAFKA_SERVERS |
String |
Да | "localhost:9092" | Адрес Kafka |
APIGATEWAY_KAFKA_COMMANDEVENT_TOPIC |
String |
Да | commandevents | Название кафка-топика для отправки сообщений со статусами выполняемых команд. ОБЯЗАТЕЛЬНО должно соответствовать названию этого топика в сервисе статуса команд. |
APIGATEWAY_KAFKA_AUTH_USER |
String |
Нет | "" | Название учетной записи Kafka. Если название не указано, то настройки авторизации не будут применены. |
APIGATEWAY_KAFKA_AUTH_PASSWORD |
String |
Нет | "" | Пароль учетной записи Kafka. |
APIGATEWAY_KAFKA_AUTH_PRINCIPAL |
String |
Нет | "" | Principal учетной записи Kafka в Kerberos(в случае соединения с kafka через Kerberos). |
APIGATEWAY_KAFKA_AUTH_KEYTAB_PATH |
String |
Нет | "" | Путь до keytab-файла(в случае соединения с kafka через Kerberos). |
APIGATEWAY_KAFKA_AUTH_TRUSTSTORE_LOCATION |
String |
Нет | "" | Путь до хранилища сертификатов (Java key store). Если путь не указан, то сертификат применяться не будет. |
APIGATEWAY_KAFKA_AUTH_TRUSTSTORE_PASSWORD |
String |
Нет | "" | Пароль к хранилищу сертификатов. |
APIGATEWAY_KAFKA_AUTH_MODE |
String |
Нет | "static" | Режим аутентификации: static - одна учетная запись на все запросы, mapping - учетная запись зависит от запроса |
APIGATEWAY_KAFKA_AUTH_CONFIG |
String |
Нет | "" | Настройки для аутентификации: если AuthMode = mapping, то необходим JSON с List[KafkaAuthConfig]. Переменная соответствует полю authConfig из KafkaAuthSettings. |
APIGATEWAY_KAFKA_AUTH_CACHE_SIZE |
Int |
Нет | Максимальный размер кеша для Kafka producer (количество активных соединений). | |
APIGATEWAY_KAFKA_AUTH_CACHE_TTL |
Duration String |
Нет | Время жизни Kafka producer в кеше. | |
APIGATEWAY_KAFKA_PRODUCER_PROPS |
String |
Нет | "max.request.size=1048576" | Дополнительные параметры для Kafka producer. Заполняются по шаблону "key1=value1;key2=value2". |
APIGATEWAY_CONSUL_ADDR |
URL |
Нет | "http://localhost:8500" | Адрес Consul |
APIGATEWAY_CONSUL_AUTH_USER |
String |
Нет | "" | Название учетной записи Сonsul. Если название не указано, то настройки авторизации не будут применены. |
APIGATEWAY_CONSUL_AUTH_PASSWORD |
String |
Нет | "" | Пароль учетной записи Сonsul. |
APIGATEWAY_CONSUL_RETRY_MAX |
Int |
Нет | 20 | Количество попыток переподключения к Consul |
APIGATEWAY_CONSUL_RETRY_DELAY |
Duration String |
Нет | 3 second | Задержка при попытках переподключения к Consul |
APIGATEWAY_ANONYMOUS_ACCESS_MODE |
String |
Нет | any | Режим доступа к командам для анонимных пользователей: any - все команды доступны; some - доступны команды из списка команд; none - ни одна команда не доступна |
APIGATEWAY_ANONYMOUS_ACCESS_COMMANDS |
String |
Нет | "" | Строка названиями команд, перечисленных через запятую "," |
APIGATEWAY_TOKEN_HANDLING |
String |
Нет | "Authorization=mon_http_UserCommandContextData_OauthAccessToken" | Настройки получения информации о пользователе НЕ с помощью JWT. Содержит строку с парами (хедер из запроса, который нужно передать команде; команда, которую нужно вызвать с пустым телом и данным хедером, чтобы получить данные о пользователе). Формат строки: "headerName1=commandName1;headerName2=commandName2;" headerName и commandName при этом не должны содержать = и ;.Хедеры обрабатываются по очереди в алфавитном порядке. Если в конфиге хедеру соответствует несколько команд, то команды с одним и тем же хедером вызываются в порядке возникновения пары с этой командой в строке с настройками. Для указания cookie можно использовать формат "Cookie:target_name1=commandName1;Cookie:target_name2=commandName2". В значении cookie ожидается формат "TOKEN_TYPE%20TOKEN" (пробел запрещен в cookie и заменен на %20) или просто "TOKEN". Поддерживаемые типы токенов: "Basic", "Bearer", "DPoP", "mac", "unknown", "N_A". Значение cookie будет отправлено как значение HTTP заголовка "Authorization": "TOKEN_TYPE%20TOKEN" преобразуется в "TOKEN_TYPE TOKEN", "TOKEN" будет передан как есть ("TOKEN"). В качестве информации о пользователе используется первый успешный вызов команды. |
APIGATEWAY_TRACE_DURATION |
Boolean |
Нет | false | Проводить ли трассировку вызова команд (логировать временные метки) |
APIGATEWAY_STACKTRACE_SHOW |
Boolean |
Нет | false | Выводить ли stack trace в ошибках |
APIGATEWAY_POLL_STATUS_TIMEOUT |
Duration String |
Нет | 3 seconds | Максимальное время ожидания для команды PollStatus. Ограничивает минимально возможное значение для параметра строки запроса "timeout". |
APIGATEWAY_POLL_STATUS_TIMEOUT_MAX |
Duration String |
Нет | 3 minutes | Ограничивает максимально возможное значение для параметра строки запроса "timeout" для ожидания статуса команды PollStatus. Самая верхняя граница для значений: 65535 секунд. |
APIGATEWAY_OPENAPI_TITLE |
String |
Нет | API Gateway | Заголовок генерируемого OpenAPI |
APIGATEWAY_OPENAPI_VERSION |
String |
Нет | 0.5 | Версия, отображаемая в генерируемом OpenAPI |
APIGATEWAY_OPENAPI_URLPREFIX |
String |
Нет | Префикс для всех url, публикуемых в генерируемом OpenAPI | |
APIGATEWAY_FS_REQUIRE |
Boolean |
Нет | false | Требуется ли использовать файловое хранилище. Если false, тогда не будут создаваться http-routes для работы с файлами |
APIGATEWAY_JWT_SIGNATURE |
String |
Нет | "my very secret string for signature" | Сигнатура для подписи и расшифровки jwt-токенов, используемых для аутентификации |
APIGATEWAY_AKKA_HTTP_PARSING_MAX_BYTES |
Size String |
Нет | 50m | Максимальный размер данных из http-запроса, который может быть принят и распаршен |
APIGATEWAY_AKKA_HTTP_PARSING_MAX_CHUNK_SIZE |
Size String |
Нет | 10m | Максимальный размер одной части http-запроса, который может быть принят и распаршен |
APIGATEWAY_AKKA_HTTP_PARSING_MAX_HEADER_COUNT |
Int |
Нет | 64 | Максимальное количество заголовков http-запроса, который может быть принят и распаршен |
APIGATEWAY_AKKA_HTTP_PARSING_MAX_HEADER_NAME_SIZE |
Int |
Нет | 64 | Максимальный размер названия заголовка из http-запроса, который может быть принят и распаршен |
APIGATEWAY_AKKA_HTTP_PARSING_MAX_HEADER_VALUE_SIZE |
Size String |
Нет | 8k | Максимальный размер значения заголовка из http-запроса, который может быть принят и распаршен |
APIGATEWAY_AKKA_HTTP_CLIENT_MAXCON |
Int |
Нет | 512 | Максимальное количество входящих http-соединений |
APIGATEWAY_AKKA_HTTP_CLIENT_MAXREQ |
Int |
Нет | 1024 | Максимальное количество одновременно обслуживаемых запросов |
APIGATEWAY_AKKA_HTTP_CLIENT_RESP_SUBSCR_TIMEOUT |
Duration String |
Нет | 1 second | Таймаут, за который нужно подписаться на обработку тела http-запроса после обработки заголовков запроса |
APIGATEWAY_AKKA_HTTP_CLIENT_IDLE_TIMEOUT |
Duration String |
Нет | 1 minute | Максимальное время на исходящий http-запрос (в какой-либо сервис) |
APIGATEWAY_AKKA_HTTP_HOST_CONN_POOL_CLIENT_IDLE_TIMEOUT |
Duration String |
Нет | равно APIGATEWAY_AKKA_HTTP_CLIENT_IDLE_TIMEOUT | Позволяет отдельно настроить максимальное время на исходящий http-запрос, использующий пул соединений (т.е. для синхронной отправки синхронной команды) |
APIGATEWAY_AKKA_HTTP_HOST_CONN_POOL_IDLE_TIMEOUT |
Duration String |
Нет | 30 second | Максимальное время жизни пула соединений (с каким-либо сервисом) при отсутствии исходящих соединений |
APIGATEWAY_AKKA_HTTP_SERVER_MAXCON |
Int |
Нет | 1024 | Максимальное количество входящих http-соединений |
APIGATEWAY_AKKA_HTTP_SERVER_IDLE_TIMEOUT |
Duration String |
Нет | 5 minutes | Максимальное время жизни входящего http-соединения |
APIGATEWAY_AKKA_HTTP_SERVER_REQUEST_TIMEOUT |
Duration String |
Нет | 5 minutes | Максимальное время обработки входящего http-запроса. Должно быть не больше предыдущего значения, иначе входящее соединение оборвется по таймауту времени жизни запроса |
APIGATEWAY_INTERNALCMD_ALLOW |
Boolean |
Нет | false | Позволять ли выполнять внутренние команды, не предназначенные для вызова с UI |
APIGATEWAY_SENDERLIB_COMMANDS_CACHE_UPDATEPERIOD |
Duration String |
Нет | 10 minutes | Время жизни кэша команд, получаемых из Consul |
APIGATEWAY_SENDERLIB_SERVICES_CACHE_UPDATEPERIOD |
Duration String |
Нет | 30 seconds | Время жизни кэша service discovery для данных адресов сервисов, получаемых из Consul |
APIGATEWAY_SENDERLIB_KAFKA_POLLING_PERIOD |
Duration String |
Нет | 1 second | Период опроса статуса kafka-команды. Нужно для синхронного выполнения асинхронных команд |
APIGATEWAY_SENDERLIB_KAFKA_POLLING_TIMEOUT |
Duration String |
Нет | 10 seconds | Таймаут для синхронного выполнения асинхронной kafka-команды |
APIGATEWAY_FS_URI |
URL |
Нет | "http://localhost:9000" | Адрес для подключения к хранилищу файлов по S3-API |
APIGATEWAY_FS_ACCESS_KEY_ID |
String |
Нет | minioadmin | Ключ доступа для хранилища файлов (aka логин) |
APIGATEWAY_FS_SECRET_ACCESS_KEY |
String |
Нет | minioadmin | Секретный ключ для хранилища файлов (aka пароль) |
APIGATEWAY_FS_UPLOAD_PARALLELISM |
Int |
Нет | 4 | Параллелизм для загрузки файлов |
APIGATEWAY_FS_AUTH_MODE |
String |
Нет | static | Режим аутентификации: static - одна учетная запись на все запросы, mapping - учетная запись зависит от запроса |
APIGATEWAY_FS_AUTH_CONFIG |
String |
Нет | "" | Настройки для аутентификации: если AuthMode = mapping, то необходим JSON с маппингом учетных записей |
APIGATEWAY_FS_CACHE_SIZE |
Int |
Нет | 1 | Максимальный размер кеша клиентов для хранилища файлов (количество активных соединений). |
APIGATEWAY_FS_CACHE_TTL |
Duration String |
Нет | Время жизни клиента в кеше | |
APIGATEWAY_FS_RETRY_ATTEMPTS |
Int |
Нет | 5 | Количество ретраев, которое будет произведено в случае Exception-а в операции FSClient-а и при вычитывании стрима в get операциях FSClient-а. |
APIGATEWAY_FS_RETRY_DELAY |
Duration String |
Нет | 10 millis | Задержка между ретраями операций FSClient-а. |
APIGATEWAY_FS_ZIO_SHORT_MESSAGE_MODE |
Boolean |
Нет | false | Флаг включения режима сохранения ошибок работы с файловым хранилищем в сервисе журналирования nestor. При включении режима ошибки в логах будут отображаться в сокращенном формате: Short zio message mode. ExceptionType: ТИП ОШИБКИ, Exception id: 'СГЕНЕРИРОВАННЫЙ UUID' added to journal. Указанный id будет фиксироваться в event записи nestor'а в поле data.id |
APIGATEWAY_TEMP_BUCKET |
String |
Нет | temp | Бакет в файловом хранилище для временных файлов, загружаемых на gateway |
APIGATEWAY_TEMP_USERCACHE_INIT_SIZE |
Int |
Нет | 16 | Изначальный размер кэша, хранящего сведения о том, какой пользователь загрузил какой временный файл (далее TEMP_USERCACHE). |
APIGATEWAY_TEMP_USERCACHE_MAX_SIZE |
Int |
Нет | 1000 | Максимально допустимый размер кэша TEMP_USERCACHE |
APIGATEWAY_TEMP_USERCACHE_DURATION |
Duration String |
Нет | 60 seconds | Время жизни записи с данными пользователя в кэше TEMP_USERCACHE |
APIGATEWAY_CACHE_USERINFO_MAX_SIZE |
Int |
Нет | 1000 | Максимально допустимый размер кэша CACHE_USERINFO |
APIGATEWAY_CACHE_USERINFO_DURATION |
Duration String |
Нет | 60 seconds | Время жизни записи с данными пользователя в кэше CACHE_USERINFO |
APIGATEWAY_KAFKA_CONSUMER_GROUP |
String |
Нет | api-gateway | Имя consumer-группы для чтения из кафка-топиков. |
APIGATEWAY_KAFKA_USEREVENT_TOPIC |
String |
Нет | userEvents | Название кафка-топика для получения событий пользователей |
APIGATEWAY_KAFKA_USEREVENT_PARTITIONS |
Int |
Нет | 1 | Число читаемых партиций из кафка-топика событий пользователей. |
APIGATEWAY_KAFKA_CONSUMER_RESTART_MIN_BACKOFF |
Duration String |
Нет | 1 second | Изначальная задержка до рестарта консьюмера после падения (увеличивается в 2 раза после каждого рестарта) |
APIGATEWAY_KAFKA_CONSUMER_RESTART_MAX_BACKOFF |
Duration String |
Нет | 30 seconds | Максимальное задержка до рестарта консьюмера после падения |
APIGATEWAY_KAFKA_CONSUMER_RESTART_RANDOM_FACTOR |
Double |
Нет | 0.2 | Коэффициент величины дополнительной случайной задержки(jitter) относительно основной задержки (При значении 0.2 задержка может быть до 20% больше, чем при 0). Если после умножения задержки на APIGATEWAY_KAFKA_CONSUMER_RESTART_RANDOM_FACTOR получится меньше 1 миллисекунды, то jitter будет приравнен к нулю. |
APIGATEWAY_KAFKA_CONSUMER_RESTART_MAX_RESTARTS |
Int |
Нет | 5 | Максимальное число рестартов консьюмера после падения (в пределах APIGATEWAY_KAFKA_CONSUMER_RESTART_MAX_RESTARTS_WITHIN) .После превышения этого числа сервис будет объявлен больным. Все рестарты для каждого отдельного сообщения увеличивают и общий счетчик рестартов консьюмера, поэтому при использовании APIGATEWAY_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS нужно указывать APIGATEWAY_KAFKA_CONSUMER_RESTART_MAX_RESTARTS > APIGATEWAY_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS или не указывать APIGATEWAY_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS совсем |
APIGATEWAY_KAFKA_CONSUMER_RESTART_MAX_RESTARTS_WITHIN |
Duration String |
Нет | 5 minutes | Временной отрезок, в который APIGATEWAY_KAFKA_CONSUMER_RESTART_MAX_RESTARTS ограничивает число рестартов |
APIGATEWAY_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS |
Int |
Нет | 2 | Максимальное количество раз, которое консьюмер перезапустится с неизменной очередью сообщений(в пределах DATA_MODEL_KAFKA_CONSUMER_RESTART_MAX_RESTARTS_WITHIN), прежде чем проигнорировать сообщение, на котором происходит ошибка (Указано количество рестартов, а не прочтений. Если APIGATEWAY_KAFKA_CONSUMER_RESTART_MAX_RESTARTS = 2, то ошибочное сообщение будет обработано 3 раза, после чего произойдет 3ий рестарт и оно будет проигнорировано). Если указать 0, то перезапуск произойдет, но сообщение будет обработано только в первый раз, когда произошла ошибка. Если указать значение меньше 0, то перезапуски все равно будут происходить, но игнорирование сообщений, вызывающих ошибку, будет отключено. |
APIGATEWAY_KAFKA_CONSUMER_PER_MESSAGE_RESTART_CACHE_SIZE |
Int |
Нет | 100 | Для каждого сообщения счетчик перепрочтений хранится в кэше. Максимальное количество значений в этом кэше. |
APIGATEWAY_KAFKA_CONSUMER_PER_MESSAGE_RESTART_CACHE_TTL |
Duration String |
Нет | 5 minutes | Для каждого сообщения счетчик перепрочтений хранится в кэше.Максимальное время жизни элемента в этом кэше. В случае отсутствия значения время жизни элемента не будет ограничено. |
APIGATEWAY_KAFKA_CONSUMER_POLL_TIMEOUT |
Duration String |
Нет | 10 milliseconds | timeout запроса poll для kafka consumer |
APIGATEWAY_KAFKA_CONSUMER_POLL_INTERVAL |
Duration String |
Нет | 100 milliseconds | интервал между запросами poll для kafka consumer |
APIGATEWAY_KAFKA_CONSUMER_PROPS |
String |
Нет | "max.poll.records=500;max.partition.fetch.bytes=524288" | дополнительные параметры для kafka consumer в формате "key1=value1;key2=value2" |
APIGATEWAY_KAFKA_PRODUCER_PROPS |
String |
Нет | "batch.size=524288;linger.ms=10;max.request.size=1048576" | дополнительные параметры для kafka producer в формате "key1=value1;key2=value2" |
APIGATEWAY_SENDERLIB_COMMANDS_HTTP_RETRY_ATTEMPTS |
Int |
Нет | 5 | Поле attempts из RetrySettings |
APIGATEWAY_SENDERLIB_COMMANDS_HTTP_RETRY_DELAY |
Duration String |
Нет | "5 seconds" | Поле delay из RetrySettings |
APIGATEWAY_SENDERLIB_COMMANDS_HTTP_RETRY_KIND |
String |
Нет | "OnSomeExceptions(ConnectException)" | CommandResultRetryConditionKind |
APIGATEWAY_LICENSE_PATH |
String |
Да | "" |
Путь до файла с лицензией (только binary format). Можно указать несколько лицензий, перечислив пути через запятую. Количество и порядок лицензий должны совпадать с количеством и порядком ключей для лицензий (APIGATEWAY_LICENSE_KEY). |
APIGATEWAY_LICENSE_KEY |
String |
Да | "" |
Путь до файла с публичным ключом лицензии. Можно указать несколько ключей, перечислив пути через запятую. Количество и порядок ключей должны совпадать с количеством и порядком лицензий (APIGATEWAY_LICENSE_PATH). |
APIGATEWAY_LICENSE_PATH_PRIORITY |
String |
Нет | "" |
Порядок использования лицензий. При пустом значении - порядок будет соответствовать порядку путей до файлов лицензий (APIGATEWAY_LICENSE_PATH). Строка должна содержать приоритет для каждой лицензии, приоритеты разделяются запятой (например, 1,5,2) - лицензии будут обрабатываться в порядке возрастания приоритета. |
LOG_LEVEL_JWT |
String |
Нет | "WARN" |
Уровень логирования операций во время валидации jwt |
LOG_LEVEL_LICENSE |
String |
Нет | "INFO" |
Уровень логирования операций с лицензиями |
Контроль доступа к командам
Анонимный доступ
Отправка запросов для анонимных пользователей контролируется переменными окружения: APIGATEWAY_ANONYMOUS_ACCESS_MODE
и APIGATEWAY_ANONYMOUS_ACCESS_COMMANDS.
Проверка доступа к командам осуществляется при каждой обработке запроса (sync/async отправка, проверка статуса,
загрузка и скачивание файлов).
На уровне ApiGateway только пользователь изначально без JWT будет считаться анонимным.
На уровне системы, анонимами также могут считаться пользователи, которые состоят в группе "Anonymous", даже если у них и есть валидный JWT. Это влияет только на проверку прав.
Если у пользователя изначально не было JWT и анонимный доступ разрешен, то apigateway отправит команду микросервису.
Если у пользователя изначально не было JWT и анонимный доступ запрещен, то apigateway не будет отправлять команду микросервису, а сразу вернет ошибку:
HTTP status 403
{
"message": "Anonymous access is not allowed",
"businessError": null,
"data": null,
"stackTrace": null
}
- Если в запросе пользователь передал JWT, но этот JWT не является валидным, то вне зависимости от настроек
анонимного доступа,
apigateway не будет отправлять команду микросервису, а сразу вернет ошибку 401 "SES001".
Исключениями из этого правила являются команды
mon_http_LoginByCredentials,mon_http_LoginByKerberos,mon_http_LoginByKeycloak,mon_http_GetKeycloakAuthUrl. В случае вызова этих команд apigateway всегда отправит команду сервису от лица анонимного пользователя(вне зависимости от настроек анонимного доступа в apigateway).
HTTP status 401
{
"message": null,
"businessError": "SES001",
"data": null,
"stackTrace": null
}
JWT не является валидным, если:
- нарушен его формат
- не совпадает подпись
- его срок действия истек
- он был инвалидирован apigateway в соответствии с правилами инвалидации и состоянием пользователя
Инвалидация JWT производится apigateway, если:
- Истек срок действия пароля пользователя и вызываемая команда не mon_http_ChangeUserPassword (этот тип инвалидации JWT возвращает другую ошибку, описанную в секции Время действия пароля).
- Статус пользователя = Deactivated
- Сервис mon вернул для пользователя контекст, содержащий дату деактивации deactivateAt и она прошла
- Сервис mon вернул для пользователя контекст, содержащий правило инвалидации, условие в которым выполнилось для
текущего пользователя.
На данный момент работа с правилами инвалидации производится с помощью команд сервиса mon mon_http_CloseAllUserSessions и mon_http_DeleteJwtInvalidation
Время действия пароля
Если у пользователя истекло время действия пароля, то команды не будут выполняться и на каждый вызов будет возвращаться ошибка
HTTP status 401
{
"message": "Password lifespan has been exceeded",
"businessError": "PWD001",
"data": null,
"stackTrace": null
}
Синхронный запрос
Отправляем команду на выполнение
import com.embedika.verdi.senderlib.Dispatcher
import com.embedika.verdi.models.command.CommandName
import com.embedika.verdi.models.RequestContext
import io.circe.Json
implicit val rc: RequestContext = RequestContext.builder().build()
val dispatcher: Dispatcher = VerdiFactory.dispatcher
dispatcher.sendCommandSync(CommandName("pingpong_ping_post"), Some(Json.obj("value" -> Json.fromString("ping"))))
POST /send/sync/pingpong_ping_post
{
"value": "ping"
}
Синхронно получаем результат выполнения команды
import com.embedika.verdi.models.command.{CommandAggregatedStatus, CommandName}
import com.embedika.verdi.models.error.ErrorResponse
import com.embedika.verdi.models.RequestContext
import io.circe.Json
import scala.concurrent.Future
import io.circe.syntax._
implicit val rc: RequestContext = RequestContext.builder().build()
val commandResponse: Future[Either[ErrorResponse, CommandAggregatedStatus]] =
dispatcher.sendCommandSync(CommandName("pingpong_ping_post"), Some(Json.obj("value" -> Json.fromString("ping"))))
val result = commandResponse.map { r => // Future response
r.map { cs => // Either command status
cs.value.as[PingResponse] // Option Json
}
}
{
"bodyLength": 172,
"value": "pong"
}
Отправляет команду на синхронное исполнение. Результат такого запроса возвращается сразу в ответе от Api Gateway. Запрос висит открытым все время обработки команды, пока не сформируется ответ. Применяется для простых команд, не требующих долгого выполнения. Например, запросы на чтение данных удобнее делать с помощью синхронных запросов.
Отправка команды
Чтобы синхронно выполнить команду необходимо знать ее название и
формат данных, которые она принимает.
Для этого нужно отправить POST-запрос, где в URL передать
название команды в {command_name}:
POST /send/sync/{command_name}
Формат тела запроса зависит от формата данных, которые принимает команда. Подразумевается, что при вызове команды мы знаем, какой формат данных принимает команда.
Результат
Результат выполнения команды будет доступен сразу в ответе. Тип ответа - JSON или файл, зависит от типа команды. Формат JSON зависит от конкретной выполняемой команды. Подразумевается, что при вызове команды мы знаем, какой формат данных возвращает команда.
Синхронный запрос через GET
GET /get/CommandName?data=%7B%22foo%22%3A123%2C%22bar%22%3A%22parameter%22%7D
Отправка команды
Тело запроса принимается в query параметре data как закодированный в urlencode json.
Например, при таком json
{
"foo": 123,
"bar": "parameter"
}
Запрос будет выглядеть так
GET /get/CommandName?data=%7B%22foo%22%3A123%2C%22bar%22%3A%22parameter%22%7D
Результат
Аналогичен результату синхронного запроса
Запросом через GET удобно скачивать файл. Для этого нужно вызвать команду, возвращающую файл (см. документацию других сервисов)
Асинхронный запрос
Отправляем команду на выполнение
import com.embedika.verdi.senderlib.Dispatcher
import com.embedika.verdi.models.error.ErrorResponse
import com.embedika.verdi.models.command.{CommandAggregatedStatus, CommandId, CommandName, CommandStatus}
import com.embedika.verdi.models.RequestContext
import scala.concurrent.Future
import io.circe.Json
implicit val rc: RequestContext = RequestContext.builder().build()
val dispatcher: Dispatcher = VerdiFactory.dispatcher
val commandIdF: Future[Either[ErrorResponse, CommandId]] =
dispatcher.sendCommandAsync(CommandName("pingpong_ping_kafka"), Some(Json.obj("value" -> Json.fromString("ping"))))
POST /send/async/pingpong_ping_kafka
{
"value": "ping"
}
Получаем в ответе id созданной команды
import com.embedika.verdi.senderlib.Dispatcher
import com.embedika.verdi.models.error.ErrorResponse
import com.embedika.verdi.models.command.{CommandAggregatedStatus, CommandId, CommandName, CommandStatus}
import com.embedika.verdi.models.RequestContext
import scala.concurrent.Future
import io.circe.Json
implicit val rc: RequestContext = RequestContext.builder().build()
val dispatcher: Dispatcher = VerdiFactory.dispatcher
val commandIdF: Future[Either[ErrorResponse, CommandId]] =
dispatcher.sendCommandAsync(CommandName("pingpong_ping_kafka"), Some(Json.obj("value" -> Json.fromString("ping"))))
"cd6fe966-9296-43bb-828d-7662cffb0c09"
Отправляет команду на асинхронное исполнение. Результат такого выполнения команды возвращается не сразу, а запрашивается дополнительно через некоторое время с помощью метода получения статуса. Запрос сразу возвращает id созданной команды и не висит открытым на протяжении всего выполнения команды. Применяется для сложных команд, выполнение которых может занять некоторое ощутимое время. Например, запросы на модификацию данных со сложными проверками, импорты, формирование документов, и т.п.
Отправка команды
Чтобы асинхронно выполнить команду необходимо знать ее название и
формат данных, которые она принимает.
Для этого нужно отправить POST-запрос, где в URL передать
название команды в {command_name}:
POST /send/async/{command_name}
Формат тела запроса зависит от формата данных, которые принимает команда. Подразумевается, что при вызове команды мы знаем, какой формат данных принимает команда.
Результат
В результате асинхронного запроса будет содержаться только одна строка с id команды, которая начала выполняться. Стоит отметить, что ответ будет JSON-строкой, а значит, содержать свое значение в кавычках.
Получение статуса
Запрашиваем статус GET-запросом, указывая id в URL
import com.embedika.verdi.senderlib.Dispatcher
import com.embedika.verdi.models.error.ErrorResponse
import com.embedika.verdi.models.command.{CommandAggregatedStatus, CommandId, CommandName, CommandStatus}
import com.embedika.verdi.models.RequestContext
import scala.concurrent.Future
import io.circe.Json
implicit val rc: RequestContext = RequestContext.builder().build()
val commandId: CommandId = ???
val dispatcher: Dispatcher = VerdiFactory.dispatcher
dispatcher.status(commandId)
}
GET /status/eee8f8d3-6e28-462a-be42-7e3d13b3bec3
Получаем описание текущего состояния команды
import com.embedika.verdi.senderlib.Dispatcher
import com.embedika.verdi.models.error.ErrorResponse
import com.embedika.verdi.models.command.{CommandAggregatedStatus, CommandId, CommandName, CommandStatus}
import com.embedika.verdi.models.RequestContext
import scala.concurrent.Future
import io.circe.Json
implicit val rc: RequestContext = RequestContext.builder().build()
val commandId: CommandId = ???
val dispatcher: Dispatcher = VerdiFactory.dispatcher
val status: Future[Either[ErrorResponse, Option[CommandAggregatedStatus]]] = dispatcher.status(commandId)
status.flatMap {
case Right(Some(CommandAggregatedStatus(CommandStatus.Completed, _, jsonValue, _))) =>
// команда выполнилась
doSomeUsefulAction()
case Right(Some(CommandAggregatedStatus(CommandStatus.InProcess, _, jsonValue, _))) =>
// команда еще выполнеяется
Future.successful(true)
case _ =>
Future.successful(false)
}
// команда еще выполняется
{
"status": "InProcess",
"timestamp": "2021-03-23T09:00:15.674384Z"
}
// команда выполнилась
{
"status": "Completed",
"timestamp": "2021-03-23T09:01:20.190815Z",
"value": {
"value": "pong"
}
}
Для запущенной команды получает ее текущий статус выполнения.
Применяется для асинхронных запросов. Клиент, вызвавший команду асинхронно,
должен на своей стороне организовать пуллинг состояний с помощью
этого вызова. Пуллинг должен продолжаться до тех пор, пока не вернется
состояние команды Completed. В этом случае в поле
value будут данные с ответом по команде.
Также нужно иметь в виду, что если вызвать status сразу же после ответа async-запроса, то status может вернуть ошибку 404. Это вызвано тем, что статус команды не успевает дойти до сервиса CommandStatus через kafka. Механизм пуллинга должен это учитывать.
Получение статуса с задержкой
GET /pollStatus/eee8f8d3-6e28-462a-be42-7e3d13b3bec3?timeout=30
Работа с данной командой аналогична работе с командой status
Для запущенной команды получает ее текущий статус выполнения. Если результат выполнения еще не доступен, то команда ждет некоторое время (это время можно настроить с помощью переменной окружения). Если по прошествию этого времени результат все еще не доступен, то вместо него возвращается последний статус команды. Если нет никакого статуса (например, указан несуществующий ID команды), то команда точно так же ждет некоторое время, а потом выдает либо появившийся статус, либо ошибку 404. Таким образом, эта команда может быть использована как альтернатива "пуллингу" для быстрых команд.
Формат запроса статуса команды
command_id: обязательный параметр
Для получения статуса запущенной команды нужно вызвать GET-запрос,
в котором в URL передать id запущенной команды в
{command_id}:
GET /status/{command_id}
GET /pollStatus/{command_id}
timeout: необязательный параметр
Дополнительно можно передать в параметрах строки запроса таймаут в секундах для пулинга
timeout:
GET /pollStatus/{command_id}?timeout=30
Ограничение для значений параметра timeout:
- минимальное значение ограничивается через переменную окружения "APIGATEWAY_POLL_STATUS_TIMEOUT"
- максимальное значение ограничивается через переменную окружения "APIGATEWAY_POLL_STATUS_TIMEOUT_MAX"
- если значение параметра не задано или не входит в диапазон "APIGATEWAY_POLL_STATUS_TIMEOUT" <= timeout <= " APIGATEWAY_POLL_STATUS_TIMEOUT_MAX" и timeout <= "65535 seconds", то будет использовано значение по умолчанию из переменной окружения "APIGATEWAY_POLL_STATUS_TIMEOUT"
Формат ответа со статусом команды
В ответе будет JSON с состоянием команды, временем последнего изменения
этого состояния и значение, которое вернула команда. Это значение
будет отсутствовать, если состояние команды отлично от
Created.
Поля в JSON ответа:
| Поле | Тип | Описание |
|---|---|---|
| status | Строка | Код текущего состояния команды. Список кодов смотри ниже |
| timestamp | Instant | Строковое представление даты последнего изменения состояния команды в UTC, соответствующее java-типу java.time.Instant |
| value | Json | Опциональное значение произвольного формата. Обычно некоторый JSON-объект. Зависит от вызываемой команды |
Статусы команды
| Код статуса | Описание |
|---|---|
| Created | Команда только что создана и не начата исполняться |
| InProcess | Сервис принял команду и начал ее выполнять |
| Completed | Команда успешно выполнена |
| Failed | Команда выполнена с ошибкой |
| TimedOut | Команда не успела выполниться за отведенное ей время |
Выполнение команд с OpenId connect Access token вместо JWT
При каждом выполнении команд пользователь предоставляет опциональный JWT, который он получает от сервиса Mon после прохождения операции "Login". Когда стороннему сервису требуется работать с системой, не всегда есть возможность проходить через "Login" для получения JWT. Чаще удобнее использовать общеизвестные протоколы (например, OpenId connect) и передавать токены.
Процесс выполнения команд в системе и для стороннего сервиса, и для пользователя почти не будет отличаться. Разница лишь в том, как клиент получает токен: пользователь в сервисе Mon, а сторонний сервис в общеизвестном авторизационном сервисе.
При выполнении команд аутентификация с Access token также проходит через сервис Mon, который валидирует токен во внешнем авторизационном сервисе.
Для простоты далее будут использоваться следующие сокращения:
- "сторонний сервис" = "AuxService"
- "общеизвестный авторизационный сервис" = "IdentityProvider"
Общий алгоритм выглядит следующим образом:
- AuxService авторизуется в IdentityProvider и получает Access token (возможны и другие варианты реализации данного
пункта (через grant_type = authorization_code), но главное получить Access token).
- Отправка POST запроса на "/protocol/openid-connect/token" с необходимыми данными (login, password, grant_type = password, client_id, client_secret и т.п.)
- Передаются "login" и "password" для пользователя, под которым впоследствии будут выполняться команды. Для него выдается Access token.
- Передаются "client_id" и "client_secret" для AuxService, который выполняет действия от имени пользователя.
- AuxService отправляет запрос на "какое-то действие" в сервис интеграции (внешнее API для AuxService). Access token должен передаваться в "Authorization" заголовке HTTP запроса с типом токена "Bearer".
- Сервис интеграции формирует CommandRequest из запроса от AuxService и отправляет его в ApiGateway.
- ApiGateway не находит JWT, но находит Access token. Отправляет запрос данных о пользователе с Access token в сервис Mon.
- Сервис Mon запрашивает от IdentityProvider профиль пользователя по Access token, тем самым валидируя токен. По полученному профилю в БД сервиса Mon ищется пользователь. Если пользователя нет (первое обращение к системе), то пользователь будет автоматически создан в системе.
- Сервис Mon отправляет найденные данные пользователя обратно в ApiGateway.
- ApiGateway обогащает CommandRequest данными пользователя и отправляет его в целевой сервис. Если данные пользователя не были получены (вернулась ошибка), то будет использованы данные для анонимного пользователя.
- ApiGateway получает ответ от целевого сервиса, куда отправлялась команда, и отвечает в сервис интеграции либо с ErrorResponse, либо со структурой ответа команды.
OpenAPI
{
"openapi": "3.0.3",
"info": {
"title": "API Gateway",
"version": "0.4"
},
"paths": {
"/sync/UpdateObjectByCode/accessMatrixRoleRBAM/{entityId}": {
"post": {
"description": "Обновляет объект по его Code",
"operationId": "postSyncUpdateobjectbycodeAccessmatrixrolerbamEntityid",
"parameters": [
{
"name": "entityId",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
}
],
"requestBody": {
"description": "Command arguments as JSON object",
"content": {
"text/plain": {
"schema": {
"type": "string"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "Command execution result as JSON object",
"content": {
"text/plain": {
"schema": {
"type": "string"
}
}
}
}
}
}
}
}
}
// не применимо
По url /openapi.json доступна спецификация OpenAPI
описывающая все доступные команды в виде разных URL.
Применяется для интеграции Api Gateway с различными системами.
Кроме того, полезно при разработке фронта.
Upload
Загрузка файла
POST /upload
// не применимо
Результат вызова
{
"fileId": "1c689788-9617-4c93-bcee-6eae8909a0ba",
"url": "temp/1c689788-9617-4c93-bcee-6eae8909a0ba"
}
// не применимо
Загрузить файл в систему. Загруженный файл помещается во временный бакет APIGATEWAY_TEMP_BUCKET.
Файл передается в multipart-formdata в поле file. Принимается запрос POST на url /upload.
На выходе возвращается объект, содержащий id загруженного файла и относительный URL, по которому доступен этот файл.
Далее можно использовать этот id для передачи в сервисы.
При каждой загрузке, файл "привязывается" к текущему пользователю на уровне данных FileMeta (ожидается, что в заголовках запроса будет Cookie с JWT или access token в header/cookie). В дальнейшем информация об этой привязке будет использоваться для определения начилия доступа к получению данных как самого файла, так и его метаданных. Если файл был загружен до появления функционала "привязки", то он считается доступным всем.
Анонимные пользователи воспринимаются как один и тот же пользователь, т.е. любой анонимный пользователь имеет доступ
ко всем файлам, что были загружены другими анонимными пользователями.
В текущей реализации, анонимный пользователь отличается от "залогиненого", т.е. "залогиненый" пользователь не имеет
доступа к файлам от "анонимов".
Чтобы получить такой доступ, нужно выйти из системы и обратиться к файлу в качестве "анонима".
Чтобы разрешить анонимный доступ, при APIGATEWAY_ANONYMOUS_ACCESS_MODE не равном any, нужно добавить в *
APIGATEWAY_ANONYMOUS_ACCESS_COMMANDS* значение apigw_uploadFile.
Download
При скачивании через этот метод не происходит проверки прав.
Поэтому лучше использовать команду getFile синхронно.
Скачивание файла
GET /download/temp/1c689788-9617-4c93-bcee-6eae8909a0ba
// не применимо
Скачивание файла из системы. Для скачивания передается GET-запрос. В url после /download/ передать url файла.
В этот url входит бакет, путь внутри бакета и id файла. HTTP-ответ формируется как файл.
При попытке обращения к файлу, происходит проверка наличия доступа у пользователя к файлу (ожидается, что в
заголовках запроса будет Cookie с JWT или access token в header/cookie). Если
доступа нет - возвращается статус 404 Not Found.
Детали предоставления и проверки доступа описаны в Загрузке файла в систему.
Чтобы разрешить анонимный доступ, при APIGATEWAY_ANONYMOUS_ACCESS_MODE не равном any, нужно добавить в *
APIGATEWAY_ANONYMOUS_ACCESS_COMMANDS* значение apigw_downloadFile.
После выполнения данного запроса http-клиент получит в ответе файл и хедер Content-Disposition,
с помощью которого http-клиент сможет понять, какое имя файла предложить пользователю при сохранении.
Если имя файла содержит только ASCII-символы, то хедер будет иметь вид
Content-Disposition: attachment; filename="MyFileName.pdf"
и с большой вероятностью будет успешно распознан любым http-клиентом.
В случае если возвращаемый файл имеет в имени символы, не входящие в ASCII,
то для корректной передачи имени будет использоваться дополнительное поле filename* и например для имени файла
"файл.pdf"
хедер будет иметь вид
Content-Disposition: attachment; filename="????.pdf"; filename*=utf-8''%D1%84%D0%B0%D0%B9%D0%BB.pdf.
Использование этого поля в хедере описано в RFC 6266,
но не все http-клиенты и браузеры поддерживают filename*. Если http-клиент поддерживает filename*,
то он предложит сохранить скачиваемый файл с именем, в котором будут отображены все содержащиеся в нем символы, но если
http-клиент не поддерживает filename*(например Safari, Internet Explorer версии 8 и раньше), то скорее всего будет
использовано имя из filename,
где все не-ASCII символы будут заменены на ?.
Metadata
Получение метаданных файла
GET /metadata/temp/1c689788-9617-4c93-bcee-6eae8909a0ba
// не применимо
Результат с метаданными
{
"fileId": "1c689788-9617-4c93-bcee-6eae8909a0ba",
"name": "Текстовый документ.pdf",
"size": 301,
"url": "temp/1c689788-9617-4c93-bcee-6eae8909a0ba",
"md5": "953c3ff8a7afa87d759fb606eabc8438",
"contentType": "application/pdf"
}
// не применимо
Получение метаданных файла в системе. Передается GET-запрос. В url после /metadata/ передать url файла.
В этот url входит бакет, путь внутри бакета и id файла. Возвращается json с метаданными файла.
При попытке обращения к метаданным файла, происходит проверка наличия доступа у пользователя к файлу (ожидается, что в
заголовках запроса будет Cookie с JWT или access token в header/cookie). Если
доступа нет - возвращается статус 404 Not Found.
Детали предоставления и проверки доступа описаны в Загрузке файла в систему.
Чтобы разрешить анонимный доступ, при APIGATEWAY_ANONYMOUS_ACCESS_MODE не равном any, нужно добавить в
APIGATEWAY_ANONYMOUS_ACCESS_COMMANDS значение apigw_getFileMeta.
Archiver: сервис архивации файлов
Сервис архивации файлов из S3 в zip архив, который сохраняется в собственном топике S3. Хранит информацию о сохраненных файлах, для быстрой выдачи уже созданных архивов.
Состояние хранится в PostgreSQL.
Команды могут приходить как по HTTP, так и через Kafka в топик archiver_commands.
Сервис разбит на несколько модулей, в виде sbt проектов:
domain, в котором содержатся все доменные модели и их различные представления.commands, в котором содержатся все, что связано с командами, их описанием и обработчиками.infrastructure, в котором содержится описание взаимодействия с другими сервисами.storage, содержит сервисы для сохранения и чтения их разных хранилищ доменных моделей.service, содержит сервисы бизнес логики, которые определяют правила взаимодействия компонентов между собой.boot, содержит зависимости и описание для сборки и запуска сервиса.
Локальный запуск
При запуске сервиса ожидается, что уже развернута необходимая инфраструктура:
- PostgreSQL база по адресу
localhost:5432/archiver_db - Kafka по адресу
localhost:9092 - Consul по адресу
localhost:8500 - Адрес Kafka будет указан в
application.conf - Добавлены необходимые переменные окружения:
- ARCHIVER_DB_HOST
- ARCHIVER_DB_PORT
- ARCHIVER_DB_NAME
- ARCHIVER_DB_USER
- ARCHIVER_DB_PASSWORD
Запуск из консоли с помощью SBT
ARCHIVER_DB_HOST=localhost ARCHIVER_DB_PORT=5432 ARCHIVER_DB_NAME=archiver_db ARCHIVER_DB_USER=postgres ARCHIVER_DB_PASSWORD=12345 sbt boot/run
Список переменных окружения сервиса Archiver
Все доступные переменные окружения для настройки сервиса.
| Переменная | Тип | Обязательная | Значение по умолчанию | Описание |
|---|---|---|---|---|
ARCHIVER_HTTP_HOST |
String |
Нет | "0.0.0.0" | Хост, на котором слушает HTTP-сервер |
ARCHIVER_HTTP_PORT |
Int |
Нет | 8193 | Порт, на котором слушает HTTP-сервер |
ARCHIVER_KAFKA_SERVERS |
String |
Да | "localhost:9092" | Адрес Kafka |
ARCHIVER_KAFKA_TOPIC |
String |
Нет | "archiver_commands" | Название кафка-топика для получения команд. Сервис получает кафка-команды по нему, но и также сам публикует это название в CommandDiscovery. |
ARCHIVER_KAFKA_CONSUMER_GROUP |
String |
Нет | "archiver_consumer_group" | Имя consumer-группы для чтения из кафка-топика команд. Не должна меняться и не должна быть пустой, иначе сервис перечитает свои команды при перезапуске. |
ARCHIVER_KAFKA_PARTITIONS |
Int |
Нет | 10 | Число читаемых партиций из кафка-топика команд. |
ARCHIVER_KAFKA_CONSUMER_RESTART_MIN_BACKOFF |
Duration String |
Нет | 1 second | Изначальная задержка до рестарта консьюмера после падения (увеличивается в 2 раза после каждого рестарта) |
ARCHIVER_KAFKA_CONSUMER_RESTART_MAX_BACKOFF |
Duration String |
Нет | 30 seconds | Максимальное задержка до рестарта консьюмера после падения |
ARCHIVER_KAFKA_CONSUMER_RESTART_RANDOM_FACTOR |
Double |
Нет | 0.2 | Коэффициент величины дополнительной случайной задержки(jitter) относительно основной задержки (При значении 0.2 задержка может быть до 20% больше, чем при 0). Если после умножения задержки на ARCHIVER_KAFKA_CONSUMER_RESTART_RANDOM_FACTOR получится меньше 1 миллисекунды, то jitter будет приравнен к нулю. |
ARCHIVER_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS |
Int |
Нет | 2 | Максимальное количество раз, которое консьюмер перезапустится с неизменной очередью сообщений(в пределах DATA_MODEL_KAFKA_CONSUMER_RESTART_MAX_RESTARTS_WITHIN), прежде чем проигнорировать сообщение, на котором происходит ошибка (Указано количество рестартов, а не прочтений. Если ARCHIVER_KAFKA_CONSUMER_RESTART_MAX_RESTARTS = 2, то ошибочное сообщение будет обработано 3 раза, после чего произойдет 3ий рестарт и оно будет проигнорировано). Если указать 0, то перезапуск произойдет, но сообщение будет обработано только в первый раз, когда произошла ошибка. Если указать значение меньше 0, то перезапуски все равно будут происходить, но игнорирование сообщений, вызывающих ошибку, будет отключено. |
ARCHIVER_KAFKA_CONSUMER_PER_MESSAGE_RESTART_CACHE_SIZE |
Int |
Нет | 100 | Для каждого сообщения счетчик перепрочтений хранится в кэше. Максимальное количество значений в этом кэше. |
ARCHIVER_KAFKA_CONSUMER_PER_MESSAGE_RESTART_CACHE_TTL |
Duration String |
Нет | 5 minutes | Для каждого сообщения счетчик перепрочтений хранится в кэше.Максимальное время жизни элемента в этом кэше. В случае отсутствия значения время жизни элемента не будет ограничено. |
ARCHIVER_KAFKA_CONSUMER_RESTART_MAX_RESTARTS |
Int |
Нет | 5 | Максимальное число рестартов консьюмера после падения (в пределах ARCHIVER_KAFKA_CONSUMER_RESTART_MAX_RESTARTS_WITHIN).После превышения этого числа сервис будет объявлен больным. Все рестарты для каждого отдельного сообщения увеличивают и общий счетчик рестартов консьюмера, поэтому при использовании ARCHIVER_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS нужно указывать ARCHIVER_KAFKA_CONSUMER_RESTART_MAX_RESTARTS > ARCHIVER_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS или не указывать ARCHIVER_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS совсем. |
ARCHIVER_KAFKA_CONSUMER_RESTART_MAX_RESTARTS_WITHIN |
Duration String |
Нет | 5 minutes | Временной отрезок, в который ARCHIVER_KAFKA_CONSUMER_RESTART_MAX_RESTARTS ограничивает число рестартов |
ARCHIVER_KAFKA_CONSUMER_POLL_TIMEOUT |
Duration String |
Нет | 10 milliseconds | timeout запроса poll для kafka consumer |
ARCHIVER_KAFKA_CONSUMER_POLL_INTERVAL |
Duration String |
Нет | 100 milliseconds | интервал между запросами poll для kafka consumer |
ARCHIVER_KAFKA_CONSUMER_PROPS |
String |
Нет | "max.poll.records=500;max.partition.fetch.bytes=524288" | дополнительные параметры для kafka consumer в формате "key1=value1;key2=value2" |
ARCHIVER_KAFKA_PRODUCER_PROPS |
String |
Нет | "batch.size=524288;linger.ms=10;max.request.size=1048576" | дополнительные параметры для kafka producer в формате "key1=value1;key2=value2" |
ARCHIVER_KAFKA_COMMANDEVENT_TOPIC |
String |
Да | "commandevents" | Название кафка-топика для отправки сообщений со статусами выполняемых команд. ОБЯЗАТЕЛЬНО должно соответствовать названию этого топика в сервисе статуса команд. |
ARCHIVER_KAFKA_AUTH_USER |
String |
Нет | "" | Название учетной записи Kafka. Если название не указано, то настройки авторизации не будут применены. |
ARCHIVER_KAFKA_AUTH_PASSWORD |
String |
Нет | "" | Пароль учетной записи Kafka. |
ARCHIVER_KAFKA_AUTH_TRUSTSTORE_LOCATION |
String |
Нет | "" | Путь до хранилища сертификатов (Java key store). Если путь не указан, то сертификат применятся не будет. |
ARCHIVER_KAFKA_AUTH_TRUSTSTORE_PASSWORD |
String |
Нет | "" | Пароль к хранилищу сертификатов. |
ARCHIVER_KAFKA_AUTH_MODE |
String |
Нет | "" | Режим аутентификации: static - одна учетная запись на все запросы, mapping - учетная запись зависит от запроса |
ARCHIVER_KAFKA_AUTH_CONFIG |
String |
Нет | "" | Настройки для аутентификации: если AuthMode = mapping, то необходим JSON с List[KafkaAuthConfig] |
ARCHIVER_KAFKA_AUTH_CACHE_SIZE |
Int |
Нет | Максимальный размер кеша для Kafka producer (количество активных соединений). | |
ARCHIVER_KAFKA_AUTH_CACHE_TTL |
Duration String |
Нет | Время жизни Kafka producer в кеше. | |
ARCHIVER_KAFKA_CONNECTION_CHECK_TEST_MESSAGES_INTERVAL |
Duration String |
Нет | 4 minutes | Применяется только для producer-ов со способом аутентификации kerberos. Интервал отправки тестовых сообщений кафки в топик connectionCheck.testMessagesTopicName. Тестовые сообщения (null, service producer test) отправляются регулярно с этим интервалом. |
ARCHIVER_KAFKA_CONNECTION_CHECK_INTERVAL |
Duration String |
Нет | 60 seconds | Применяется только для producer-ов со способом аутентификации kerberos. Интервал проверки того, сколько тестовых сообщений было отправлено за данный период. Если количество сообщений за этот период равно количеству сообщений за прошлый период, то начинается отсчет периода без сообщений. |
ARCHIVER_KAFKA_CONNECTION_CHECK_FAILED_AFTER_INTERVAL |
Duration String |
Нет | 5 minutes | Применяется только для producer-ов со способом аутентификации kerberos. Максимальная продолжительность периода без успешно отправленных тестовых сообщений. По ее достижении сервис будет объявлен больным. |
ARCHIVER_KAFKA_PRODUCER_PROPS |
String |
Нет | "max.request.size=1048576" | Дополнительные параметры для Kafka producer. Заполняются по шаблону "key1=value1;key2=value2". |
ARCHIVER_CONSUL_ADDR |
URL |
Нет | "http://localhost:8500" | Адрес Сonsul. |
ARCHIVER_CONSUL_AUTH_USER |
String |
Нет | "" | Название учетной записи Сonsul. Если название не указано, то настройки авторизации не будут применены. |
ARCHIVER_CONSUL_AUTH_PASSWORD |
String |
Нет | "" | Пароль учетной записи Сonsul. |
ARCHIVER_TRACE_DURATION |
Boolean |
Нет | false | Признак необходимости трассировки выполнения команд |
ARCHIVER_DISCOVERABLE_ID |
String |
Нет | "another_ARCHIVER_service_instance" | ID сервиса в ServiceDiscovery |
ARCHIVER_DISCOVERABLE_NAME |
String |
Нет | "archiver" | Имя сервиса в ServiceDiscovery |
ARCHIVER_DISCOVERABLE_HOST |
String |
Да | "localhost" | Хост, публикуемый в ServiceDiscovery. По нему на данный сервис будут обращаться другие через HTTP. Указанный адрес должен быть виден другим сервисам. Пример: имя kubernetes/docker_swarm service |
ARCHIVER_DISCOVERABLE_PORT |
Int |
Нет | Порт, публикуемый в ServiceDiscovery. По нему на данный сервис будут обращаться другие через HTTP. По умолчанию указывается порт, который слушает HTTP-сервер. | |
ARCHIVER_DISCOVERABLE_LIVETIME |
Duration String |
Нет | 2 minutes | Период после последней отправки health check, в течение которого ServiceDiscovery считает данный сервис живым. |
ARCHIVER_DISCOVERABLE_HEALTHPASS |
String |
Нет | 1 minute | Периодичность отправки health check в ServiceDiscovery |
ARCHIVER_SERVICE_TITLE |
String |
Нет | "Archiver" | Название сервиса для отображения |
ARCHIVER_SERVICE_DESCRIPTION |
String |
Нет | "Service ARCHIVER" | Описание сервиса для отображения |
ARCHIVER_AKKA_HTTP_CLIENT_MAXCON |
Int |
Нет | 512 | Максимальное число одновременных исходящих HTTP-соединений |
ARCHIVER_AKKA_HTTP_CLIENT_MAXREQ |
Int |
Нет | 1024 | Максимальное число одновременных исходящих HTTP-запросов |
ARCHIVER_AKKA_HTTP_SERVER_MAXCON |
Int |
Нет | 1024 | Максимальное число одновременных входящих HTTP-соединений |
ARCHIVER_INTERNALCMD_ALLOW |
Boolean |
Нет | false | Можно ли сервису отправлять внутрисистемные команды |
ARCHIVER_SENDERLIB_CONSIDER_ALL_COMMANDS_AS_INTERNAL |
Boolean |
Нет | false | Флаг, определяющий будут ли все обращения в другие сервисы являться внутренними (т.е. не требовать авторизацию). Детальное описание механизма: Внутренние команды. |
ARCHIVER_SENDERLIB_COMMANDS_CACHE_UPDATEPERIOD |
Duration String |
Нет | 10 minutes | Время кэширования данных по командам из CommandDiscovery |
ARCHIVER_SENDERLIB_SERVICES_CACHE_UPDATEPERIOD |
Duration String |
Нет | 30 seconds | Время кэширования данных по сервисам из ServiceDiscovery |
ARCHIVER_SENDERLIB_CONSUL_CONNECTION_RETRY_MAX |
Int |
Нет | 5 | Количество попыток переподключения к Consul |
ARCHIVER_SENDERLIB_CONSUL_CONNECTION_RETRY_DELAY |
Duration String |
Нет | 1 second | Задержка при попытках переподключения к Consul |
ARCHIVER_DB_HOST |
String |
Да | Хост БД | |
ARCHIVER_DB_PORT |
Int |
Да | Порт БД | |
ARCHIVER_DB_NAME |
String |
Да | Имя базы в БД | |
ARCHIVER_DB_URL |
JBDC URL |
Нет | JDBC-url для соединения с БД. По умолчанию собирается из других обязательных переменных. Можно указать только его, если не хочется отдельно указывать хост/порт/имя базы. | |
ARCHIVER_DB_USER |
String |
Да | Пользователь БД | |
ARCHIVER_DB_PASSWORD |
String |
Да | Пароль пользователя БД | |
ARCHIVER_DB_THREADS |
Int |
Нет | 10 | Количество потоков в пуле потоков для соединения с БД |
ARCHIVER_DB_QUEUE_SIZE |
Int |
Нет | 300 | Размер очереди для действий базы данных, которые не могут быть выполнены немедленно, когда все потоки заняты. За пределами этого значения новые действия немедленно завершаются неудачей |
ARCHIVER_DB_CONN_MAX |
Int |
Нет | 10 | Максимальное количество одновременных подключений к БД |
ARCHIVER_DB_CONN_TIMEOUT |
Duration String |
Нет | 20 second | Максимальное время ожидания ответа для соединения к БД. Если это время превышено, а соединение не становится доступным, будет брошено исключение SQLException. 1000 мс — минимальное значение. |
ARCHIVER_DB_ISOLATION |
String |
Нет | "READ_COMMITTED" | Уровень изоляции транзакций для новых подключений. Допустимые значения: NONE, READ_COMMITTED, READ_UNCOMMITTED, REPEATABLE_READ, SERIALIZABLE. |
ARCHIVER_DB_READONLY |
Boolean |
Нет | false | Read-only SQL транзакция может изменять только временные таблицы. Этот параметр управляет статусом «только для чтения» по умолчанию для каждой новой транзакции. |
ARCHIVER_DB_CONN_MIN |
Int |
Нет | = DB_THREADS | Минимальное количество одновременных подключений к БД |
ARCHIVER_DB_VALIDATION_TIMEOUT |
Duration String |
Нет | 1 seconds | Максимальное время, в течение которого соединение будет проверяться на работоспособность. 1000 мс — минимальное значение. |
ARCHIVER_DB_IDLE_TIMEOUT |
Duration String |
Нет | 10 minutes | Максимальное время, в течение которого соединению разрешено простаивать в пуле. Значение 0 означает, что простаивающие соединения никогда не удаляются из пула. |
ARCHIVER_DB_MAX_LIFETIME |
Duration String |
Нет | 30 minutes | Максимальное время жизни соединения в пуле. Когда простаивающее соединение достигает этого времени ожидания, даже если оно недавно использовалось, оно будет удалено из пула. Значение 0 указывает на отсутствие максимального срока службы. |
ARCHIVER_DB_INITIALIZATION_FAIL_FAST |
String |
Нет | false | Deprecated, начиная с версии Slick 3.3.0. Определяет, будет ли пул «быстро выходить из строя», если пул не может быть успешно заполнен начальными соединениями. Если соединения не могут быть созданы во время запуска пула, будет выдано исключение RuntimeException. Это свойство не имеет никакого эффекта, если minConnections равно 0. |
ARCHIVER_DB_LEAK_DETECTION_THRESHOLD |
Int |
Нет | 0 | Время, в течение которого соединение может находиться вне пула, прежде чем будет зарегистрировано сообщение, указывающее на возможную утечку соединения. Значение 0 означает, что обнаружение утечек отключено. Наименьшее приемлемое значение для включения обнаружения утечек составляет 10 с. |
ARCHIVER_DB_CONNECTION_TEST_QUERY |
String |
Нет | "SELECT 1" | Выражение, которое будет выполнено непосредственно перед получением соединения из пула для проверки того, что соединение с базой данных все еще активно. Оно зависит от базы данных и должно представлять собой запрос, требующий минимальной обработки базой данных (например, «VALUES 1»). Если этот параметр не установлен, вместо него используется метод JDBC4 Connection.isValid(). |
ARCHIVER_DB_AUTO_COMMIT |
Boolean |
Нет | true | Это свойство определяет то, как будут вести себя по умолчанию возвращаемые соединения относительно autocommit-а. |
ARCHIVER_DB_SCHEMA |
String |
Нет | "public" | Устанавливает schema по умолчанию |
ARCHIVER_DB_ISOLATE_INTERNAL_QUERIES |
Boolean |
Нет | false | Определяет то, изолируются ли с помощью транзакций внутренние запросы пула(например запрос connection alive test). Свойство применяется только если autoCommit выключен. |
ARCHIVER_DB_INITIALIZATION_FAIL_TIMEOUT |
Int |
Нет | 1 | Работает, начиная с версии Slick 3.3.0. Определяет, будет ли пул «быстро выходить из строя», если пул не может быть успешно заполнен начальными соединениями. Любое положительное число считается числом миллисекунд для попытки получить начальное соединение;поток приложения будет заблокирован в течение этого периода. Если соединение не может быть получено до истечения этого времени,будет брошено исключение. Данный таймаут применяется после периода connectionTimeout. Если значение равно нулю (0),HikariCP попытается получить и проверить подключение. Если соединение получено,но проверка не пройдена, будет брошено исключение, и пул не будет запущен. Однако,если соединение не может быть получено, пул запустится,но последующие попытки получить соединение могут потерпеть неудачу.Значение меньше нуля пройдет любую первоначальную попытку подключения, и пул немедленно запустится,пытаясь получить соединения в фоновом режиме.Следовательно, последующие попытки получить соединение могут потерпеть неудачу. |
ARCHIVER_DB_REGISTER_MBEANS |
Boolean |
Нет | false | Зарегистрированы ли JMX Management Beans («MBeans») |
ARCHIVER_AUTHZFORCE_ADDR |
String |
Нет | "http://localhost:8080/authzforce-ce" | Адрес AuthZforce server |
ARCHIVER_AUTHZFORCE_DOMAIN |
String |
Нет | "" | Доступный DomainID в AuthZforce server |
ARCHIVER_AUTHZFORCE_CONNECT_TIMEOUT |
Duration String |
Нет | 10 seconds | Timeout присоединения к AuthZforce server |
LOG_LEVEL |
String |
Нет | INFO | Общий уровень логирования в сервисе |
LOG_LEVEL_AKKA |
String |
Нет | INFO | Уровень логирования для akka |
LOG_LEVEL_LIQUIBASE |
String |
Нет | INFO | Уровень логирования для liquibase (миграции) |
LOG_LEVEL_APPLICATION |
String |
Нет | DEBUG | Уровень логирования для application |
LOG_LEVEL_SLICK_STATEMENT |
String |
Нет | DEBUG | Уровень логирования запросов, отправляемых slick в БД |
LOG_LEVEL_SLICK_BENCHMARK |
String |
Нет | OFF | Уровень логирование бенчмарков выполнения запросов slick |
LOG_LEVEL_KAFKA_PRODUCER |
String |
Нет | WARN | Уровень логирования конфига kafka-producer |
LOG_LEVEL_KAFKA_CONSUMER |
String |
Нет | WARN | Уровень логирования конфига kafka-consumer |
LOG_LEVEL_HTTP_SERVER |
String |
Нет | WARN | Уровень логирования HTTP-сервера |
LOG_LEVEL_AKKAHTTPSENDER |
String |
Нет | TRACE | Уровень логирования для отправки команд через HTTP. На уровне INFO логируется трассировка, если она включена |
LOG_LEVEL_KAFKASENDER |
String |
Нет | TRACE | Уровень логирования для отправки команд через Kafka. На уровне INFO логируется трассировка, если она включена |
LOG_LEVEL_COMMANDSTATUSCLI |
String |
Нет | TRACE | Уровень логирования для проверки состояний команд в сервисе статусов |
LOG_LEVEL_TEAM_ROUTES |
String |
Нет | TRACE | Уровень логирования для роутов /team |
ARCHIVER_FS_URI |
URL |
Нет | http://localhost:9000 | Адрес S3 файлового хранилища |
ARCHIVER_FS_ACCESS_KEY_ID |
String |
Нет | minioadmin | Идентификатор доступа к s3 |
ARCHIVER_FS_SECRET_ACCESS_KEY |
String |
Нет | minioadmin | Секретный ключ доступа к s3 |
ARCHIVER_FS_UPLOAD_PARALLELISM |
Int |
Нет | 4 | Параллелизм загрузки файлов в s3 |
ARCHIVER_FS_AUTH_MODE |
String |
Нет | static | Режим аутентификации: static - одна учетная запись на все запросы, mapping - учетная запись зависит от запроса |
ARCHIVER_FS_AUTH_CONFIG |
String |
Нет | "" | Настройки для аутентификации: если AuthMode = mapping, то необходим JSON с List[FSBucketConfig] соответствует полю authConfig FSConfigRep |
ARCHIVER_FS_CACHE_SIZE |
Int |
Нет | 1 | Максимальный размер кеша клиентов для хранилища файлов (количество активных соединений) |
ARCHIVER_FS_CACHE_TTL |
Duration String |
Нет | Время жизни клиента в кеше | |
ARCHIVER_FS_RETRY_ATTEMPTS |
Int |
Нет | 5 | Количество ретраев, которое будет произведено в случае Exception-а в операции FSClient-а и при вычитывании стрима в get операциях FSClient-а. |
ARCHIVER_FS_RETRY_DELAY |
Duration String |
Нет | 10 millis | Задержка между ретраями операций FSClient-а. |
ARCHIVER_FS_TEMP_BUCKET |
String |
Нет | "temp" | Название бакета в s3, в котором находятся временные файлы |
ARCHIVER_FS_ARCHIVE_BUCKET |
String |
Нет | "archive" | Название бакета в s3, в котором находятся архивы |
ARCHIVER_FS_ZIO_SHORT_MESSAGE_MODE |
Boolean |
Нет | false | Флаг включения режима сохранения ошибок работы с файловым хранилищем в сервисе журналирования nestor. При включении режима ошибки в логах будут отображаться в сокращенном формате: Short zio message mode. ExceptionType: ТИП ОШИБКИ, Exception id: 'СГЕНЕРИРОВАННЫЙ UUID' added to journal. Указанный id будет фиксироваться в event записи nestor'а в поле data.id |
ARCHIVER_FS_CHUNK_SIZE |
Int |
Нет | 8192 | Размер буферов для обработки стримов из s3. |
ARCHIVER_JOURNAL_MODE |
String |
Нет | WriteToJournal |
Режим журналирования Nestor. Допустимые значения: WriteToJournal (Отправка в сервис журналирования), WriteToTopic (Отправка события в очередь) |
ARCHIVER_JOURNAL_TOPIC |
String |
Да, если переменная ARCHIVER_JOURNAL_MODE = WriteToTopic |
"" | Название очереди журналирования. Для режима WriteToJournal значение игнорируется. |
Список команд сервиса Archiver
В описании команд используется путь/route для отправки команды в сам сервис, а не в ApiGateway. В качестве Input-а для команд, сервис всегда ожидает CommandRequest (как и любой другой сервис, принимающий команды), так что в описании команды указано лишь описание поля payload для CommandRequest.
В сервисе реализованно 4 команды:
| Название команды | EntityType | Actions |
|---|---|---|
| Список архивов | Archiver |
ViewArchiveRegistry |
| Архивация файлов из S3 | Archiver |
CreateArchive |
| Архивация файлов из модели данных | Archiver |
CreateArchive |
| Распаковка архива | Archiver |
UnpackArchive |
ListArchives
На входе
{
"query": "",
"context": {}
}
На выходе
{
"items": [
{
"archiveUrl": "archive/archiveName.zip",
"userId": "00000000-0000-0000-0000-000000000000",
"status": "finished",
"fileUrls": [
"/temp/21b130ad-008d-43ef-a681-04fcdfe91afc"
],
"entityObjectIdentities": null
},
{
"archiveUrl": "archive/closed.zip",
"userId": "00000000-0000-0000-0000-000000000000",
"status": "closed",
"fileUrls": [
"sed-nmd-rc-datamodel/NmdPublish/a077e8dd-eb0f-4e82-aea9-be5596f0fb55",
"sed-nmd-rc-datamodel/NmdPublish/c61f0c50-3b62-4f2c-bcfe-e15e38f5f317",
"sed-nmd-rc-datamodel/NmdPublish/1d1249a3-ebfc-4df8-bd31-e1264c18da22",
"sed-nmd-rc-datamodel/NmdPublish/276209fb-4d0b-4454-92fb-f19a4b8a5db8"
],
"entityObjectIdentities": [
{
"entityType": "NmdPublish",
"objectId": "deed5141-a45d-4931-866a-db3759124659"
},
{
"entityType": "NmdPublish",
"objectId": "b986085c-d80a-420f-b294-5a7ccff5ea49"
},
{
"entityType": "NmdPublish",
"objectId": "2688b889-b3ac-4d61-b7ca-ef10e5c03c7b"
},
{
"entityType": "NmdPublish",
"objectId": "414b92bd-b0a5-4a4e-a429-5a2c20062141"
}
]
},
{
"archiveUrl": "archive/empty.zip",
"userId": "00000000-0000-0000-0000-000000000000",
"status": "finished",
"fileUrls": [],
"entityObjectIdentities": null
}
],
"total": 3
}
Возвращает список всех архивов.
Результат выполнения команды не журналируется.
- Input: Search
- Output: Page[ArchiveDTO]
| Команда | Путь |
|---|---|
| archiver_http_listArchives | HTTP POST "/archiver_http_listArchives" |
ArchiveFromUrls
На входе
{
"filesUrls": [
"/temp/21b130ad-008d-43ef-a681-04fcdfe91afc",
"/temp/21b130ad-008d-43ef-a681-04fcdfe91afc"
],
"archiveName": "archiveName"
}
На выходе
{
"archiveUrl": "archive/archiveName.zip",
"status": "finished"
}
Архивация файлов из S3, переданных ссылками.
Результат выполнения команды не журналируется.
- Input: UrlsInputDTO
- Output: OutputDTO
| Команда | Путь |
|---|---|
| archiver_kafka_archiveFromUrls | Kafka Topic "archiver_commands" |
ArchiveFromDataModelSearch
На входе
{
"search": {
"query": "entityType",
"context": {
"entityType": "NmdPublish"
}
},
"archiveName": "archiveName",
"includedFiles": "all",
"additionalFilesFilter": [
"pdf"
]
}
На выходе
{
"archiveUrl": "archive/archiveName.zip",
"status": "finished"
}
Архивация файлов из S3, привязанных к сущностям датамодела, найденым по переданному search.
Результат выполнения команды не журналируется.
- Input: SearchInputDTO
- Output: OutputDTO
| Команда | Путь |
|---|---|
| archiver_kafka_archiveFromDataModelSearch | Kafka Topic "archiver_commands" |
Unarchive
На входе
"temp/archiveName.zip"
На выходе
[
{
"fileId": "98ac926c-9b9a-4464-997f-5307b8a48abf",
"name": "myFileName1.txt",
"size": 9181759,
"url": "temp/98ac926c-9b9a-4464-997f-5307b8a48abf",
"md5": "E06273F88B2A9AF84C2A826C3AA97DA9",
"contentType": "binary/octet-stream"
},
{
"fileId": "41df8b0a-f742-4fae-80bc-c1a25052d3b9",
"name": "myFileName2.txt",
"size": 9181751,
"url": "temp/41df8b0a-f742-4fae-80bc-c1a25052d3b9",
"md5": "69BCDFC2BBE42DFE34610A924403381E",
"contentType": "binary/octet-stream"
}
]
Разархивация архива из S3, возвращает список файлов, которые были в архиве. Извлекаемые файлы сохраняются в 'ARCHIVER_FS_TEMP_BUCKET', при загрузке сохраняется ownerUserId от исходного файла.
Результат выполнения команды не журналируется.
- Input: StoredFile
- Output: List[FileMetadata]
Объекты сервиса Archiver
ArchiveDTO
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| archiveUrl | String | да | url архива в S3 |
| userId | UUID | Нет | UUID пользователя - автора |
| status | String (finished, inProcess, closed, deleted) | да | Статус архива |
| fileUrls | String[] | да | Список url собранных файлов в S3 |
| entityObjectIdentities | EntityObjectIdentity[] | Нет | Список связанных объектов модели данных |
UrlsInputDTO
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| archiveUrl | String | да | url архива в S3 |
| fileUrls | String[] | да | Список url собранных файлов в S3 |
SearchInputDTO
| Поле | Тип | Обязательное | Значение по умолчанию | Описание |
|---|---|---|---|---|
| archiveUrl | String | да | - | url архива в S3 |
| search | Search | да | - | search объектов из модели данных |
| includedFiles | String (all, main, additional) | нет | "main" | Какого типа файлы включить в архив |
| additionalFilesFilter | String[] | нет | - | Из каких полей взять дополнительные файлы |
OutputDTO
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| archiveUrl | String | да | url архива в S3 |
| status | String (finished, inProcess) | да | Статус архива |
Attila-client: клиент для сервиса Attila
Предоставляемые методы: - TBD
Ключевые сущности: - TBD
Attila: сервис композитных правил
Данные сервиса хранятся в PostgreSQL. Команды могут приходить как по HTTP, так и по Kafka.
Сервис разбит на несколько модулей, в виде sbt проектов:
domain, в котором содержатся все доменные модели и их различные представления.infrastructure, в котором содержатся базовые компоненты для взаимодействия с инфраструктурой.store, содержит сервисы для сохранения и чтения их разных хранилищ доменных моделей.service, содержит сервисы бизнес логии, которые определяют правила взаимодействия компонентов между собой.route, содержит HTTP роуты.boot, содержит зависимости и описание для сборки и запуска сервиса.
В сервисе реализованны следующие команды:
- Получение списка команд
- Получение списка ресурсов
- Получение списка полей для ресурсов
- Добавление полей для ресурса
- Удаление полей из ресурса
- Получение списка действий для "низкоуровневых" правил
- Получение списка UI действий для "высокоуровневых" правил
- Добавление данных для авторизации команды
- Удаление данных для авторизации команды
- Обновление правило с новой версией
- Удаление версии правила по ID
- Получение версии правила по ID
- Получение списка правил с указанием добавленных версий
Локальный запуск сервиса Attila
При запуске сервиса ожидается, что уже развернута необходимая инфраструктура:
- PostgreSQL база по адресу
localhost:5432/attila_db - Kafka по адресу
localhost:9092 - Consul по адресу
localhost:8500 - Добавлены необходимые переменные окружения:
- ATTILA_DB_HOST
- ATTILA_DB_PORT
- ATTILA_DB_NAME
- ATTILA_DB_USER
- ATTILA_DB_PASSWORD
Запуск Attila из консоли с помощью SBT
ATTILA_DB_HOST=localhost ATTILA_DB_PORT=5432 ATTILA_DB_NAME=attila_db ATTILA_DB_USER=$ATTILA_DB_USER ATTILA_DB_PASSWORD=$ATTILA_DB_PASSWORD sbt boot/run
Список всех переменных окружения для сервиса Attila
| Переменная | Тип | Обязательная | Значение по умолчанию | Описание |
|---|---|---|---|---|
ATTILA_HTTP_HOST |
String |
Да | "0.0.0.0" | Хост для HttpListener |
ATTILA_HTTP_PORT |
Int |
Да | 8192 | Порт для HttpListener |
ATTILA_KAFKA_SERVERS |
String |
Да | "localhost:9092" | Адрес Kafka |
ATTILA_KAFKA_TOPIC |
String |
Нет | "attila_commands" | Название топика для входящих команд |
ATTILA_KAFKA_COMMANDEVENT_TOPIC |
String |
Нет | "commandevents" | Название топика для входящих/исходящих событий |
ATTILA_KAFKA_CONSUMER_GROUP |
String |
Да | Название группы для чтения топика событий | |
ATTILA_KAFKA_TOPIC_PARTITIONS |
Int |
Да | 10 | Количество партиций в топике команд. |
ATTILA_KAFKA_CONSUMER_RESTART_MIN_BACKOFF |
Duration String |
Нет | "1 second" | Минимальная задержка перед перезапуском. |
ATTILA_KAFKA_CONSUMER_RESTART_MAX_BACKOFF |
Duration String |
Нет | "30 seconds" | Максимально возможная задержка перед перезапуском. |
ATTILA_KAFKA_CONSUMER_RESTART_RANDOM_FACTOR |
Double |
Нет | 0.2 | Коэффициент величины дополнительной случайной задержки (jitter) относительно основной задержки (При значении 0.2 задержка может быть до 20% больше, чем при 0). Если после умножения задержки на ATTILA_KAFKA_CONSUMER_RESTART_RANDOM_FACTOR получится меньше 1 миллисекунды, то jitter будет приравнен к нулю. |
ATTILA_KAFKA_CONSUMER_RESTART_MAX_RESTARTS |
Int |
Нет | 5 | Максимальное количество перезапусков в заданный период времени. После превышения этого числа сервис будет объявлен больным. Все рестарты для каждого отдельного сообщения увеличивают и общий счетчик рестартов консьюмера, поэтому при использовании ATTILA_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS нужно указывать ATTILA_KAFKA_CONSUMER_RESTART_MAX_RESTARTS > ATTILA_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS или не указывать ATTILA_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS совсем |
ATTILA_KAFKA_CONSUMER_RESTART_MAX_RESTARTS_WITHIN |
String |
Нет | "5 minutes" | Период времени для ограничения перезапусков. |
ATTILA_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS |
Int |
Нет | 2 | Максимальное количество раз, которое консьюмер перезапустится с неизменной очередью сообщений (в пределах DATA_MODEL_KAFKA_CONSUMER_RESTART_MAX_RESTARTS_WITHIN), прежде чем проигнорировать сообщение, на котором происходит ошибка (Указано количество рестартов, а не прочтений. Если ATTILA_KAFKA_CONSUMER_RESTART_MAX_RESTARTS = 2, то ошибочное сообщение будет обработано 3 раза, после чего произойдет 3ий рестарт и оно будет проигнорировано). Если указать 0, то перезапуск произойдет, но сообщение будет обработано только в первый раз, когда произошла ошибка. Если указать значение меньше 0, то перезапуски все равно будут происходить, но игнорирование сообщений, вызывающих ошибку, будет отключено. |
ATTILA_KAFKA_CONSUMER_PER_MESSAGE_RESTART_CACHE_SIZE |
Int |
Нет | 100 | Для каждого сообщения счетчик перепрочтений хранится в кэше. Максимальное количество значений в этом кэше. |
ATTILA_KAFKA_CONSUMER_PER_MESSAGE_RESTART_CACHE_TTL |
Duration String |
Нет | 5 minutes | Для каждого сообщения счетчик перепрочтений хранится в кэше. Максимальное время жизни элемента в этом кэше. В случае отсутствия значения время жизни элемента не будет ограничено. |
ATTILA_KAFKA_CONSUMER_POLL_TIMEOUT |
Duration String |
Нет | 10 milliseconds | timeout запроса poll для kafka consumer |
ATTILA_KAFKA_CONSUMER_POLL_INTERVAL |
Duration String |
Нет | 100 milliseconds | интервал между запросами poll для kafka consumer |
ATTILA_KAFKA_CONSUMER_PROPS |
String |
Нет | "max.poll.records=500;max.partition.fetch.bytes=524288" | дополнительные параметры для kafka consumer в формате "key1=value1;key2=value2" |
ATTILA_KAFKA_AUTH_USER |
String |
Нет | "" | Название учетной записи Kafka. Если название не указано, то настройки авторизации не будут применены. |
ATTILA_KAFKA_AUTH_PASSWORD |
String |
Нет | "" | Пароль учетной записи Kafka. |
ATTILA_KAFKA_AUTH_PRINCIPAL |
String |
Нет | "" | Principal учетной записи Kafka в Kerberos(в случае соединения с kafka через Kerberos). |
ATTILA_KAFKA_AUTH_KEYTAB_PATH |
String |
Нет | "" | Путь до keytab-файла (в случае соединения с kafka через Kerberos). |
ATTILA_KAFKA_AUTH_TRUSTSTORE_LOCATION |
String |
Нет | "" | Путь до хранилища сертификатов (Java key store). Если путь не указан, то сертификат применяться не будет. |
ATTILA_KAFKA_AUTH_TRUSTSTORE_PASSWORD |
String |
Нет | "" | Пароль к хранилищу сертификатов. |
ATTILA_KAFKA_AUTH_MODE |
String |
Нет | Режим аутентификации: static - одна учетная запись на все запросы, mapping - учетная запись зависит от запроса | |
ATTILA_KAFKA_AUTH_CONFIG |
String |
Нет | Настройки для аутентификации: если AuthMode = mapping, то необходим JSON с List[KafkaAuthConfig]. Переменная соответствует полю authConfig из KafkaAuthSettings. | |
ATTILA_KAFKA_AUTH_CACHE_SIZE |
Int |
Нет | Максимальный размер кеша для Kafka producer (количество активных соединений). | |
ATTILA_KAFKA_CONNECTION_CHECK_TEST_MESSAGES_INTERVAL |
Duration String |
Нет | 4 minutes | Применяется только для producer-ов со способом аутентификации kerberos. Интервал отправки тестовых сообщений кафки в топик connectionCheck.testMessagesTopicName. Тестовые сообщения (null, service producer test) отправляются регулярно с этим интервалом. |
ATTILA_KAFKA_CONNECTION_CHECK_INTERVAL |
Duration String |
Нет | 60 seconds | Применяется только для producer-ов со способом аутентификации kerberos. Интервал проверки того, сколько тестовых сообщений было отправлено за данный период. Если количество сообщений за этот период равно количеству сообщений за прошлый период, то начинается отсчет периода без сообщений. |
ATTILA_KAFKA_CONNECTION_CHECK_FAILED_AFTER_INTERVAL |
Duration String |
Нет | 5 minutes | Применяется только для producer-ов со способом аутентификации kerberos. Максимальная продолжительность периода без успешно отправленных тестовых сообщений. По ее достижении сервис будет объявлен больным. |
ATTILA_KAFKA_AUTH_CACHE_TTL |
Duration String |
Нет | Время жизни Kafka producer в кеше. | |
ATTILA_CONSUL_ADDR |
String |
Да | "http://localhost:8500" | Адрес Сonsul. |
ATTILA_CONSUL_AUTH_USER |
String |
Нет | "" | Название учетной записи Сonsul. Если название не указано, то настройки авторизации не будут применены. |
ATTILA_CONSUL_AUTH_PASSWORD |
String |
Нет | "" | Пароль учетной записи Сonsul. |
ATTILA_TRACE_DURATION |
Boolean |
Нет | false | Нужно ли логировать длительность выполнения команд |
ATTILA_DISCOVERABLE_ID |
String |
Нет | "another_attila_instance" | ID данного сервиса |
ATTILA_DISCOVERABLE_NAME |
String |
Нет | "attila" | Название группы сервисов к которой принадлежит данный |
ATTILA_DISCOVERABLE_HOST |
String |
Нет | "localhost" | Адрес текущего инстанса сервиса, который будет виден через ServiceDiscovery |
ATTILA_DISCOVERABLE_PORT |
String |
Нет | {ATTILA_HTTP_PORT} | Адрес текущего инстанса сервиса, который будет виден через ServiceDiscovery |
ATTILA_DISCOVERABLE_LIVETIME |
Duration String |
Нет | "2 minutes" | Время с последнего HeathCheck, в течении которого сервис считается "живым" |
ATTILA_DISCOVERABLE_HEALTHPASS |
Duration String |
Нет | "1 minute" | Периодичность отправки HeathCheck |
ATTILA_INTERNALCMD_ALLOW |
Boolean |
Нет | true | Возможно ли сервису отправлять "внутренние" команды |
ATTILA_SENDERLIB_CONSIDER_ALL_COMMANDS_AS_INTERNAL |
Boolean |
Нет | false | Флаг, определяющий будут ли все обращения в другие сервисы являться внутренними (т.е. не требовать авторизацию). Детальное описание механизма: Внутренние команды. |
ATTILA_SENDERLIB_COMMANDS_CACHE_UPDATEPERIOD |
Duration String |
Нет | "10 minutes" | Время на которое будут кешироваться данные о командах |
ATTILA_SENDERLIB_SERVICES_CACHE_UPDATEPERIOD |
Duration String |
Нет | "30 seconds" | Время на которое будут кешироваться данные о сервисах |
ATTILA_DB_HOST |
String |
Да | Хост сервера базы данных | |
ATTILA_DB_PORT |
String |
Да | Порт сервера базы данных | |
ATTILA_DB_NAME |
String |
Да | Название базы | |
ATTILA_DB_USER |
String |
Да | Пользователь для базы данных | |
ATTILA_DB_PASSWORD |
String |
Да | Пароль для пользователь для базы данных | |
ATTILA_DB_THREADS |
Int |
Нет | 10 | Количество потоков в пуле потоков для соединения с БД |
ATTILA_DB_QUEUE_SIZE |
Int |
Нет | 300 | Размер очереди для действий базы данных, которые не могут быть выполнены немедленно, когда все потоки заняты. За пределами этого значения новые действия немедленно завершаются неудачей |
ATTILA_DB_CONN_MAX |
Int |
Нет | 10 | Максимальное количество одновременных подключений к БД |
ATTILA_DB_CONN_TIMEOUT |
Duration String |
Нет | 20 second | Максимальное время ожидания ответа для соединения к БД. Если это время превышено, а соединение не становится доступным, будет брошено исключение SQLException. 1000 мс — минимальное значение. |
ATTILA_DB_ISOLATION |
String |
Нет | "READ_COMMITTED" | Уровень изоляции транзакций для новых подключений. Допустимые значения: NONE, READ_COMMITTED, READ_UNCOMMITTED, REPEATABLE_READ, SERIALIZABLE. |
ATTILA_DB_READONLY |
Boolean |
Нет | false | Read-only SQL транзакция может изменять только временные таблицы. Этот параметр управляет статусом «только для чтения» по умолчанию для каждой новой транзакции. |
ATTILA_DB_CONN_MIN |
Int |
Нет | = DB_THREADS | Минимальное количество одновременных подключений к БД |
ATTILA_DB_VALIDATION_TIMEOUT |
Duration String |
Нет | 1 seconds | Максимальное время, в течение которого соединение будет проверяться на работоспособность. 1000 мс — минимальное значение. |
ATTILA_DB_IDLE_TIMEOUT |
Duration String |
Нет | 10 minutes | Максимальное время, в течение которого соединению разрешено простаивать в пуле. Значение 0 означает, что простаивающие соединения никогда не удаляются из пула. |
ATTILA_DB_MAX_LIFETIME |
Duration String |
Нет | 30 minutes | Максимальное время жизни соединения в пуле. Когда простаивающее соединение достигает этого времени ожидания, даже если оно недавно использовалось, оно будет удалено из пула. Значение 0 указывает на отсутствие максимального срока службы. |
ATTILA_DB_INITIALIZATION_FAIL_FAST |
String |
Нет | false | Deprecated, начиная с версии Slick 3.3.0. Определяет, будет ли пул «быстро выходить из строя», если пул не может быть успешно заполнен начальными соединениями. Если соединения не могут быть созданы во время запуска пула, будет выдано исключение RuntimeException. Это свойство не имеет никакого эффекта, если minConnections равно 0. |
ATTILA_DB_LEAK_DETECTION_THRESHOLD |
Int |
Нет | 0 | Время, в течение которого соединение может находиться вне пула, прежде чем будет зарегистрировано сообщение, указывающее на возможную утечку соединения. Значение 0 означает, что обнаружение утечек отключено. Наименьшее приемлемое значение для включения обнаружения утечек составляет 10 с. |
ATTILA_DB_CONNECTION_TEST_QUERY |
String |
Нет | "SELECT 1" | Выражение, которое будет выполнено непосредственно перед получением соединения из пула для проверки того, что соединение с базой данных все еще активно. Оно зависит от базы данных и должно представлять собой запрос, требующий минимальной обработки базой данных (например, «VALUES 1»). Если этот параметр не установлен, вместо него используется метод JDBC4 Connection.isValid(). |
ATTILA_DB_AUTO_COMMIT |
Boolean |
Нет | true | Это свойство определяет то, как будут вести себя по умолчанию возвращаемые соединения относительно autocommit-а. |
ATTILA_DB_SCHEMA |
String |
Нет | "public" | Устанавливает schema по умолчанию |
ATTILA_DB_ISOLATE_INTERNAL_QUERIES |
Boolean |
Нет | false | Определяет то, изолируются ли с помощью транзакций внутренние запросы пула (например запрос connection alive test). Свойство применяется только если autoCommit выключен. |
ATTILA_DB_INITIALIZATION_FAIL_TIMEOUT |
Int |
Нет | 1 | Работает, начиная с версии Slick 3.3.0. Определяет, будет ли пул «быстро выходить из строя», если пул не может быть успешно заполнен начальными соединениями. Любое положительное число считается числом миллисекунд для попытки получить начальное соединение;поток приложения будет заблокирован в течение этого периода. Если соединение не может быть получено до истечения этого времени, будет брошено исключение. Данный таймаут применяется после периода connectionTimeout. Если значение равно нулю (0),HikariCP попытается получить и проверить подключение. Если соединение получено, но проверка не пройдена, будет брошено исключение, и пул не будет запущен. Однако, если соединение не может быть получено, пул запустится, но последующие попытки получить соединение могут потерпеть неудачу. Значение меньше нуля пройдет любую первоначальную попытку подключения, и пул немедленно запустится, пытаясь получить соединения в фоновом режиме. Следовательно, последующие попытки получить соединение могут потерпеть неудачу. |
ATTILA_DB_REGISTER_MBEANS |
Boolean |
Нет | false | Зарегистрированы ли JMX Management Beans («MBeans») |
LOG_LEVEL_HLRULE_CONVERTER |
String |
Нет | "INFO" | Уровень логов для процесса конвертации высокоуровневых правил |
ATTILA_READABLE_NAME |
String |
Нет | "Сервис композитных правил" | Читаемое название этого сервиса |
ATTILA_DESCRIPTION |
String |
Нет | "Сервис для работы с композитными правилами ограничения доступа" | Читаемое описание этого сервиса |
ATTILA_RULE_UPDATE_TIMEOUT |
Duration String |
Нет | "10 minutes" | Таймаут на обновление HighLevelRule в сервисе Оberto |
ATTILA_DEFAULT_RESOURCES |
String |
Нет | "User{id:Идентификатор пользователя;email:Email пользователя;groupId:Идентификаторы групп пользователя}" | Описание ресурсов по умолчанию. Разделитель между ресурсами и полями в них ";". Символы для названий ресурсов и полей "a-zA-Z_\-0-9". Для описания разрешено все, кроме ";" и "}". |
ATTILA_SENDERLIB_COMMANDS_HTTP_RETRY_ATTEMPTS |
Int |
Нет | 5 | Поле attempts из RetrySettings |
ATTILA_SENDERLIB_COMMANDS_HTTP_RETRY_DELAY |
Duration String |
Нет | "5 seconds" | Поле delay из RetrySettings |
ATTILA_SENDERLIB_COMMANDS_HTTP_RETRY_KIND |
String |
Нет | "OnSomeExceptions(ConnectException)" | CommandResultRetryConditionKind |
ATTILA_SENDERLIB_CONSUL_CONNECTION_RETRY_MAX |
Int |
Нет | 5 | Количество попыток переподключения к Consul |
ATTILA_SENDERLIB_CONSUL_CONNECTION_RETRY_DELAY |
Duration String |
Нет | "1 second" | Задержка при попытках переподключения к Consul |
ATTILA_JOURNAL_MODE |
String |
Нет | WriteToJournal |
Режим журналирования Nestor. Допустимые значения: WriteToJournal (Отправка в сервис журналирования), WriteToTopic (Отправка события в очередь) |
ATTILA_JOURNAL_TOPIC |
String |
Да, если переменная ATTILA_JOURNAL_MODE = WriteToTopic |
"" | Название очереди журналирования. Для режима WriteToJournal значение игнорируется. |
Список команд сервиса Attila
В описании команд используется путь/route для отправки команды в сам сервис, а не в ApiGateway. В качестве Input-а для команд, сервис всегда ожидает CommandRequest (как и любой другой сервис, принимающий команды), так что в описании команды указано лишь описание поля payload для CommandRequest.
Информация по добавлению команд можно прочитать в описании шаблона
Список реализованных в сервисе команд, моделей EntityType и действий Actions, которые можно использовать при настройке авторизации.
| Название команды | EntityType | Actions |
|---|---|---|
| attila_GetResourceTypeFields | - | - |
| attila_AddResourceTypeFields | - | - |
| attila_RemoveResourceTypeFields | - | - |
| attila_AddAuthorizationInfo | - | - |
| attila_DeleteAuthorizationInfo | - | - |
| attila_ListCommandAuthorizationInfo | AuthorizationInfo | AuthorizationInfo_ViewCommands |
| attila_ListResourceTypeAuthorizationInfo | AuthorizationInfo | AuthorizationInfo_ViewResources |
| attila_ListRuleActionAuthorizationInfo | AuthorizationInfo | AuthorizationInfo_ViewRuleActions |
| attila_ListUIActionAuthorizationInfo | AuthorizationInfo | AuthorizationInfo_ViewUIActions |
| attila_UpdateHighLevelRule | HighLevelRule | HighLevelRule_Update |
| attila_DeleteHighLevelRule | HighLevelRule | HighLevelRule_Delete |
| attila_GetHighLevelRule | HighLevelRule | HighLevelRule_View |
| attila_ListHighLevelRules | HighLevelRule | HighLevelRule_ViewList |
ListCommands (attila)
Payload для команды
{
"query": "resource",
"context": {
"resource": "like %A"
},
"sorting": {
"fieldName": "ruleAction",
"order": "desc"
},
"paging": {
"page": 1,
"count": 3
}
}
Результат выполнения команды
{
"items": [
"commandName_EoverA",
"commandName_DoverA",
"commandName_CoverA"
],
"total": 5
}
Возвращает список названий команд, которые удовлетворяют заданным фильтрам.
Имя команды для вызова: attila_ListCommandAuthorizationInfo.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: Search
- На выходе: Page[CommandName]
По умолчанию сортировка производится по полю commandName.
Запрос принимает параметры сортировки, фильтров и пейджинга в параметре Search.
Применяется к полям модели AuthorizationInfo.
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров |
|---|---|
| id | InSetQuery, LikeQuery |
| commandname | InSetQuery, LikeQuery |
| resource | InSetQuery, LikeQuery |
| ruleaction | InSetQuery, LikeQuery |
| uiaction | InSetQuery, LikeQuery |
Доступные поля для сортировки:
| Поле |
|---|
| resource |
| ruleaction |
| uiaction |
| commandName |
ListResources (attila)
Payload для команды
{
"query": "resource",
"context": {
"resource": "like %A"
},
"sorting": {
"fieldName": "ruleAction",
"order": "desc"
},
"paging": {
"page": 1,
"count": 3
}
}
Результат выполнения команды
{
"items": [
"resource_BA",
"resource_A"
],
"total": 2
}
Возвращает список названий ресурсов, которые удовлетворяют заданным фильтрам.
Имя команды для вызова: attila_ListResourceTypeAuthorizationInfo.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: Search
- На выходе: Page[ResourceType]
По умолчанию сортировка производится по полю commandName.
Запрос принимает параметры сортировки, фильтров и пейджинга в параметре Search.
Применяется к полям модели AuthorizationInfo.
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров |
|---|---|
| id | InSetQuery, LikeQuery |
| commandname | InSetQuery, LikeQuery |
| resource | InSetQuery, LikeQuery |
| ruleaction | InSetQuery, LikeQuery |
| uiaction | InSetQuery, LikeQuery |
Доступные поля для сортировки:
| Поле |
|---|
| resource |
| ruleaction |
| uiaction |
| commandName |
ListRuleActions (attila)
Payload для команды
{
"query": "resource",
"context": {
"resource": "like %A"
},
"sorting": {
"fieldName": "ruleAction",
"order": "desc"
},
"paging": {
"page": 1,
"count": 3
}
}
Результат выполнения команды
{
"items": [
"ruleAction_EoverA",
"ruleAction_DoverA",
"ruleAction_CoverA"
],
"total": 5
}
Возвращает список действий для низкоуровневых правил, которые удовлетворяют заданным фильтрам.
Имя команды для вызова: attila_ListRuleActionAuthorizationInfo.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: Search
- На выходе: Page[RuleAction]
По умолчанию сортировка производится по полю commandName.
Запрос принимает параметры сортировки, фильтров и пейджинга в параметре Search.
Применяется к полям модели AuthorizationInfo.
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров |
|---|---|
| id | InSetQuery, LikeQuery |
| commandname | InSetQuery, LikeQuery |
| resource | InSetQuery, LikeQuery |
| ruleaction | InSetQuery, LikeQuery |
| uiaction | InSetQuery, LikeQuery |
Доступные поля для сортировки:
| Поле |
|---|
| resource |
| ruleaction |
| uiaction |
| commandName |
ListUIActions (attila)
Payload для команды
{
"query": "resource",
"context": {
"resource": "like %A"
},
"sorting": {
"fieldName": "ruleAction",
"order": "desc"
},
"paging": {
"page": 1,
"count": 3
}
}
Результат выполнения команды
{
"items": [
"uiAction_A"
],
"total": 1
}
Возвращает список UI действий, которые удовлетворяют заданным фильтрам.
Имя команды для вызова: attila_ListUIActionAuthorizationInfo.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
По умолчанию сортировка производится по полю commandName.
Запрос принимает параметры сортировки, фильтров и пейджинга в параметре Search.
Применяется к полям модели AuthorizationInfo.
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров |
|---|---|
| id | InSetQuery, LikeQuery |
| commandname | InSetQuery, LikeQuery |
| resource | InSetQuery, LikeQuery |
| ruleaction | InSetQuery, LikeQuery |
| uiaction | InSetQuery, LikeQuery |
Доступные поля для сортировки:
| Поле |
|---|
| resource |
| ruleaction |
| uiaction |
| commandName |
AddAuthorizationInfo (attila)
Payload для команды
[
{
"commandName": "Command_Executed_When_Viewing_Register",
"dependencies": [
[
"resource_A",
"view_register_of_a",
[
"SectionForA_View_Register"
]
],
[
"resource_A",
"other_action_on_a",
[]
]
]
},
{
"commandName": "Other_Command",
"dependencies": [
[
"AttractiveResourceName",
"Some_Action_On_AttractiveResource",
[]
]
]
},
{
"commandName": "Command_With_Resource_A",
"dependencies": [
[
"resource_A",
"ruleAction_BoverA",
[
"uiAction_A"
]
]
]
}
]
Результат выполнения команды
{
"Other_Command": true,
"Command_Executed_When_Viewing_Register": true,
"Command_With_Resource_A": true
}
Возвращает список команд с результатом добавления соответствующей информации для авторизации.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway), не требует аутентификации.
- Payload: [List[CommandAuthorizationInfo]
- Result: Map[CommandName, Boolean]
| Команда | Путь |
|---|---|
| attila_AddAuthorizationInfo | kafka topic "attila_commands" |
DeleteAuthorizationInfo (attila)
Payload для команды
[
"Other_Command"
]
Результат выполнения команды
1
Возвращает количество удаленных записей с информацией для авторизации. Одна запись это картеж из (CommandName, ResourceName, RuleAction, UiAction), т.е. количество записей не всегда равно количеству добавленных команд.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway), не требует аутентификации.
- Payload: List[CommandName]
- Result: Int
| Команда | Путь |
|---|---|
| attila_DeleteAuthorizationInfo | kafka topic "attila_commands" |
GetHighLevelRule (attila)
Payload для команды
"Rule_AccessTo_ResourceA"
Результат выполнения команды
{
"id": "Rule_AccessTo_ResourceA",
"name": "Rule_AccessTo_ResourceA",
"description": "Some very high rule",
"action": "SectionForA_View_Register",
"condition": "User.groupId == 'users' && A.authorId == User.id",
"priority": 100,
"effect": true
}
Возвращает по указаному идентификатору высокоуровневое правило, если оно существует.
Иначе возвращает статус 404 Not Found.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: HighLevelRuleId
- Result: HighLevelRule
| Команда | Путь |
|---|---|
| attila_GetHighLevelRule | HTTP POST "/v1/rules/get" |
ListHighLevelRules (attila)
Payload для команды
{
"query": "resource",
"context": {
"resource": "like %A"
},
"sorting": {
"fieldName": "priority",
"order": "asc"
},
"paging": {
"page": 12,
"count": 1
}
}
Результат выполнения команды
[
{
"id": "Rule_AccessTo_ResourceA",
"name": "Rule_AccessTo_ResourceA",
"description": "Some very high rule",
"action": "SectionForA_View_Register",
"condition": "User.groupId == 'users' && A.authorId == User.id",
"priority": 100,
"effect": true
},
{
"id": "Rule_View_List_Of_Data",
"name": "Rule_View_List_Of_Data",
"description": "Another rule",
"action": "A_ViewList",
"condition": "User.groupId == 'users'",
"priority": 20,
"effect": true
},
{
"id": "Rule_Action_Over_A",
"name": "Rule_Action_Over_A",
"description": "Just a high rule",
"action": "VerySmartAction",
"condition": "User.groupId == 'users' && A.authorId == User.id",
"priority": 30,
"effect": true
}
]
Возвращает список высокоуровневых правил с набором версий, версии которых удовлетворяют заданным фильтрам (paging
игнорируется, т.к. возвращается весь список).
Имя команды для вызова: attila_ListHighLevelRules.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: Search
- На выходе: List[HighLevelRule]
По умолчанию сортировка производится по полю priority.
Запрос принимает параметры сортировки, фильтров в параметре Search.
Применяется к полям модели HighLevelRules.
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров |
|---|---|
| id | InSetQuery, LikeQuery |
| description | InSetQuery, LikeQuery |
| priority | InSetQuery, RangeQuery |
| modified | InSetQuery, RangeQuery |
| effect | InSetQuery |
| action | InSetQuery, LikeQuery |
Доступные поля для сортировки:
| Поле |
|---|
| id |
| name |
| description |
| effect |
| action |
| modified |
| priority |
UpdateHighLevelRule (attila)
Payload для команды
{
"id": "Rule_AccessTo_ResourceA",
"name": "Rule_AccessTo_ResourceA",
"previousId": "Rule_AccessTo_ResourceA",
"description": "Some very high rule",
"action": "SectionForA_View_Register",
"condition": "User.groupId == 'users' && A.authorId == User.id",
"priority": 100,
"effect": true
}
Результат выполнения команды
true
Возвращает индикатор успеха добавления новой версии правила.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
- Payload: HighLevelRuleUpdateDTO
- Result: Boolean
| Команда | Путь |
|---|---|
| attila_UpdateHighLevelRule | kafka topic "attila_commands" |
DeleteHighLevelRule (attila)
Payload для команды
"Rule_AccessTo_ResourceA"
Результат выполнения команды
true
Возвращает индикатор успеха удаления указанной версии правила.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
- Payload: HighLevelRuleId
- Result: Boolean
| Команда | Путь |
|---|---|
| attila_DeleteHighLevelRule | kafka topic "attila_commands" |
GetResourceTypeFields (attila)
Payload для команды
{
"query": "resourceType",
"context": {
"resource": "like %A"
},
"sorting": {
"fieldName": "fieldName",
"order": "asc"
},
"paging": {
"page": 1,
"count": 3
}
}
Результат выполнения команды
{
"Resource_A": {
"field_1": "title_1",
"field_2": "title_2"
},
"Resource_ABA": {
"field_1": "title_123",
"field_2": "title_2"
}
}
Возвращает список полей, которые удовлетворяют заданным фильтрам.
Имя команды для вызова: attila_GetResourceTypeFields.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: Search
- На выходе: Map[ResourceType, Map[FieldName, Title]]
По умолчанию сортировка производится по полю resourceType.
Запрос принимает параметры сортировки, фильтров в параметре Search.
Применяется к полям модели ResourceTypeFields.
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров |
|---|---|
| resourcetype | InSetQuery, LikeQuery |
| fieldname | InSetQuery, LikeQuery |
| title | InSetQuery, LikeQuery |
Доступные поля для сортировки:
| Поле |
|---|
| fieldname |
| title |
| resourceType |
При сортировке не по полю "resourceType", resourceType будут сортироваться по мере появления (т.к. на беке список
плоский, без вложенностей).
Например, при сортировке по "fieldName":
ABC(f1,t1), CBA(f23,t2), ABC(f30,t12), ZS(f2,t3), CBA(f0, t43), ABC(f3,t1) =>
CBA(f0, t43), ABC(f1,t1), ZS(f2,t3), ABC(f3,t1), CBA(f23,t2), ABC(f30,t12) =>
CBA((f0, t43), (f23,t2)), ABC((f1,t1), (f3,t1), (f30,t12)), ZS(f2,t3)
AddResourceTypeFields (attila)
Payload для команды
"Rule_AccessTo_ResourceA"
Результат выполнения команды
true
Добавление набора полей для определенного типа ресурсов.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway), не требует аутентификации.
- Payload: Map[ResourceType, Map[FieldName, Title]]
- Result: Map[ResourceType, Map[FieldName, Boolean]]
| Команда | Путь |
|---|---|
| attila_AddResourceTypeFields | kafka topic "attila_commands" |
RemoveResourceTypeFields (attila)
Payload для команды
"Rule_AccessTo_ResourceA"
Результат выполнения команды
true
Удаляет указанные поля из определенного типа ресурсов.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway), не требует аутентификации.
| Команда | Путь |
|---|---|
| attila_RemoveResourceTypeFields | kafka topic "attila_commands" |
Модели сервиса Attila
CommandName
Наименование команды. Имеет тип String.
ResourceType
Наименование типа ресурса. Имеет тип String.
RuleAction
Наименование действия, которое используется в низкоуровневых правилах. Имеет тип String.
UIAction
Наименование UI действия, которое используется в высокоуровневых правилах. Имеет тип String.
FieldName
Наименование поля. Имеет тип String.
Title
Наименование чего-либо для отображения в интерфейсе. Имеет тип String.
CommandAuthorizationInfo
Информация для авторизации определенной команде.
| Поле | Описание |
|---|---|
| commandName | Наименование команды. Имеет тип CommandName |
| dependencies | Список констант, которые используются для авторизации команды. Константы образуют кортеж, обозначающее одно действие, которое необходимо авторизовать, где: ResourceType - ресурс, к которому осуществляется доступ, RuleAction - название действия для авторизации, UIAction - названия UI действий, которыми выражается RuleAction в терминах пользовательского интерфейса. Имеет тип List[(ResourceType, RuleAction, List[UIAction])] |
HighLevelRuleId
Идентификатор высокоуровневого правила. Имеет тип String.
HighLevelRule
Описание версии высокоуровневого правила
| Поле | Описание | Тип данных |
|---|---|---|
| id | Идентификатор правила. | HighLevelRuleId |
| name | Название правила для отображения в интерфейсе. | HighLevelRuleVersion |
| description | Описание правила. | String |
| action | UI действие, для которого необходимо применять данное правило. | UIAction |
| condition | Условие применения правила. Поле опционально. | Option[Condition] |
| priority | Приоритет правила : чем больше значение, тем "дальше" в очереди на применение будет распологаться правило | Int |
| effect | Является ли правило "разрешающим". | Boolean |
HighLevelRuleUpdateDTO
Описание версии высокоуровневого правила
| Поле | Описание | Тип данных |
|---|---|---|
| id | Идентификатор правила. | HighLevelRuleId |
| previousId | Используемый раньше идентификатор правила. Для новых правил, может быть пустым или равным текущему ID. | HighLevelRuleId |
| name | Название правила для отображения в интерфейсе. | HighLevelRuleVersion |
| description | Описание правила. | String |
| action | UI действие, для которого необходимо применять данное правило. | UIAction |
| condition | Условие применения правила. Поле опционально. | Option[Condition] |
| priority | Приоритет правила : чем больше значение, тем "дальше" в очереди на применение будет распологаться правило | Int |
| effect | Является ли правило "разрешающим". | Boolean |
AuthorizationInfo
Информация для авторизации.
| Поле | Описание | Тип данных |
|---|---|---|
| id | Идентификатор. | UUID |
| commandName | Наименование команды. | CommandName |
| resource | Наименование типа ресурса. | ResourceType |
| ruleAction | Наименование действия. | RuleAction |
| uiAction | Наименование UI действия. | UIAction |
ResourceTypeFields
Набор полей для определенного типа ресурсов.
| Поле | Описание | Тип данных |
|---|---|---|
| resourceType | Наименование типа ресурса. | ResourceType |
| fieldName | Наименование поля. | FieldName |
| title | Наименование. | Title |
Attribute-provider: провайдер атрибутов для сервиса Oberto
Является расширением для Authzforce server (Community edition). В терминах XACML является PIP.
Репозиторий Authzforce server: https://github.com/authzforce/server
Wiki Authzforce server: https://github.com/authzforce/core/wiki/Attribute-Providers
Спецификация XACML 3.0: http://docs.oasis-open.org/xacml/3.0/errata01/os/xacml-3.0-core-spec-errata01-os-complete.html
Расширение представляет собой jar файл с фабрикой для класса реализующего интерфейс CloseableNamedAttributeProvider (
предоставляется authzforce-ce-core-pdp-api):
AttributeValueProviderDescriptorописание провайдера вXMLAttributeValueProviderFactoryфабрика (создается при стартеAuthzforce server)AttributeValueProviderкласс реализующийCloseableNamedAttributeProvider
Предоставляемые атрибуты
Атрибуты предоставляются для объектов сервиса DataModel,
где AttributeId = <Название типа ресурса>.<Путь к полю Json-объекта в поле "data">.
Например, запрашиваеммый атрибут MyModel.firstField будет
получен по пути MyModel.data.firstField. Значения всех атрибутов имеют тип String или List[String], в зависимости
от структуры.
Атрибуты связанных объектов
Атрибуты связанных объектов указываются с использованием relation-поля:
<Название типа ресурса>.<Название relation-поля>.<Путь к полю Json-объекта в поле "data" связанного объекта>.
Например,elibJournalArticle.links.journalId.
| Тип отношения между объектами | Тип значения атрибута | Если в поле связанного объекта хранится список |
|---|---|---|
| one-to-one | String | List[String] |
| one-to-many | List[String] | List[List[String]].flatten преобразуется в List[String] |
| many-to-many | List[String] | List[List[String]].flatten преобразуется в List[String] |
Список переменных окружения
Список переменных окружения для настройки AttributeProvider. Переменные для логов находятся в
файле resources/logback.xml.
| Переменная | Описание | Значение по-умолчанию |
|---|---|---|
MAVEN_HOME |
Домашняя директория для MAVEN, где находится bin/mvn. Используется только во время сборки. |
"/usr/share/maven" |
AUTHZFORCE_CONSUL_ADDR |
Адрес Consul. | "http://localhost:8500" |
AUTHZFORCE_CONSUL_AUTH_USER |
Адрес Consul. | "http://localhost:8500" |
AUTHZFORCE_CONSUL_AUTH_PASSWORD |
Адрес Consul. | "http://localhost:8500" |
AUTHZFORCE_KAFKA_ADDR |
Название топика для входящих/исходящих событий. | "localhost:9092" |
AUTHZFORCE_KAFKA_EVENTS_TOPIC |
Название топика для входящих/исходящих событий. | "commandevents" |
AUTHZFORCE_KAFKA_AUTH_USER |
Название учетной записи Kafka. Если название не указано, то настройки авторизации не будут применены. | "" |
AUTHZFORCE_KAFKA_AUTH_PASSWORD |
Пароль учетной записи Kafka. | "" |
AUTHZFORCE_KAFKA_AUTH_PRINCIPAL |
Principal учетной записи Kafka в Kerberos(в случае аутентификации в kafka через Kerberos). | "" |
AUTHZFORCE_KAFKA_AUTH_KEYTAB_PATH |
Путь до keytab-файла (в случае аутентификации в kafka через Kerberos). | "" |
AUTHZFORCE_KAFKA_AUTH_TRUSTSTORE_LOCATION |
Путь до хранилища сертификатов (Java key store). Если путь не указан, то сертификат применяться не будет. | "" |
AUTHZFORCE_KAFKA_AUTH_TRUSTSTORE_PASSWORD |
Пароль к хранилищу сертификатов. | "" |
AUTHZFORCE_KAFKA_AUTH_MODE |
Режим аутентификации: static - одна учетная запись на все запросы, mapping - учетная запись зависит от запроса. | "static" |
AUTHZFORCE_KAFKA_AUTH_CONFIG |
Настройки для аутентификации: если AuthMode = mapping, то необходим JSON с List[KafkaAuthConfig]. Переменная соответствует полю authConfig из KafkaAuthSettings. | |
AUTHZFORCE_KAFKA_AUTH_CACHE_SIZE |
Максимальный размер кеша для Kafka producer (количество активных соединений). | |
AUTHZFORCE_KAFKA_CONNECTION_CHECK_TEST_MESSAGES_INTERVAL |
Применяется только для producer-ов со способом аутентификации kerberos. Интервал отправки тестовых сообщений кафки в топик connectionCheck.testMessagesTopicName. Тестовые сообщения (null, service producer test) отправляются регулярно с этим интервалом. | 4 minutes |
AUTHZFORCE_KAFKA_CONNECTION_CHECK_INTERVAL |
Применяется только для producer-ов со способом аутентификации kerberos. Интервал проверки того, сколько тестовых сообщений было отправлено за данный период. Если количество сообщений за этот период равно количеству сообщений за прошлый период, то начинается отсчет периода без сообщений. | 60 seconds |
AUTHZFORCE_KAFKA_CONNECTION_CHECK_FAILED_AFTER_INTERVAL |
Применяется только для producer-ов со способом аутентификации kerberos. Максимальная продолжительность периода без успешно отправленных тестовых сообщений. По ее достижении сервис будет объявлен больным. | 5 minutes |
AUTHZFORCE_KAFKA_AUTH_CACHE_TTL |
Время жизни Kafka producer в кеше. | |
AUTHZFORCE_COMMANDS_PREFIX |
Префикс в Consul для ключей команд. | "commands" |
AUTHZFORCE_CACHE_LIFETIME |
Время жизни в кеше (актуальность) 1 результата выполнения команды. | "20 minutes" |
AUTHZFORCE_CACHE_SIZE |
Максимальное количество закешированных результатов команд. | "10000" |
AUTHZFORCE_CACHE_REQ_TIMEOUT |
Хост для HttpListener. | "10 seconds" |
LOG_LEVEL |
Общий уровень логов. | "INFO" |
LOG_OUTPUT |
Параметры вывода логов: STDOUT - обычный лог в консоль, STDOUT_CEF - лог в формате CEF в консоль, FILE - обычный лог в файл, FILE_CEF - лог в формате CEF в файл, SYSLOG - лог в SYSLOG, SYSLOG_CEF - лог в формате CEF в SYSLOG. | "FILE" |
LOGGING_SRC_IP |
Параметр SRC (источник/source, на который ссылается событие) для логов в формате CEF. Если не установлена, src=notFound. Требуемый формат: IPv4, например 192.168.10.1. |
|
LOGGING_SRC_HOST |
Параметр SHOST (источник/source, на который ссылается событие) для логов в формате CEF. Если не установлена, shost=notFound. Требуемый формат: fully qualified domain name (FQDN), например host или host.domain.com. |
|
LOGGING_DST_IP |
Параметр DST (получатель/destination, на который ссылается событие) для логов в формате CEF. Если не установлена, dst=notFound. Требуемый формат: IPv4, например 192.168.10.1. |
|
LOGGING_CEF_VER |
Версия формата CEF: либо 0, либо 1. Рекомендуется использовать 0. |
0 |
AUTHZFORCE_SENDERLIB_COMMANDS_HTTP_RETRY_ATTEMPTS |
Поле attempts из RetrySettings. |
5 |
AUTHZFORCE_SENDERLIB_COMMANDS_HTTP_RETRY_DELAY |
Поле delay из RetrySettings. |
"5 seconds" |
AUTHZFORCE_SENDERLIB_COMMANDS_HTTP_RETRY_KIND |
CommandResultRetryConditionKind |
"OnSomeExceptions(ConnectException)" |
Формат CEF для authzfoce-provider
У логов есть возможность включить формат CEF для
логирования по следующему шаблону:
2022-12-14T16:56:31+0500 CEF:Version|Device Vendor|Device Product|Device Version|EventClassId|Message|Severity|src=? dst=? shost=? suid=? suser=? msg=? end=currentTimeMillis|.
Чтобы включить логирование в формате CEF, нужно задать переменную LOG_OUTPUT = STDOUT_CEF. Если логи
пишутся в формате CEF, то необходимо задать следующие переменные, которые по умолчанию не заданы:
LOGGING_SRC_IP, для параметраsrcв логахLOGGING_SRC_HOST, для параметраshostв логахLOGGING_DST_IP, для параметраdstв логах
В файле boot/src/main/resources/logback.xml можно поменять class path для основного класса приложения (
переменная projectMainClassPath), если это необходимо.
Maven
В проекте используется Maven, путь к которому должен быть указан в MAVEN_HOME. Для
генерации AttributeValueProviderDescriptor по XML описанию использутся maven
плагин org.jvnet.jaxb2.maven2 % maven-jaxb2-plugin, т.к. он умеет работать с jar в качестве источника XML схем.
Github репозиторий плагина: https://github.com/highsource/maven-jaxb2-plugin.
Конфигурация для плагин находится в файле pom.xml, которй также описывает maven проект. Плагин вызывается во время
компиляции sbt проекта. За вызов плагина отвечает sbt task cachedFilesGeneration и класс MavenInvoker.
Сгененрированные классы кешируются до следующего изменения файлов с конфигурацией для генерации.
Важно На данный момент attribute-provider собирается только под Java 11 и ниже.
Используемые классы
EntityObject (attribute-provider)
Описывает возвращаемый объект из сервиса dataModel
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | uuid | да | ID объекта |
| entityType | string | да | Тип сущности объекта |
| source | string | да | Источник данных для объекта |
| created | TimeStamp | да | Дата и время создания объекта |
| data | json object | да | Json с полями объекта |
| additionalData | json object | да | Json с дополнительными полями объекта |
| version | int | да | Версия объекта для оптимистичных блокировок |
EntityObjectsRepository
Репозиторий с доступом к экземплярам EntityObject по идентификатору EntityObjectIdentity.
Содержит кеш для хранения объектов. При отсутсвии объекта в кеше, отправляет команду с запросом объекта в сервис
dataModel.
FieldValuesExtractor
Вспомогательный объект для получения полей из json-а EntityObject
Алгоритм обновления jar в Authzforce server
- Создать jar через
sbt assembly(target/scala-2.13/attribute-provider.jar) - Добавление namespace (выполняется при первом добавлении attribute-provider.jar)
- Добавить
<xs:import namespace="http://embedika.com/verdi/generated"/>вconf/authzforce-ext.xsd(путь в докер образе/opt/authzforce-ce-server/conf/authzforce-ext.xsd) - Добавить
<uri name="http://embedika.com/verdi/generated" uri="classpath:xsd/com.embedika.verdi.xmlschema.xsd"/>вconf/catalog.xml(путь в докер образе/opt/authzforce-ce-server/conf/catalog.xml)
- Добавить
- Добавить
target/scala-2.13/attribute-provider.jarв/opt/authzforce-ce-server/webapp/WEB-INF/lib - Перезапустить tomcat
Добавление конфига для AttributeValueProvider в необходимый домен:
- Файл конфиг
/opt/authzforce-ce-server/data/domains/{{DOMAIN_ID}}/pdp.xml - URL для PUT запроса изменения
конфига
http://localhost:8080/authzforce-ce/domains/{{DOMAIN_ID}}/pap/attribute.providers - Добавление конфигурации для AttributeValueProvider, активирует его в качестве "attribute provider" для указанных атрибутов
Пример тела запроса на изменение конфигурации AttributeValueProvider
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns2:attributeProviders xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17" xmlns:ns2="http://authzforce.github.io/rest-api-model/xmlns/authz/5" xmlns:ns3="http://www.w3.org/2005/Atom" xmlns:ns4="http://authzforce.github.io/core/xmlns/pdp/7" xmlns:ns5="http://authzforce.github.io/pap-dao-flat-file/xmlns/properties/3.6">
<ns2:attributeProvider xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:ns7="http://embedika.com/verdi/generated" xsi:type="ns7:AttributeValueProviderDescriptor" id="valuesProvider">
<Attributes Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource">
<Attribute AttributeId="MyModel.firstField" IncludeInResult="false">
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">StubValue</AttributeValue>
</Attribute>
<Attribute AttributeId="MyModel.testField" IncludeInResult="false">
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">StubValue</AttributeValue>
</Attribute>
<Attribute AttributeId="MyModel.additionalField" IncludeInResult="false">
<AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">StubValue</AttributeValue>
</Attribute>
</Attributes>
</ns2:attributeProvider>
</ns2:attributeProviders>
Authzforce-client: клиент для Authzforce
Клиент для Authzforce-server предоставляет 3 интерфейса:
Основная особенность, о которой стоит помнить, в том, что клиент не предоставляет многопоточный доступ к API, т.к. скорее всего будет необходима синхронизация не только потоков, но и экземпляров сервисов, которые используют данный клиент.
Authorizer (Authzforce)
Предоставляет API для авторизации. Авторизация происходит на основе "контекста авторизации", т.е. набора полей с заранее известными значениями и набором полей, значения которых вычисляются динамически. Результатом авторизации является решение (Boolean) и набор фильтров, которые необходимо применить к набору обрабатываемых данных.
PolicyUpdater (Authzforce)
Предоставляет API для изменения политик.
Так как все политики должны быть включены в корневую политику (PolicySetId = root), почти все методы вносят изменения в корневую политику.
Данное API не обеспечивает безопасный конкуретный доступ.
AttributeProviderApi (Authzforce)
Предоставляет API для изменения конфигурации AttributeProvider-ов. Конфигурация изменяется атомарно, но возможно "состояние гонки" при доступе к файлу настроек. Данное API не обеспечивает безопасный конкуретный доступ.
Buzzer-client: клиент для работы с сервисами buzzer.
Библиотека предоставляет интерфейсы и реализацию клиента для работы с сервисами buzzer.
Пример создания клиента.
Для того чтобы использовать библиотеку необходимо добавить зависимость "com.embedika.verdi" %% "buzzer-client" % verdiVersion.
Все классы находятся в пакете package com.embedika.buzzer.client.
Предоставлен следующий набор интерфейсов:
- BuzzerClient (клиент основного сервиса Buzzer)
- BuzzerEmailClient (клиент сервиса почтовых рассылок)
- BuzzerPersonalPageClient (клиент сервиса уведомлений в веб интерфейсе)
- BuzzerSubscriptionClient (клиент сервиса подписок на события в системе)
Все данные интерфейсы реализованы в одном классе LiveBuzzerClient.
Buzzer-core: библиотека для сервисов Buzzer
В библиотеку вынесен общий для сервисов уведомлений код.
Модели
Notification
Базовое представление уведомления
| Название поля | Тип | Обязательное | Описание |
|---|---|---|---|
| code | string | да | Код уведомления, по сути идентификатор |
| userId | uuid string | да | Идентификатор пользователя для которого уведомление предназначено |
| data | object | да | Данные уведомления |
MustacheTemplate
Шаблон уведомления
| Название поля | Тип | Обязательное | Описание |
|---|---|---|---|
| key | string | да | Идентификатор шаблона |
| content | string | да | Данные шаблона |
Код для работы с шаблонизатором mustache
MustacheService
Сервис для контролирования эффектов загрузки mustache шаблонов. Библиотека mustache поддерживает импорты шаблонов, но по умолчанию импортируемый шаблон ищется в локальной файловой структуре. Сервис переопределяет это поведение и оборачивает всю логику в алгебру.
Buzzer-email: сервис уведомлений на электронную почту
Сервис получает через Kafka уведомления и отправляет их на электронную почту. Уведомления отправляются через рассылки по определенному расписанию. Каждая рассылка описывает шаблон отображения уведомления в письме. Уведомления могут группироваться в одном письме. Уведомления, рассылки и группы связываются через настройки.
Сервис предоставляет следующие команды:
- CreateSettingEmail
- GetSettingEmail
- DeleteSettingEmail
- UpdateSettingEmail
- ListSettingEmail
- CreateGroupEmail
- GetGroupEmail
- DeleteGroupEmail
- UpdateGroupEmail
- ListGroupEmail
- CreateDeliveryTemplate
- DeliveryTemplatesEmail
- CreateTemplateEmail
- GetTemplateEmail
- DeleteTemplateEmail
- UpdateTemplateEmail
- ListTemplateEmail
- CreateDeliveryEmail
- GetDeliveryEmail
- DeleteDeliveryEmail
- UpdateDeliveryEmail
- ListDeliveryEmail
- ListNotificationErrors
Конфигурирование сервиса отправки уведомлений на электронную почту
Требования к запуску сервиса отправки уведомлений на электронную почту
Запуск сервиса осуществляется локально через sbt, на стенде в docker на jvm.
Для корректной минимальной работы сервиса требуется обязательное подключение к PostgreSQL, Kafka, Consul. Для настройки подключения к ним нужно заполнить обязательные переменные окружения из раздела ниже.
Для нормальной работы сервису дополнительно требуется окружение Verdi: CommandStatus и ApiGateway. В этом случае нужно уделить внимание настройкам, связанным с ServiceDiscovery и CommandDiscovery.
Список переменных окружения сервиса
Все доступные переменные окружения для настройки сервиса отправки уведомлений на электронную почту.
| Переменная | Тип | Обяза-тельная | Значение по умолчанию | Описание |
|---|---|---|---|---|
| SERVER_PORT | int | да | 8080 | Порт, на котором слушает HTTP-сервер |
| CONSUMER_TOPIC | string | да | "email" | Название кафка-топика, куда отправляются запросы на выполнение команд. |
| CONSUMER_GROUP | string | да | "email" | Имя consumer-группы для чтения из CONSUMER_TOPIC. Не должна меняться и не должна быть пустой, иначе сервис будет перечитывать все входящие команды при перезапуске. |
| VERDI_HOST | string | да | "localhost" | Адрес, который будет зарегистрирован за данным экземпляром сервиса |
| VERDI_TTL | duration string | да | 30 seconds | Время, в течение которого экземпляр сервиса считается "активным". Таймер обновляется каждый раз, когда сервис присылает "health check" |
| VERDI_HEALTH_CHECK | duration string | да | 10 seconds | Периодичность отправки "health check" |
| VERDI_COMMAND_STORAGE_UPDATE_PERIOD | duration string | да | 1 minute | Время жизни статуса команд в кеше сервиса статусов (после получения последнего статуса из кафка). |
| VERDI_SERVICE_DISCOVERY_UPDATE_PERIOD | duration string | да | 30 seconds | Период проверки кеша со статусами команд для удаления статусов, время жизни которых превысило COMMAND_STATUS_SERVICE_STATUS_CACHE_TTL. |
| VERDI_ALLOW_INTERNAL_COMMANDS | bool | да | true | Период проверки Command discovery для очистки команд, привязанных к сервисам, которые не считаются "живыми". |
| VERDI_CONSIDER_ALL_COMMANDS_AS_INTERNAL | boolean | Нет | false | Флаг, определяющий будут ли все обращения в другие сервисы являться внутренними (т.е. не требовать авторизацию). Детальное описание механизма: Внутренние команды. |
| VERDI_KAFKA | string | да | "localhost:9092" | Адрес Kafka |
| VERDI_KAFKA_TOPIC | string | да | "commandevents" | Название кафка-топика, куда отправляются сообщения со статусами выполняемых команд. |
| VERDI_KAFKA_AUTH_USER | string | да | "" | Название учетной записи Kafka. Если название не указано, то настройки авторизации не будут применены. |
| VERDI_KAFKA_AUTH_PASSWORD | string | да | "" | Пароль учетной записи Kafka. |
| VERDI_KAFKA_AUTH_PRINCIPAL | string | нет | "" | Principal учетной записи Kafka в Kerberos(в случае соединения с kafka через Kerberos). |
| VERDI_KAFKA_AUTH_KEYTAB_PATH | string | нет | "" | Путь до keytab-файла (в случае соединения с kafka через Kerberos). |
| VERDI_KAFKA_AUTH_TRUSTSTORE_LOCATION | string | да | "" | Путь до хранилища сертификатов (Java key store). Если путь не указан, то сертификат применяться не будет. |
| VERDI_KAFKA_AUTH_TRUSTSTORE_PASSWORD | string | да | "" | Пароль к хранилищу сертификатов. |
| VERDI_KAFKA_AUTH_MODE | string | нет | "static" | Режим аутентификации: static - одна учетная запись на все запросы, mapping - учетная запись зависит от запроса |
| VERDI_KAFKA_AUTH_CONFIG | string | нет | "" | Настройки для аутентификации: если AuthMode = mapping, то необходим JSON с List[KafkaAuthConfig]. Переменная соответствует полю authConfig из KafkaAuthSettings. |
| VERDI_KAFKA_AUTH_CACHE_SIZE | int | нет | Максимальный размер кеша для Kafka producer (количество активных соединений). | |
| VERDI_KAFKA_CONNECTION_CHECK_TEST_MESSAGES_INTERVAL | duration string | нет | 4 minutes | Применяется только для producer-ов со способом аутентификации kerberos. Интервал отправки тестовых сообщений кафки в топик connectionCheck.testMessagesTopicName. Тестовые сообщения (null, service producer test) отправляются регулярно с этим интервалом. |
| VERDI_KAFKA_CONNECTION_CHECK_INTERVAL | duration string | нет | 60 seconds | Применяется только для producer-ов со способом аутентификации kerberos. Интервал проверки того, сколько тестовых сообщений было отправлено за данный период. Если количество сообщений за этот период равно количеству сообщений за прошлый период, то начинается отсчет периода без сообщений. |
| VERDI_KAFKA_CONNECTION_CHECK_FAILED_AFTER_INTERVAL | duration string | нет | 5 minutes | Применяется только для producer-ов со способом аутентификации kerberos. Максимальная продолжительность периода без успешно отправленных тестовых сообщений. По ее достижении сервис будет объявлен больным. |
| VERDI_KAFKA_AUTH_CACHE_TTL | duration string | нет | Время жизни Kafka producer в кеше. | |
| VERDI_CONSUL | url string | да | "http://localhost:8500" | Адрес Сonsul. |
| VERDI_CONSUL_AUTH_USER | string | да | "" | Название учетной записи Сonsul. Если название не указано, то настройки авторизации не будут применены. |
| VERDI_CONSUL_AUTH_PASSWORD | string | да | "" | Пароль учетной записи Сonsul. |
| VERDI_CONSUL_CONNECTION_MAX_RETRY | int | да | 5 | Максимальное количество попыток подключения к Consul после обрыва соединения |
| VERDI_CONSUL_CONNECTION_RETRY_DELAY | duration string | да | 1 seconds | Задержка перед попыткой подключения к Consul |
| DB_HOST | string | да | Хост БД | |
| DB_PORT | int | да | Порт БД | |
| DB_NAME | string | да | Имя базы в БД | |
| DB_JDBC_URL | jdbc url string | да | JDBC-url для соединения с БД. По умолчанию собирается из других обязательных переменных. Можно указать только его, если не хочется отдельно указывать хост/порт/имя базы. | |
| DB_USER | string | да | Пользователь БД | |
| DB_PASSWORD | string | да | Пароль пользователя БД | |
| DB_THREADS | int | нет | 10 | Количество потоков в пуле потоков для соединения с БД |
| DB_QUEUE_SIZE | int | нет | 300 | Размер очереди для действий базы данных, которые не могут быть выполнены немедленно, когда все потоки заняты. За пределами этого значения новые действия немедленно завершаются неудачей |
| DB_CONN_MAX | int | нет | 10 | Максимальное количество одновременных подключений к БД |
| DB_CONN_TIMEOUT | duration string | нет | 20 second | Максимальное время ожидания ответа для соединения к БД. Если это время превышено, а соединение не становится доступным, будет брошено исключение SQLException. 1000 мс — минимальное значение. |
| DB_ISOLATION | string | нет | "READ_COMMITTED" | Уровень изоляции транзакций для новых подключений. Допустимые значения: NONE, READ_COMMITTED, READ_UNCOMMITTED, REPEATABLE_READ, SERIALIZABLE. |
| DB_READONLY | boolean | нет | false | Read-only SQL транзакция может изменять только временные таблицы. Этот параметр управляет статусом «только для чтения» по умолчанию для каждой новой транзакции. |
| DB_CONN_MIN | int | нет | = DB_THREADS | Минимальное количество одновременных подключений к БД |
| DB_VALIDATION_TIMEOUT | duration string | нет | 1 seconds | Максимальное время, в течение которого соединение будет проверяться на работоспособность. 1000 мс — минимальное значение. |
| DB_IDLE_TIMEOUT | duration string | нет | 10 minutes | Максимальное время, в течение которого соединению разрешено простаивать в пуле. Значение 0 означает, что простаивающие соединения никогда не удаляются из пула. |
| DB_MAX_LIFETIME | duration string | нет | 30 minutes | Максимальное время жизни соединения в пуле. Когда простаивающее соединение достигает этого времени ожидания, даже если оно недавно использовалось, оно будет удалено из пула. Значение 0 указывает на отсутствие максимального срока службы. |
| DB_INITIALIZATION_FAIL_FAST | string | нет | false | Deprecated, начиная с версии Slick 3.3.0. Определяет, будет ли пул «быстро выходить из строя», если пул не может быть успешно заполнен начальными соединениями. Если соединения не могут быть созданы во время запуска пула, будет выдано исключение RuntimeException. Это свойство не имеет никакого эффекта, если minConnections равно 0. |
| DB_LEAK_DETECTION_THRESHOLD | int | нет | 0 | Время, в течение которого соединение может находиться вне пула, прежде чем будет зарегистрировано сообщение, указывающее на возможную утечку соединения. Значение 0 означает, что обнаружение утечек отключено. Наименьшее приемлемое значение для включения обнаружения утечек составляет 10 с. |
| DB_CONNECTION_TEST_QUERY | string | нет | "SELECT 1" | Выражение, которое будет выполнено непосредственно перед получением соединения из пула для проверки того, что соединение с базой данных все еще активно. Оно зависит от базы данных и должно представлять собой запрос, требующий минимальной обработки базой данных (например, «VALUES 1»). Если этот параметр не установлен, вместо него используется метод JDBC4 Connection.isValid(). |
| DB_REGISTER_MBEANS | boolean | нет | false | Зарегистрированы ли JMX Management Beans («MBeans») |
| DB_AUTO_COMMIT | boolean | нет | true | Это свойство определяет то, как будут вести себя по умолчанию возвращаемые соединения относительно autocommit-а. |
| DB_SCHEMA | string | нет | "public" | Устанавливает schema по умолчанию |
| DB_ISOLATE_INTERNAL_QUERIES | boolean | нет | false | Определяет то, изолируются ли с помощью транзакций внутренние запросы пула (например запрос connection alive test). Свойство применяется только если autoCommit выключен. |
| DB_INITIALIZATION_FAIL_TIMEOUT | int | нет | 1 | Работает, начиная с версии Slick 3.3.0. Определяет, будет ли пул «быстро выходить из строя», если пул не может быть успешно заполнен начальными соединениями. Любое положительное число считается числом миллисекунд для попытки получить начальное соединение;поток приложения будет заблокирован в течение этого периода. Если соединение не может быть получено до истечения этого времени, будет брошено исключение. Данный таймаут применяется после периода connectionTimeout. Если значение равно нулю (0),HikariCP попытается получить и проверить подключение. Если соединение получено, но проверка не пройдена, будет брошено исключение, и пул не будет запущен. Однако, если соединение не может быть получено, пул запустится, но последующие попытки получить соединение могут потерпеть неудачу. Значение меньше нуля пройдет любую первоначальную попытку подключения, и пул немедленно запустится, пытаясь получить соединения в фоновом режиме. Следовательно, последующие попытки получить соединение могут потерпеть неудачу. |
| VERDI_COMMANDS_HTTP_RETRY_ATTEMPTS | int | нет | 5 | Поле attempts из RetrySettings |
| VERDI_COMMANDS_HTTP_RETRY_DELAY | duration string | нет | "5 seconds" | Поле delay из RetrySettings |
| VERDI_COMMANDS_HTTP_RETRY_KIND | string | нет | "OnSomeExceptions(ConnectException)" | CommandResultRetryConditionKind |
| SENDING_FROM_EMAIL | string | нет | "test@test.test" | Отправитель, который будет указан во всех письмах |
| SMTP_PORT | int | нет | 25 | Порт SMTP-сервера, к которому будет обращаться SMTP-клиент |
| SMTP_HOST | string | нет | "localhost" | Хост SMTP-сервера, к которому будет обращаться SMTP-клиент |
| SENDING_MAX_ATTEMPTS | string | нет | 5 | Максимальное количество попыток отправки уведомления |
| DEBUG_MAIL | string | нет | Почта для дебага. В случае не пустого значения все письма будут отправляться на нее | |
| SMTP_USER | string | нет | Логин для авторизации SMTP-клиента к SMTP-серверу | |
| SMTP_PASSWORD | string | нет | Пароль для авторизации SMTP-клиента к SMTP-серверу | |
| SMTP_READ_TIMEOUT | string | нет | 300 | Время в секундах сколько SMTP-клиент готов ожидать от SMTP-сервера ответ |
| SMTP_WRITE_TIMEOUT | string | нет | 300 | Время в секундах сколько SMTP-клиент готов пытаться передать байты своего ответа SMTP-серверу |
| SMTP_INSECURE | boolean | нет | false | При значении true отключает проверку сертификатов SMTP-сервера |
| EMAIL_CACHE_TTL | int | нет | 300 | TTL кэша с соответствующими определенным userId email-ами в секундах |
Список команд сервиса уведомлений на электронную почту
Заготовка для списка реализованных в сервисе команд, моделей EntityType и действий Actions, которые можно
использовать при настройке авторизации.
На данный момент, ни в одной команде сервиса нет авторизации.
| Название команды | EntityType | Actions |
|---|---|---|
| CreateSettingEmail | Setting | - |
| GetSettingEmail | Setting | - |
| DeleteSettingEmail | Setting | - |
| UpdateSettingEmail | Setting | - |
| ListSettingEmail | Setting | - |
| CreateGroupEmail | Group | - |
| GetGroupEmail | Group | - |
| DeleteGroupEmail | Group | - |
| UpdateGroupEmail | Group | - |
| ListGroupEmail | Group | - |
| CreateTemplateEmail | Template | - |
| GetTemplateEmail | Template | - |
| DeleteTemplateEmail | Template | - |
| UpdateTemplateEmail | Template | - |
| ListTemplateEmail | Template | - |
| CreateDeliveryEmail | Delivery | - |
| GetDeliveryEmail | Delivery | - |
| DeleteDeliveryEmail | Delivery | - |
| UpdateDeliveryEmail | Delivery | - |
| ListDeliveryEmail | Delivery | - |
| CreateDeliveryTemplate | Delivery | - |
| DeliveryTemplatesEmail | Delivery | - |
| ListNotificationErrors | NotificationError | - |
CreateSettingEmail (Buzzer-Email)
Payload для команды
{
"id": "testCode",
"deliveryId": "testDelivery",
"groupId": "testGroup",
"version": 1
}
Результат выполнения команды
"testCode"
Создание настройки.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: Setting
- Result: String (идентификатор настройки)
| Команда | Путь |
|---|---|
| CreateSettingEmail | HTTP POST "/createSetting" |
GetSettingEmail (Buzzer-Email)
Payload для команды
"testCode"
Результат выполнения команды
{
"id": "testCode",
"deliveryId": "testDelivery",
"groupId": "testGroup",
"version": 1
}
Получение настройки.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: String (идентификатор настройки)
- Result: SettingEmail
| Команда | Путь |
|---|---|
| GetSettingEmail | HTTP POST "/getSetting" |
DeleteSettingEmail (Buzzer-Email)
Payload для команды
"testCode"
Результат выполнения команды
1
Удаление настройки.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: String (идентификатор настройки)
- Result: Int (кол-во измененных записей)
| Команда | Путь |
|---|---|
| DeleteSettingEmail | HTTP POST "/deleteSetting" |
UpdateSettingEmail (Buzzer-Email)
Payload для команды
{
"id": "testCode",
"deliveryId": "another-delivery",
"groupId": "testGroup",
"version": 2
}
Результат выполнения команды
1
Обновление настройки.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: Setting
- Result: Int (кол-во измененных записей)
| Команда | Путь |
|---|---|
| UpdateSetting | HTTP POST "/updateSetting" |
ListSettingEmail (Buzzer-Email)
Payload для команды
null
Результат выполнения команды
[
{
"id": "testCode",
"deliveryId": "another-delivery",
"groupId": "testGroup",
"version": 2
}
]
Получение списка настроек.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: null
- Result: List[Setting]
| Команда | Путь |
|---|---|
| ListSettingEmail | HTTP POST "/listSetting" |
CreateGroupEmail (Buzzer-Email)
Payload для команды
{
"id": "testGroup",
"name": "test group",
"version": 1
}
Результат выполнения команды
"testCode"
Создание группы.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: Group
- Result: String (идентификатор группы)
| Команда | Путь |
|---|---|
| CreateGroupEmail | HTTP POST "/createGroup" |
GetGroupEmail (Buzzer-Email)
Payload для команды
"testCode"
Результат выполнения команды
{
"id": "testGroup",
"name": "test group",
"version": 1
}
Получение группы.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: String (идентификатор группы)
- Result: Group
| Команда | Путь |
|---|---|
| GetGroupEmail | HTTP POST "/getGroup" |
DeleteGroupEmail (Buzzer-Email)
Payload для команды
"testCode"
Результат выполнения команды
1
Удаление группы.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: String (идентификатор группы)
- Result: Int (кол-во измененных записей)
| Команда | Путь |
|---|---|
| DeleteGroupEmail | HTTP POST "/deleteGroup" |
UpdateGroupEmail (Buzzer-Email)
Payload для команды
{
"id": "testGroup",
"name": "test group for notification delivery",
"version": 2
}
Результат выполнения команды
1
Обновление группы.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: Group
- Result: Int (кол-во измененных записей)
| Команда | Путь |
|---|---|
| UpdateGroupEmail | HTTP POST "/updateGroup" |
ListGroupEmail (Buzzer-Email)
Payload для команды
null
Результат выполнения команды
[
{
"id": "testGroup",
"name": "test group for notification delivery",
"version": 2
}
]
Получение списка групп.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: null
- Result: List[Group]
| Команда | Путь |
|---|---|
| ListGroupEmail | HTTP POST "/listGroup" |
CreateTemplateEmail (Buzzer-Email)
Payload для команды
{
"id": "testTemplate",
"title": "some title",
"content": "<b>some content</b>: {{data}}",
"version": 1
}
Результат выполнения команды
"testCode"
Создание шаблона.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
Данные для вставки в шаблон находятся по пути groups.notifications.data.*
- Payload: Template
- Result: String (идентификатор шаблона)
| Команда | Путь |
|---|---|
| CreateTemplateEmail | HTTP POST "/createTemplate" |
GetTemplateEmail (Buzzer-Email)
Payload для команды
"testCode"
Результат выполнения команды
{
"id": "testTemplate",
"title": "some title",
"content": "<b>some content</b>: {{data}}",
"version": 1
}
Получение шаблона.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: String (идентификатор шаблона)
- Result: Template
| Команда | Путь |
|---|---|
| GetTemplateEmail | HTTP POST "/getTemplate" |
DeleteTemplateEmail (Buzzer-Email)
Payload для команды
"testCode"
Результат выполнения команды
1
Удаление шаблона.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: String (идентификатор шаблона)
- Result: Int (кол-во измененных записей)
| Команда | Путь |
|---|---|
| DeleteTemplateEmail | HTTP POST "/deleteTemplate" |
UpdateTemplateEmail (Buzzer-Email)
Payload для команды
{
"id": "testTemplate",
"title": "Object deletion",
"content": "Объект {{data.title}} удален",
"version": 2
}
Результат выполнения команды
1
Обновление шаблона.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: Template
- Result: Int (кол-во измененных записей)
| Команда | Путь |
|---|---|
| UpdateTemplateEmail | HTTP POST "/updateTemplate" |
ListTemplateEmail (Buzzer-Email)
Payload для команды
null
Результат выполнения команды
[
{
"id": "testTemplate",
"title": "Object deletion",
"content": "Объект {{data.title}} удален",
"version": 2
}
]
Получение списка шаблонов.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: null
- Result: List[Template]
| Команда | Путь |
|---|---|
| ListTemplateEmail | HTTP POST "/listTemplate" |
CreateDeliveryEmail (Buzzer-Email)
Payload для команды
{
"id": "testDelivery",
"schedule": "0 12"
}
Результат выполнения команды
"testCode"
Создание рассылки.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
Формат: {{minutes}} {{hours}}
- Payload: Delivery
- Result: String (идентификатор рассылки)
| Команда | Путь |
|---|---|
| CreateDeliveryEmail | HTTP POST "/createDelivery" |
GetDeliveryEmail (Buzzer-Email)
Payload для команды
"testDelivery"
Результат выполнения команды
{
"id": "testDelivery",
"schedule": "15 *",
"version": 1
}
Получение рассылки.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: String (идентификатор рассылки)
- Result: Delivery
| Команда | Путь |
|---|---|
| GetDeliveryEmail | HTTP POST "/getDelivery" |
DeleteDeliveryEmail (Buzzer-Email)
Payload для команды
"testDelivery"
Результат выполнения команды
1
Удаление рассылки.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: String (идентификатор рассылки)
- Result: Int (кол-во измененных записей)
| Команда | Путь |
|---|---|
| DeleteDeliveryEmail | HTTP POST "/deleteDelivery" |
UpdateDeliveryEmail (Buzzer-Email)
Payload для команды
{
"id": "testDelivery",
"schedule": "0 *"
}
Результат выполнения команды
1
Обновление рассылки.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: Delivery
- Result: Int (кол-во измененных записей)
| Команда | Путь |
|---|---|
| UpdateDeliveryEmail | HTTP POST "/updateDelivery" |
ListDeliveryEmail (Buzzer-Email)
Payload для команды
null
Результат выполнения команды
[
{
"id": "testDelivery",
"schedule": "0 14",
"version": 2
}
]
Получение списка рассылок.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: null
- Result: List[Delivery]
| Команда | Путь |
|---|---|
| ListDeliveryEmail | HTTP POST "/listDelivery" |
ListNotificationErrors (Buzzer-email)
Payload для команды
{
"sorting": {
"fieldName": "created",
"order": "asc"
},
"paging": {
"page": 1,
"count": 20
},
"query": "isRead",
"context": {
"isRead": "false"
}
}
Результат выполнения команды
{
"total": 1,
"items": [
{
"id": "a133f0c8-a516-4537-8f3f-915acb335e2c",
"errorMessage": "Test error message",
"notificationId": "d95c6a34-9c06-4bd3-9c65-3e6323dc33a2",
"created": "1671179029000",
"stackTrace": null
}
]
}
Список ошибок отправки уведомлений.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: Search
- Result: Page[NotificationError]
| Команда | Путь |
|---|---|
| ListNotificationErrors | HTTP POST "/listNotificationErrors" |
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров |
|---|---|
| created | InSetQuery, LikeQuery, RangeQuery |
| errorMessage | InSetQuery, LikeQuery |
| notificationId | InSetQuery, LikeQuery |
| id | InSetQuery |
Доступные поля для сортировки:
| Поле |
|---|
| created |
| errorMessage |
| notificationId |
| id |
CreateDeliveryTemplate (buzzer-email)
Payload для команды
{
"templateId": "testTemplate",
"deliveryId": "testDelivery"
}
Результат выполнения команды
1
Связывание рассылки и шаблона.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: DeliveryTemplateDTO
- Result: Int (кол-во измененных записей)
| Команда | Путь |
|---|---|
| CreateDeliveryTemplate | HTTP POST "/createDeliveryTemplate" |
DeliveryTemplatesEmail (buzzer-email)
Payload для команды
"testDelivery"
Результат выполнения команды
[
{
"id": "testTemplate",
"title": "Object deletion",
"content": "Объект {{data.title}} удален",
"version": 2
}
]
Получения списка шаблонов привязанных к рассылке.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: String (идентификатор настройки)
- Result: List[Template]
| Команда | Путь |
|---|---|
| DeliveryTemplatesEmail | HTTP POST "/deliveryTemplates" |
Модели сервиса отправки уведомлений на электронную почту
Delivery (Buzzer-email)
Рассылка
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | String | Да | Идентификатор рассылки |
| schedule | String | Да | Расписание в виде строки для cron в формате {{minutes}} {{hours}} |
| version | Long | Да | Версия рассылки, unix timestamp даты создания |
CreateDelivery (Buzzer-email)
Запрос создания рассылки
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | String | Да | Идентификатор рассылки |
| schedule | String | Да | Расписание в виде строки для cron в формате {{minutes}} {{hours}} |
| templateId | String | Да | Идентификатор шаблона |
DeliveryTemplate (Buzzer-email)
Связь рассылки и шаблона
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | UUID | Да | Идентификатор связи |
| deliveryId | String | Да | Идентификатор рассылки |
| templateId | String | Да | Идентификатор шаблона |
DeliveryTemplateDTO (Buzzer-email)
Запрос создания связи рассылки и шаблона
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| templateId | String | Да | Идентификатор шаблона |
| deliveryId | String | Да | Идентификатор рассылки |
Template (Buzzer-email)
Шаблон отображения уведомления или группы уведомлений в письме
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | String | Да | Идентификатор |
| title | String | Да | Заголовок |
| content | String | Да | Шаблон рендеринга уведомлений в виде html разметки |
| version | Int | Нет | Версия. Значение по умолчанию: 1 |
Group (Buzzer-email)
Группа уведомлений для отображения в письме
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | String | Да | Идентификатор |
| name | String | Да | Название группы |
| version | Int | Нет | Версия. Значение по умолчанию: 1 |
Setting (Buzzer-email)
Настройка рассылок и групп уведомлений
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | String | Да | Идентификатор, должен соответствовать коду уведомления |
| deliveryId | String | Да | Идентификатор рассылки |
| groupId | String | Да | Идентификатор группы |
| version | Int | Нет | Версия. Значение по умолчанию: 1 |
StoredNotification (Buzzer-email)
Сохраняемые уведомления
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | UUID | Да | Идентификатор уведомления |
| code | String | Да | Код уведомления |
| userId | UUID | Да | Идентификатор пользователя |
| data | Json | Да | Данные уведомления |
| String | Да | Email пользователя | |
| created | LocalDateTime | Да | Дата сохранения. A date-time without a time-zone in the ISO-8601 calendar system, such as "2007-12-03T10:15:30" |
| isSend | Boolean | Да | Отметка об успешной отправке |
| numberOfAttempts | Int | Да | Количество попыток отправки |
NotificationError (Buzzer-email)
Ошибки отправки уведомлений
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | UUID | Да | Идентификатор ошибки |
| notificationId | UUID | Да | Идентификатор уведомления |
| errorMessage | String | Нет | Сообщение об ошибке |
| stackTrace | String | Нет | Дополнительная подробная информация об ошибке |
| created | TimeStamp | Да | Дата сохранения (unix timestamp) |
Envelop (Buzzer-email)
Промежуточная структура для представления письма
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| to | String | Да | Адресат письма |
| subject | String | Да | Заголовок письма |
| content | String | Да | Содержимое письма |
Buzzer-personal-page: сервис уведомлений в личном кабинете
Сервис получает через Kafka уведомления, сохраняет и затем по запросу возвращает для личного кабинета пользователя. Уведомления могут быть поделены по разделам личного кабинета. Уведомления отображаются в личном кабинете по определенным шаблонам. Уведомления, разделы и шаблоны связываются через настройки.
Сервис предоставляет следующие команды:
- searchPPNotifications
- auditSearchPPNotifications
- changeNotificationStatus
- createSectionPp
- getSectionPp
- deleteSectionPp
- updateSectionPp
- listSectionPp
- createSettingPp
- getSettingPp
- deleteSettingPp
- updateSettingPp
- listSettingPp
- createTemplatePp
- getTemplatePp
- deleteTemplatePp
- updateTemplatePp
- listTemplatePp
Список переменных окружения для сервиса Buzzer-personal-page
Все доступные переменные окружения для настройки сервиса уведомлений в личном кабинете.
| Переменная | Тип | Обяза-тельная | Значение по умолчанию | Описание |
|---|---|---|---|---|
| SERVER_PORT | int | да | 8080 | Порт, на котором слушает HTTP-сервер |
| CONSUMER_TOPIC | string | да | "personal-page" | Название кафка-топика, куда отправляются запросы на выполнение команд. |
| CONSUMER_GROUP | string | да | "personal-page" | Имя consumer-группы для чтения из CONSUMER_TOPIC. Не должна меняться и не должна быть пустой, иначе сервис будет перечитывать все входящие команды при перезапуске. |
| CONSUMER_CHUNK_SIZE | int | да | 8080 | Максимальный размер "пачки сообщений", которые будут вычитываться из CONSUMER_TOPIC |
| CONSUMER_CHUNK_WITHIN | duration string | да | 8080 | Время в течении которого будет ожидаться "пачка сообщений" (максимальная длительность набора "пачки") |
| VERDI_HOST | string | да | "localhost" | Адрес который будет зарегистрирован за данным экземпляром сервиса |
| VERDI_TTL | duration string | да | 30 seconds | Время в течении которого экземпляр сервиса считается "активным". Таймер обновляется каждый раз, когда сервис присылает "health check" |
| VERDI_HEALTH_CHECK | duration string | да | 10 seconds | Периодичность отправки "health check" |
| VERDI_COMMAND_STORAGE_UPDATE_PERIOD | duration string | да | 1 minute | Время жизни статуса команд в кеше сервиса статусов (после получения последнего статуса из кафка). |
| VERDI_SERVICE_DISCOVERY_UPDATE_PERIOD | duration string | да | 30 seconds | Период проверки кеша со статусами команд для удаления статусов, время жизни которых превысило COMMAND_STATUS_SERVICE_STATUS_CACHE_TTL. |
| VERDI_ALLOW_INTERNAL_COMMANDS | bool | да | true | Период проверки Command discovery для очистки команд, привязанных к сервисам которые не считаются "живыми". |
| VERDI_CONSIDER_ALL_COMMANDS_AS_INTERNAL | boolean | Нет | false | Флаг, определяющий будут ли все обращения в другие сервисы являться внутренними (т.е. не требовать авторизацию). Детальное описание механизма: Внутренние команды. |
| VERDI_KAFKA | string | да | "localhost:9092" | Адрес Kafka |
| VERDI_KAFKA_TOPIC | string | да | "commandevents" | Название кафка-топика, куда отправляются сообщения со статусами выполняемых команд. |
| VERDI_KAFKA_AUTH_USER | string | да | "" | Название учетной записи Kafka. Если название не указано, то настройки авторизации не будут применены. |
| VERDI_KAFKA_AUTH_PASSWORD | string | да | "" | Пароль учетной записи Kafka. |
| VERDI_KAFKA_AUTH_PRINCIPAL | string | нет | "" | Principal учетной записи Kafka в Kerberos(в случае соединения с kafka через Kerberos). |
| VERDI_KAFKA_AUTH_KEYTAB_PATH | string | нет | "" | Путь до keytab-файла (в случае соединения с kafka через Kerberos). |
| VERDI_KAFKA_AUTH_TRUSTSTORE_LOCATION | string | да | "" | Путь до хранилища сертификатов (Java key store). Если путь не указан, то сертификат применяться не будет. |
| VERDI_KAFKA_AUTH_TRUSTSTORE_PASSWORD | string | да | "" | Пароль к хранилищу сертификатов. |
| VERDI_KAFKA_AUTH_MODE | string | нет | "static" | Режим аутентификации: static - одна учетная запись на все запросы, mapping - учетная запись зависит от запроса |
| VERDI_KAFKA_AUTH_CONFIG | string | нет | "" | Настройки для аутентификации: если AuthMode = mapping, то необходим JSON с List[KafkaAuthConfig]. Переменная соответствует полю authConfig из KafkaAuthSettings. |
| VERDI_KAFKA_AUTH_CACHE_SIZE | int | нет | Максимальный размер кеша для Kafka producer (количество активных соединений). | |
| VERDI_KAFKA_CONNECTION_CHECK_TEST_MESSAGES_INTERVAL | duration string | нет | 4 minutes | Применяется только для producer-ов со способом аутентификации kerberos. Интервал отправки тестовых сообщений кафки в топик connectionCheck.testMessagesTopicName. Тестовые сообщения (null, service producer test) отправляются регулярно с этим интервалом. |
| VERDI_KAFKA_CONNECTION_CHECK_INTERVAL | duration string | нет | 60 seconds | Применяется только для producer-ов со способом аутентификации kerberos. Интервал проверки того, сколько тестовых сообщений было отправлено за данный период. Если количество сообщений за этот период равно количеству сообщений за прошлый период, то начинается отсчет периода без сообщений. |
| VERDI_KAFKA_CONNECTION_CHECK_FAILED_AFTER_INTERVAL | duration string | нет | 5 minutes | Применяется только для producer-ов со способом аутентификации kerberos. Максимальная продолжительность периода без успешно отправленных тестовых сообщений. По ее достижении сервис будет объявлен больным. |
| VERDI_KAFKA_AUTH_CACHE_TTL | duration string | нет | Время жизни Kafka producer в кеше. | |
| VERDI_CONSUL | url string | да | "http://localhost:8500" | Адрес Сonsul. |
| VERDI_CONSUL_AUTH_USER | string | да | "" | Название учетной записи Сonsul. Если название не указано, то настройки авторизации не будут применены. |
| VERDI_CONSUL_AUTH_PASSWORD | string | да | "" | Пароль учетной записи Сonsul. |
| VERDI_CONSUL_CONNECTION_MAX_RETRY | int | да | 5 | Максимальное количество попыток подключения к Consul после обрыва соединения |
| VERDI_CONSUL_CONNECTION_RETRY_DELAY | duration string | да | 1 seconds | Задержка перед попыткой подключения к Consul |
| DB_HOST | string | да | Хост БД | |
| DB_PORT | int | да | Порт БД | |
| DB_NAME | string | да | Имя базы в БД | |
| DB_JDBC_URL | jdbc url string | да | JDBC-url для соединения с БД. По умолчанию собирается из других обязательных переменных. Можно указать только его, если не хочется отдельно указывать хост/порт/имя базы. | |
| DB_USER | string | да | Пользователь БД | |
| DB_PASSWORD | string | да | Пароль пользователя БД | |
| DB_THREADS | int | нет | 10 | Количество потоков в пуле потоков для соединения с БД |
| DB_QUEUE_SIZE | int | нет | 300 | Размер очереди для действий базы данных, которые не могут быть выполнены немедленно, когда все потоки заняты. За пределами этого значения новые действия немедленно завершаются неудачей |
| DB_CONN_MAX | int | нет | 10 | Максимальное количество одновременных подключений к БД |
| DB_CONN_TIMEOUT | duration string | нет | 20 second | Максимальное время ожидания ответа для соединения к БД. Если это время превышено, а соединение не становится доступным, будет брошено исключение SQLException. 1000 мс — минимальное значение. |
| DB_ISOLATION | string | нет | "READ_COMMITTED" | Уровень изоляции транзакций для новых подключений. Допустимые значения: NONE, READ_COMMITTED, READ_UNCOMMITTED, REPEATABLE_READ, SERIALIZABLE. |
| DB_READONLY | boolean | нет | false | Read-only SQL транзакция может изменять только временные таблицы. Этот параметр управляет статусом «только для чтения» по умолчанию для каждой новой транзакции. |
| DB_CONN_MIN | int | нет | = DB_THREADS | Минимальное количество одновременных подключений к БД |
| DB_VALIDATION_TIMEOUT | duration string | нет | 1 seconds | Максимальное время, в течение которого соединение будет проверяться на работоспособность. 1000 мс — минимальное значение. |
| DB_IDLE_TIMEOUT | duration string | нет | 10 minutes | Максимальное время, в течение которого соединению разрешено простаивать в пуле. Значение 0 означает, что простаивающие соединения никогда не удаляются из пула. |
| DB_MAX_LIFETIME | duration string | нет | 30 minutes | Максимальное время жизни соединения в пуле. Когда простаивающее соединение достигает этого времени ожидания, даже если оно недавно использовалось, оно будет удалено из пула. Значение 0 указывает на отсутствие максимального срока службы. |
| DB_INITIALIZATION_FAIL_FAST | string | нет | false | Deprecated, начиная с версии Slick 3.3.0. Определяет, будет ли пул «быстро выходить из строя», если пул не может быть успешно заполнен начальными соединениями. Если соединения не могут быть созданы во время запуска пула, будет выдано исключение RuntimeException. Это свойство не имеет никакого эффекта, если minConnections равно 0. |
| DB_LEAK_DETECTION_THRESHOLD | int | нет | 0 | Время, в течение которого соединение может находиться вне пула, прежде чем будет зарегистрировано сообщение, указывающее на возможную утечку соединения. Значение 0 означает, что обнаружение утечек отключено. Наименьшее приемлемое значение для включения обнаружения утечек составляет 10 с. |
| DB_CONNECTION_TEST_QUERY | string | нет | "SELECT 1" | Выражение, которое будет выполнено непосредственно перед получением соединения из пула для проверки того, что соединение с базой данных все еще активно. Оно зависит от базы данных и должно представлять собой запрос, требующий минимальной обработки базой данных (например, «VALUES 1»). Если этот параметр не установлен, вместо него используется метод JDBC4 Connection.isValid(). |
| DB_AUTO_COMMIT | boolean | нет | true | Это свойство определяет то, как будут вести себя по умолчанию возвращаемые соединения относительно autocommit-а. |
| DB_SCHEMA | string | нет | "public" | Устанавливает schema по умолчанию |
| DB_ISOLATE_INTERNAL_QUERIES | boolean | нет | false | Определяет то, изолируются ли с помощью транзакций внутренние запросы пула (например запрос connection alive test). Свойство применяется только если autoCommit выключен. |
| DB_INITIALIZATION_FAIL_TIMEOUT | int | нет | 1 | Работает, начиная с версии Slick 3.3.0. Определяет, будет ли пул «быстро выходить из строя», если пул не может быть успешно заполнен начальными соединениями. Любое положительное число считается числом миллисекунд для попытки получить начальное соединение;поток приложения будет заблокирован в течение этого периода. Если соединение не может быть получено до истечения этого времени, будет брошено исключение. Данный таймаут применяется после периода connectionTimeout. Если значение равно нулю (0),HikariCP попытается получить и проверить подключение. Если соединение получено, но проверка не пройдена, будет брошено исключение, и пул не будет запущен. Однако, если соединение не может быть получено, пул запустится, но последующие попытки получить соединение могут потерпеть неудачу. Значение меньше нуля пройдет любую первоначальную попытку подключения, и пул немедленно запустится, пытаясь получить соединения в фоновом режиме. Следовательно, последующие попытки получить соединение могут потерпеть неудачу. |
| DB_REGISTER_MBEANS | boolean | нет | false | Зарегистрированы ли JMX Management Beans («MBeans») |
| VERDI_COMMANDS_HTTP_RETRY_ATTEMPTS | int | нет | 5 | Поле attempts из RetrySettings |
| VERDI_COMMANDS_HTTP_RETRY_DELAY | duration string | нет | "5 seconds" | Поле delay из RetrySettings |
| VERDI_COMMANDS_HTTP_RETRY_KIND | string | нет | "OnSomeExceptions(ConnectException)" | CommandResultRetryConditionKind |
Команды сервиса Buzzer-personal-page
searchPPNotifications (Buzzer-personal-page)
Payload для команды
{
"search": {
"sorting": {
"fieldName": "created",
"order": "asc"
},
"paging": {
"page": 1,
"count": 20
},
"query": "isRead",
"context": {
"isRead": "false"
}
}
}
Результат выполнения команды
{
"total": 1,
"items": [
{
"id": "a133f0c8-a516-4537-8f3f-915acb335e2c",
"code": "testCode",
"userId": "a133f0c8-a516-4537-8f3f-915acb335e2c",
"data": {},
"created": 1673942815499,
"isRead": false,
"render": null
}
]
}
Поиск уведомлений в личном кабинете (ЛК). В качестве фильтра по пользователю, всегда используется текущий
пользователь, который отправил запрос.
Если в Search-объекте был передан фильтр "userId", то он будет переписан на текущего пользователя.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: SearchRequest
- Result: Page[NotificationPP]
| Команда | Путь |
|---|---|
| searchPPNotifications | HTTP POST "/search" |
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров |
|---|---|
| userId | Всегда используется текущий пользователь |
| sectionId | InSetQuery |
| isRead | InSetQuery |
| id | InSetQuery |
Доступные поля для сортировки:
| Поле |
|---|
| created |
| isRead |
auditSearchPPNotifications (Buzzer-personal-page)
Payload для команды
{
"search": {
"sorting": {
"fieldName": "created",
"order": "asc"
},
"paging": {
"page": 1,
"count": 20
},
"query": "userId",
"context": {
"userId": {
"kind": "any",
"values": [
"a133f0c8-a516-4537-8f3f-915acb335e2c",
"aa1ceac9-a21c-4eba-9268-c62ce7fde9b3",
"d1533243-10f1-40d8-bd88-ffe6cef735aa"
]
}
}
}
}
Результат выполнения команды
{
"total": 1,
"items": [
{
"id": "a133f0c8-a516-4537-8f3f-915acb335e2c",
"code": "testCode",
"userId": "a133f0c8-a516-4537-8f3f-915acb335e2c",
"data": {},
"created": 1673942815499,
"isRead": false,
"render": null
}
]
}
Поиск уведомлений в личном кабинете (ЛК), в котором можно указать любых пользователей в фильтре "userId".
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: SearchRequest
- Result: Page[NotificationPP]
| Команда | Путь |
|---|---|
| auditSearchPPNotifications | HTTP POST "/auditSearch" |
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров |
|---|---|
| userId | InSetQuery |
| sectionId | InSetQuery |
| isRead | InSetQuery |
| id | InSetQuery |
Доступные поля для сортировки:
| Поле |
|---|
| created |
| isRead |
changeNotificationStatus (Buzzer-personal-page)
Payload для команды
{
"ids": [
"00000000-0000-0000-0000-000000000001",
"00000000-0000-0000-0000-000000000002"
],
"isRead": true,
"allNotifications": false
}
Результат выполнения команды
true
Поиск уведомлений в личном кабинете (ЛК).
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: ChangeNotificationsDTO
- Result: Boolean
| Команда | Путь |
|---|---|
| changeNotificationStatus | HTTP POST "/changeNotificationStatus" |
createSectionPp (Buzzer-personal-page)
Payload для команды
{
"id": "section1",
"name": "section name",
"version": 1
}
Результат выполнения команды
"section1"
Создание раздела.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: Section
- Result: String (идентификатор раздела)
| Команда | Путь |
|---|---|
| createSectionPp | HTTP POST "/createSection" |
getSectionPp (Buzzer-personal-page)
Payload для команды
"section1"
Результат выполнения команды
{
"id": "section1",
"name": "section name",
"version": 1
}
Получение раздела.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: String (идентификатор раздела)
- Result: Section
| Команда | Путь |
|---|---|
| getSectionPp | HTTP POST "/getSection" |
deleteSectionPp (Buzzer-personal-page)
Payload для команды
"section1"
Результат выполнения команды
1
Удаление раздела.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: String (идентификатор раздела)
- Result: Int (кол-во измененных записей)
| Команда | Путь |
|---|---|
| deleteSectionPp | HTTP POST "/deleteSection" |
updateSectionPp (Buzzer-personal-page)
Payload для команды
{
"id": "section1",
"name": "other section name",
"version": 2
}
Результат выполнения команды
1
Обновление раздела.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: Section
- Result: Int (кол-во измененных записей)
| Команда | Путь |
|---|---|
| updateSectionPp | HTTP POST "/updateSection" |
listSectionPp (Buzzer-personal-page)
Payload для команды
null
Результат выполнения команды
[
{
"id": "section1",
"name": "other section name",
"version": 2
}
]
Получение списка разделов.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: null
- Result: List[Section]
| Команда | Путь |
|---|---|
| listSectionPp | HTTP POST "/listSection" |
createSettingPp (Buzzer-personal-page)
Payload для команды
{
"id": "testCode",
"sectionId": "section1",
"version": 1
}
Результат выполнения команды
"testCode"
Создание настройки.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: Setting
- Result: String (идентификатор настройки)
| Команда | Путь |
|---|---|
| createSettingPp | HTTP POST "/createSetting" |
getSettingPp (Buzzer-personal-page)
Payload для команды
"testCode"
Результат выполнения команды
{
"id": "testCode",
"sectionId": "section1",
"version": 1
}
Получение настройки.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: String (идентификатор настройки)
- Result: Setting
| Команда | Путь |
|---|---|
| getSettingPp | HTTP POST "/getSetting" |
deleteSettingPp (Buzzer-personal-page)
Payload для команды
"testCode"
Результат выполнения команды
1
Удаление настройки.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: String (идентификатор настройки)
- Result: Int (кол-во измененных записей)
| Команда | Путь |
|---|---|
| deleteSetting | HTTP POST "/deleteSetting" |
updateSetting (Buzzer-personal-page)
Payload для команды
{
"id": "testCode",
"sectionId": "section2",
"version": 2
}
Результат выполнения команды
1
Обновление настройки.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: Setting
- Result: Int (кол-во измененных записей)
| Команда | Путь |
|---|---|
| updateSettingPp | HTTP POST "/updateSetting" |
listSettingPp (Buzzer-personal-page)
Payload для команды
null
Результат выполнения команды
[
{
"id": "testCode",
"sectionId": "section2",
"version": 2
}
]
Получение списка настроек.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: null
- Result: List[Setting]
| Команда | Путь |
|---|---|
| listSettingPp | HTTP POST "/listSetting" |
createTemplatePp (Buzzer-personal-page)
Payload для команды
{
"id": "template1",
"settingId": "testCode",
"title": "",
"content": "",
"version": 1
}
Результат выполнения команды
"template1"
Создание шаблона.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: Template
- Result: String (идентификатор шаблона)
| Команда | Путь |
|---|---|
| createTemplatePp | HTTP POST "/createTemplate" |
getTemplatePp (Buzzer-personal-page)
Payload для команды
"template1"
Результат выполнения команды
{
"id": "template1",
"settingId": "testCode",
"title": "",
"content": "",
"version": 1
}
Получение шаблона.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: String (идентификатор шаблона)
- Result: Template
| Команда | Путь |
|---|---|
| getTemplatePp | HTTP POST "/getTemplate" |
deleteTemplatePp (Buzzer-personal-page)
Payload для команды
"template1"
Результат выполнения команды
1
Удаление шаблона.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: String (идентификатор шаблона)
- Result: Int (кол-во измененных записей)
| Команда | Путь |
|---|---|
| deleteTemplatePp | HTTP POST "/deleteTemplate" |
updateTemplatePp (Buzzer-personal-page)
Payload для команды
{
"id": "template1",
"settingId": "testCode",
"title": "Template name",
"content": "",
"version": 1
}
Результат выполнения команды
1
Обновление шаблона.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: Template
- Result: Int (кол-во измененных записей)
| Команда | Путь |
|---|---|
| updateTemplatePp | HTTP POST "/updateTemplate" |
listTemplatePp (Buzzer-personal-page)
Payload для команды
null
Результат выполнения команды
[
{
"id": "template1",
"settingId": "testCode",
"title": "Template code",
"content": "",
"version": 1
}
]
Получение списка шаблонов.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: null
- Result: List[Template]
| Команда | Путь |
|---|---|
| listTemplatePp | HTTP POST "/listTemplate" |
Модели сервиса Buzzer-personal-page
NotificationPP (Buzzer-personal-page)
Уведомление личного кабинета
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | UUID | Да | Идентификатор уведомления |
| code | String | Да | Код уведомления |
| userId | UUID | Да | Идентификатор пользователя |
| data | Json | Да | Данные уведомления |
| created | TimeStamp | Да | Дата сохранения |
| isRead | Boolean | Да | Отметка о прочтении |
| render | String | Нет | Рендер уведомления |
SearchRequest (Buzzer-personal-page)
Поисковый запрос
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| search | Search | Да | Параметры поиска |
| markRead | Boolean | Нет | Нужно ли помечать уведомления как прочитанные |
| render | Boolean | Нет | Нужно ли рендерить уведомления |
ChangeNotificationsDTO (Buzzer-personal-page)
Данные для изменения статуса уведомлений
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| ids | List[UUID] | Да | Список идентификаторов уведомлений для изменения |
| isRead | Boolean | Да | Новый статус уведомлений. True - "прочитано", False - "не прочитано" |
| allNotifications | Boolean | Да | Применение изменений ко всем уведомлениям. True - "игнорирование списка ID", False - "изменить только переданные ID" |
Section (Buzzer-personal-page)
Раздел личного кабинета
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | String | Да | Идентификатор |
| name | String | Да | Название раздела |
| version | Int | Нет | Версия. Значение по умолчанию: 1 |
Setting (Buzzer-personal-page)
Настройка раздела личного кабинета
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | String | Да | Идентификатор, должен соответствовать коду уведомления |
| sectionId | String | Да | Идентификатор раздела |
| version | Int | Нет | Версия. Значение по умолчанию: 1 |
StoredNotification (Buzzer-personal-page)
Сохраняемые уведомления
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | UUID | Да | Идентификатор |
| code | String | Да | Код уведомления |
| userId | UUID | Да | Идентификатор пользователя |
| data | Json | Да | Данные уведомления При рендере данных из data в случае когда полеотсутствует или равно null оно отображается как пустая строка. |
| created | TimeStamp | Да | Дата сохранения |
| isRead | Boolean | Да | Отметка о прочтении |
Template (Buzzer-personal-page)
Шаблон
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | String | Да | Идентификатор |
| settingId | String | Да | Идентификатор настройки |
| title | String | Да | Заголовок |
| content | String | Да | Шаблон рендеринга уведомлений |
| version | Int | Нет | Версия. Значение по умолчанию: 1 |
Buzzer-subscription: сервис подписок
Сервис подписок обеспечивает генерацию уведомлений при поступлении от бизнес-логики событий, приходящих через Kafka в
топик businessevent.
Также сервис принимает HTTP команды и хранит в PostgreSQL информацию о настройках подписки для событий и подписках
пользователя.
Локальный запуск сервиса подписок
При запуске сервиса ожидается, что уже развернута необходимая инфраструктура:
- PostgreSQL база по адресу
localhost:5432/buzzer-subscription - Kafka по адресу
localhost:9092 - Consul по адресу
localhost:8500 - Добавлены необходимые переменные окружения:
- DB_HOST
- DB_PORT
- DB_NAME
- DB_USER
- DB_PASSWORD
Запуск сервиса подписок из консоли с помощью SBT
DB_HOST=localhost DB_PORT=5432 DB_NAME=buzzer-subscription DB_USER=$DB_USER DB_PASSWORD=$DB_PASSWORD sbt run
Список переменных окружения для сервиса Buzzer-subscription
| Переменная | Значение по умолчанию | Описание |
|---|---|---|
| SERVER_PORT | 8080 | Порт для HttpListener |
| CONSUMER_TOPIC | "entityObjectEvent" | Название топика для чтения событий |
| CONSUMER_GROUP | "notification" | Название группы для чтения событий |
| SENDER_TOPIC | "notification" | Название топика для отправки уведомлений |
| VERDI_CONSUL | "http://localhost:8500" | Адрес Сonsul |
| VERDI_CONSUL_AUTH_USER | "" | Название учетной записи Сonsul. Если название не указано, то настройки авторизации не будут применены. |
| VERDI_CONSUL_AUTH_PASSWORD | "" | Пароль учетной записи Сonsul. |
| VERDI_KAFKA | "localhost:9092" | Адрес Kafka |
| VERDI_KAFKA_TOPIC | "commandevents" | Название топика для событий |
| VERDI_KAFKA_AUTH_USER | "" | Название учетной записи Kafka. Если название не указано, то настройки авторизации не будут применены. |
| VERDI_KAFKA_AUTH_PASSWORD | "" | Пароль учетной записи Kafka. |
| VERDI_KAFKA_AUTH_PRINCIPAL | "" | Principal учетной записи Kafka в Kerberos(в случае соединения с kafka через Kerberos). |
| VERDI_KAFKA_AUTH_KEYTAB_PATH | "" | Путь до keytab-файла (в случае соединения с kafka через Kerberos). |
| VERDI_KAFKA_AUTH_TRUSTSTORE_LOCATION | "" | Путь до хранилища сертификатов (Java key store). Если путь не указан, то сертификат применяться не будет. |
| VERDI_KAFKA_AUTH_TRUSTSTORE_PASSWORD | "" | Пароль к хранилищу сертификатов. |
| VERDI_KAFKA_AUTH_MODE | "static" | Режим аутентификации: static - одна учетная запись на все запросы, mapping - учетная запись зависит от запроса |
| VERDI_KAFKA_AUTH_CONFIG | "" | Настройки для аутентификации: если AuthMode = mapping, то необходим JSON с List[KafkaAuthConfig]. Переменная соответствует полю authConfig из KafkaAuthSettings. |
| VERDI_KAFKA_AUTH_CACHE_SIZE | Максимальный размер кеша для Kafka producer (количество активных соединений). | |
| VERDI_KAFKA_CONNECTION_CHECK_TEST_MESSAGES_INTERVAL | 4 minutes | Применяется только для producer-ов со способом аутентификации kerberos. Интервал отправки тестовых сообщений кафки в топик connectionCheck.testMessagesTopicName. Тестовые сообщения (null, service producer test) отправляются регулярно с этим интервалом. |
| VERDI_KAFKA_CONNECTION_CHECK_INTERVAL | 60 seconds | Применяется только для producer-ов со способом аутентификации kerberos. Интервал проверки того, сколько тестовых сообщений было отправлено за данный период. Если количество сообщений за этот период равно количеству сообщений за прошлый период, то начинается отсчет периода без сообщений. |
| VERDI_KAFKA_CONNECTION_CHECK_FAILED_AFTER_INTERVAL | 5 minutes | Применяется только для producer-ов со способом аутентификации kerberos. Максимальная продолжительность периода без успешно отправленных тестовых сообщений. По ее достижении сервис будет объявлен больным. |
| VERDI_KAFKA_AUTH_CACHE_TTL | Время жизни Kafka producer в кеше. | |
| VERDI_COMMAND_STORAGE_UPDATE_PERIOD | 1 minutes | Время кэширования данных по командам из CommandDiscovery |
| VERDI_SERVICE_DISCOVERY_UPDATE_PERIOD | 30 seconds | Время кэширования данных по сервисам из ServiceDiscovery |
| VERDI_ALLOW_INTERNAL_COMMANDS | true | Можно ли сервису отправлять внутрисистемные команды |
| VERDI_CONSIDER_ALL_COMMANDS_AS_INTERNAL | false | Флаг, определяющий будут ли все обращения в другие сервисы являться внутренними (т.е. не требовать авторизацию). Детальное описание механизма: Внутренние команды. |
| VERDI_CONSUL_CONNECTION_MAX_RETRY | 5 | Максимальное количество попыток подключений к Consul |
| VERDI_CONSUL_CONNECTION_RETRY_DELAY | 1 seconds | Таймаут между неудачными попытками подключения к Consul |
| VERDI_HOST | "localhost" | Адрес текущего инстанса сервиса, который будет виден через ServiceDiscovery |
| DB_JDBC_URL | "jdbc:postgresql://localhost:5432/buzzer-subscription" | Адрес базы данных. Можно использовать вместо DB_HOST, DB_PORT и DB_NAME |
| DB_HOST | Хост сервера базы данных | |
| DB_PORT | Порт сервера базы данных | |
| DB_NAME | Название базы данных | |
| DB_USER | Пользователь базы данных | |
| DB_PASSWORD | Пароль для пользователя базы данных | |
| DB_THREADS | 10 | Количество потоков в пуле потоков для соединения с БД |
| DB_QUEUE_SIZE | 300 | Размер очереди для действий базы данных, которые не могут быть выполнены немедленно, когда все потоки заняты. За пределами этого значения новые действия немедленно завершаются неудачей |
| DB_CONN_MAX | 10 | Максимальное количество одновременных подключений к БД |
| DB_CONN_TIMEOUT | 20 second | Максимальное время ожидания ответа для соединения к БД. Если это время превышено, а соединение не становится доступным, будет брошено исключение SQLException. 1000 мс — минимальное значение. |
| DB_ISOLATION | "READ_COMMITTED" | Уровень изоляции транзакций для новых подключений. Допустимые значения: NONE, READ_COMMITTED, READ_UNCOMMITTED, REPEATABLE_READ, SERIALIZABLE. |
| DB_READONLY | false | Read-only SQL транзакция может изменять только временные таблицы. Этот параметр управляет статусом «только для чтения» по умолчанию для каждой новой транзакции. |
| DB_CONN_MIN | = DB_THREADS | Минимальное количество одновременных подключений к БД |
| DB_VALIDATION_TIMEOUT | 1 seconds | Максимальное время, в течение которого соединение будет проверяться на работоспособность. 1000 мс — минимальное значение. |
| DB_IDLE_TIMEOUT | 10 minutes | Максимальное время, в течение которого соединению разрешено простаивать в пуле. Значение 0 означает, что простаивающие соединения никогда не удаляются из пула. |
| DB_MAX_LIFETIME | 30 minutes | Максимальное время жизни соединения в пуле. Когда простаивающее соединение достигает этого времени ожидания, даже если оно недавно использовалось, оно будет удалено из пула. Значение 0 указывает на отсутствие максимального срока службы. |
| DB_INITIALIZATION_FAIL_FAST | false | Deprecated, начиная с версии Slick 3.3.0. Определяет, будет ли пул «быстро выходить из строя», если пул не может быть успешно заполнен начальными соединениями. Если соединения не могут быть созданы во время запуска пула, будет выдано исключение RuntimeException. Это свойство не имеет никакого эффекта, если minConnections равно 0. |
| DB_LEAK_DETECTION_THRESHOLD | 0 | Время, в течение которого соединение может находиться вне пула, прежде чем будет зарегистрировано сообщение, указывающее на возможную утечку соединения. Значение 0 означает, что обнаружение утечек отключено. Наименьшее приемлемое значение для включения обнаружения утечек составляет 10 с. |
| DB_CONNECTION_TEST_QUERY | "SELECT 1" | Выражение, которое будет выполнено непосредственно перед получением соединения из пула для проверки того, что соединение с базой данных все еще активно. Оно зависит от базы данных и должно представлять собой запрос, требующий минимальной обработки базой данных (например, «VALUES 1»). Если этот параметр не установлен, вместо него используется метод JDBC4 Connection.isValid(). |
| DB_AUTO_COMMIT | boolean | Это свойство определяет то, как будут вести себя по умолчанию возвращаемые соединения относительно autocommit-а. |
| DB_SCHEMA | string | Устанавливает schema по умолчанию |
| DB_ISOLATE_INTERNAL_QUERIES | boolean | Определяет то, изолируются ли с помощью транзакций внутренние запросы пула (например запрос connection alive test). Свойство применяется только если autoCommit выключен. |
| DB_INITIALIZATION_FAIL_TIMEOUT | int | Работает, начиная с версии Slick 3.3.0. Определяет, будет ли пул «быстро выходить из строя», если пул не может быть успешно заполнен начальными соединениями. Любое положительное число считается числом миллисекунд для попытки получить начальное соединение;поток приложения будет заблокирован в течение этого периода. Если соединение не может быть получено до истечения этого времени, будет брошено исключение. Данный таймаут применяется после периода connectionTimeout. Если значение равно нулю (0),HikariCP попытается получить и проверить подключение. Если соединение получено, но проверка не пройдена, будет брошено исключение, и пул не будет запущен. Однако, если соединение не может быть получено, пул запустится, но последующие попытки получить соединение могут потерпеть неудачу. Значение меньше нуля пройдет любую первоначальную попытку подключения, и пул немедленно запустится, пытаясь получить соединения в фоновом режиме. Следовательно, последующие попытки получить соединение могут потерпеть неудачу. |
| DB_REGISTER_MBEANS | false | Зарегистрированы ли JMX Management Beans («MBeans») |
| VERDI_COMMANDS_HTTP_RETRY_ATTEMPTS | 5 | Поле attempts из RetrySettings |
| VERDI_COMMANDS_HTTP_RETRY_DELAY | "5 seconds" | Поле delay из RetrySettings |
| VERDI_COMMANDS_HTTP_RETRY_KIND | "OnSomeExceptions(ConnectException)" | CommandResultRetryConditionKind |
| CHUNK_SIZE | 512 | Размер батчей, которыми происходит обработка стримов userId подписанных на событие пользователей |
| GROUP_CACHE_TTL | 300 | Количество секунд, которое маппинг группы (groupId) к ее участниками (userId) хранится в кэше |
| SERVER_AUTHORIZER_KIND | "authzforce" | Вид авторизатора, который используется в сервисе. Допустимые значения: "authzforce", "oberto". При указании неизвестного значения будет использовано значение по-умолчанию. |
| AUTHZFORCE_ADDR | "http://localhost:8080/authzforce-ce" | Адрес AuthZforce server |
| AUTHZFORCE_DOMAIN | "" | Доступный DomainID в AuthZforce server |
| AUTHZFORCE_CONNECT_TIMEOUT | "5 seconds" | Таймаут подключения к authzforce |
| JOURNAL_MODE | string | нет |
| JOURNAL_TOPIC | string | да, если переменная JOURNAL_MODE = WriteToTopic |
Команды сервиса Buzzer-subscription
В качестве тела команд сервис всегда ожидает CommandRequest. В описании команд указано описание поля payload для CommandRequest и путь для отправки команды в сам сервис (не в ApiGateway).
В сервисе реализованы следующие команды:
- CreateEventSettings
- GetEventSettings
- UpdateEventSettings
- DeleteEventSettings
- ListEventSettings
- SearchEventSettings
- CreateSubscription
- GetSubscription
- UpdateSubscription
- DeleteSubscription
- ListSubscription
- CreateGroupSubscription
- ListGroupSubscription
- DeleteGroupSubscription
- UpdateGroupSubscription
- GetGroupSubscription
Список реализованных в сервисе команд, моделей EntityType и действий Actions, которые можно использовать при настройке
авторизации.
Не все поля EntityType доступны для использования в настройке авторизации.
Если указан прочерк "-", то данное значение не влияет на авторизацию:
- если не указан Action, то никакой Action не проверяется (= без авторизации)
- если не указан EntityType, то на авторизацию влияет только Action
| Название команды | EntityType | Actions |
|---|---|---|
| createEventSettingsBuzzer-subscription | - | - |
| getEventSettingsBuzzer-subscription | - | - |
| updateEventSettingsBuzzer-subscription | - | - |
| deleteEventSettingsBuzzer-subscription | - | - |
| listEventSettingsBuzzer-subscription | - | - |
| searchEventSettingsBuzzer-subscription | - | - |
| createGroupSubscriptionBuzzer-subscription | GroupSubscription | createGroupSubscription |
| listGroupSubscriptionBuzzer-subscription | GroupSubscription | listGroupSubscription |
| deleteGroupSubscriptionBuzzer-subscription | GroupSubscription | deleteGroupSubscription |
| updateGroupSubscriptionBuzzer-subscription | GroupSubscription | updateGroupSubscription |
| getGroupSubscriptionBuzzer-subscription | GroupSubscription | getGroupSubscription |
| createSubscriptionBuzzer-subscription | - | - |
| getSubscriptionBuzzer-subscription | - | - |
| updateSubscriptionBuzzer-subscription | - | - |
| deleteSubscriptionBuzzer-subscription | - | - |
CreateEventSettings (Buzzer-subscription)
Передаем JSON с данными для создания настроек события
{
"entityType": "Document",
"eventType": "Create",
"enabled": true,
"notificationCode": "DocumentCreated"
}
Получаем Id настроек события
"4345011c-c579-4e1b-b84b-94e4eed2f2da"
Создать настройки события из данных EventSettingsDTO.
Гарантируется уникальность для набора полей: entityType, eventType.
В ответ приходит Id настроек события.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Input: EventSettingsDTO
- Output: UUID
| Команда | Путь |
|---|---|
| createEventSettingsBuzzer-subscription | HTTP POST "/createEventSettings" |
GetEventSettings (Buzzer-subscription)
Передаем Id настроек события
"ed2de80e-0289-43c2-a944-70e9a4277d36"
Получаем JSON с настройками события
{
"id": "ed2de80e-0289-43c2-a944-70e9a4277d36",
"entityType": "Employee",
"eventType": "Create",
"enabled": true,
"notificationCode": "EmployeeCreated",
"version": 1
}
Возвращает настройки события EventSettings по Id.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Input: UUID
- Output: EventSettings
| Команда | Путь |
|---|---|
| getEventSettingsBuzzer-subscription | HTTP POST "/getEventSettings" |
UpdateEventSettings (Buzzer-subscription)
Передаем JSON с настройками события
{
"id": "0b27209a-1931-4cd7-a19a-7739bd1dfb4f",
"entityType": "DocumentFile",
"eventType": "Delete",
"enabled": true,
"notificationCode": "DocumentFileDeleted",
"version": 1
}
Получаем результат
1
Обновить существующие настройки события из EventSettings.
Если значение, передаваемое в version, отличается от текущего, обновление не происходит.
При успешном обновлении version формы увеличивается на единицу.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Input: EventSettings
- Output: Int
| Команда | Путь |
|---|---|
| updateEventSettingsBuzzer-subscription | HTTP POST "/updateEventSettings" |
DeleteEventSettings (Buzzer-subscription)
Передаем Id настроек события
"0ccd05ac-50c0-4e7e-906b-6893eaa8d9de"
Получаем результат
1
Удалить существующие настройки события по Id.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Input: UUID
- Output: Int
| Команда | Путь |
|---|---|
| deleteEventSettingsBuzzer-subscription | HTTP POST "/deleteEventSettings" |
ListEventSettings (Buzzer-subscription)
Получаем JSON со списком всех существующих настроек событий
[
{
"id": "f3287c8e-efa5-45d9-ba38-76ef78f09fe0",
"entityType": "Document",
"eventType": "Delete",
"enabled": true,
"notificationCode": "DocumentDeleted",
"version": 1
},
{
"id": "34c919ae-a73c-4705-8833-0a1b0434e04c",
"entityType": "Employee",
"eventType": "Update",
"enabled": false,
"notificationCode": "EmployeeUpdated",
"version": 2
}
]
Возвращает список всех существующих настроек событий.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Input: -
- Output: List[EventSettings]
| Команда | Путь |
|---|---|
| listEventSettingsBuzzer-subscription | HTTP POST "/listEventSettings" |
SearchEventSettings (Buzzer-subscription)
Передаем поисковой запрос
{
"query": "eventType",
"context": {
"eventType": "Delete"
},
"sorting": {
"fieldName": "eventType",
"order": "Asc"
},
"paging": {
"page": 2,
"count": 10
}
}
Получаем JSON со списком отфильтрованных настроек событий
{
"items": [
{
"id": "f3287c8e-efa5-45d9-ba38-76ef78f09fe0",
"entityType": "Document",
"eventType": "Delete",
"enabled": true,
"notificationCode": "DocumentDeleted",
"version": 1
},
{
"id": "34c919ae-a73c-4705-8833-0a1b0434e04c",
"entityType": "Employee",
"eventType": "Update",
"enabled": false,
"notificationCode": "EmployeeUpdated",
"version": 2
}
],
"total": 12
}
Возвращает отфильтрованный список настроек событий.
Доступные для сортировки поля:
- enabled
- eventType
- notificationCode
- entityType
Доступные для фильтрации поля и виды фильтров по ним:
| Поле | Виды фильтров |
|---|---|
| id | InSetQuery |
| eventType | InSetQuery, LikeQuery |
| notificationCode | InSetQuery, LikeQuery |
| entityType | InSetQuery, LikeQuery |
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Input: Search
- Output: Page[EventSettings]
| Команда | Путь |
|---|---|
| searchEventSettingsBuzzer-subscription | HTTP POST "/searchEventSettings" |
CreateGroupSubscription (Buzzer-subscription)
Передаем JSON с данными для создания подписки
{
"entityType": "Document",
"entityId": "fd460be0-99f6-4cfc-95eb-2e3f6a847ef5",
"eventType": "Create",
"enabled": true,
"groupId": "someGroupId"
}
Получаем Id подписки
"d053e6c2-877e-4dc4-83c6-d7f80911e1f1"
Создать подписку для всех userId из группы с указанным groupId из
данных GroupSubscriptionDTO.
Гарантируется уникальность для набора полей: entityType, entityId, eventType, groupId.
Поле eventType опциональное, в случае его отсутствия подписка будет генерировать уведомления на все типы событий.
В ответ приходит Id подписки.
Поддерживается только синхронный вызов.
Результат выполнения команды журналируется.
- Input: GroupSubscriptionDTO
- Output: UUID
| Команда | Путь |
|---|---|
| createGroupSubscriptionBuzzer-subscription | HTTP POST "/createGroupSubscription" |
GetGroupSubscription (Buzzer-subscription)
Передаем UUID с id подписки
Получаем JSON с данными для о подписке
{
"id": "ed3fa199-5576-4e83-b54c-15cfd116aaaf",
"entityType": "Document",
"entityId": "fd460be0-99f6-4cfc-95eb-2e3f6a847ef5",
"eventType": "Create",
"enabled": true,
"groupId": "someGroupId",
"version": 2
}
Получить подписку с указанным id в формате GroupSubscription.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Input: UUID
- Output: GroupSubscription
| Команда | Путь |
|---|---|
| getGroupSubscriptionBuzzer-subscription | HTTP POST "/getGroupSubscription" |
UpdateGroupSubscription (Buzzer-subscription)
Передаем JSON с данными для создания подписки
{
"id": "ed3fa199-5576-4e83-b54c-15cfd116aaaf",
"entityType": "Document",
"entityId": "fd460be0-99f6-4cfc-95eb-2e3f6a847ef5",
"eventType": "Create",
"enabled": true,
"groupId": "someGroupId",
"version": 2
}
Обновить подписку для всех userId из группы с указанным groupId из
данных GroupSubscription.
Гарантируется уникальность для набора полей: entityType, entityId, eventType, groupId.
Поле eventType опциональное, в случае его отсутствия подписка будет генерировать уведомления на все типы событий.
Поддерживается только синхронный вызов.
Результат выполнения команды журналируется.
- Input: GroupSubscription
- Output: -
| Команда | Путь |
|---|---|
| updateGroupSubscriptionBuzzer-subscription | HTTP POST "/updateGroupSubscription" |
DeleteGroupSubscription (Buzzer-subscription)
Передаем id групповой подписки
"d053e6c2-877e-4dc4-83c6-d7f80911e1f1"
Удалить групповую подписку с указанным id.
Поддерживается только синхронный вызов.
Результат выполнения команды журналируется.
- Input: UUID
- Output: -
| Команда | Путь |
|---|---|
| deleteGroupSubscriptionBuzzer-subscription | HTTP POST "/deleteGroupSubscription" |
ListGroupSubscription (Buzzer-subscription)
Получаем JSON со списком всех существующих групповых подписок
[
{
"id": "8eca9dc3-f64c-4169-ac00-94e35f7a77c5",
"entityType": "File",
"entityId": "4de27416-e20d-4883-889c-207527eb724e",
"eventType": "Delete",
"enabled": true,
"groupId": "groupId",
"version": 1
}
]
Возвращает список всех существующих настроек групповых событий.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Input: -
- Output: List[GroupSubscription]
| Команда | Путь |
|---|---|
| listGroupSubscriptionBuzzer-subscription | HTTP POST "/listGroupSubscription" |
CreateSubscription (Buzzer-subscription)
Передаем JSON с данными для создания подписки
{
"entityType": "Document",
"entityId": "fd460be0-99f6-4cfc-95eb-2e3f6a847ef5",
"eventType": "Create",
"enabled": true,
"userId": "fd460be0-99f6-4cfc-95eb-2e3f6a847efb"
}
Получаем Id подписки
"d053e6c2-877e-4dc4-83c6-d7f80911e1f1"
Создать подписки из данных SubscriptionDTO.
Гарантируется уникальность для набора полей: entityType, entityId, eventType, userId.
Поле eventType опциональное, в случае его отсутствия подписка будет генерировать уведомления на все типы событий.
В ответ приходит Id подписки.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Input: SubscriptionDTO
- Output: UUID
| Команда | Путь |
|---|---|
| createSubscriptionBuzzer-subscription | HTTP POST "/createSubscription" |
GetSubscription (Buzzer-subscription)
Передаем Id подписки
"d053e6c2-877e-4dc4-83c6-d7f80911e1f1"
Получаем JSON с подпиской
{
"id": "d053e6c2-877e-4dc4-83c6-d7f80911e1f1",
"entityType": "Document",
"entityId": "fd460be0-99f6-4cfc-95eb-2e3f6a847ef5",
"eventType": "Create",
"enabled": true,
"userId": "fd460be0-99f6-4cfc-95eb-2e3f6a847efa",
"version": 1
}
Возвращает подписку Subscription по Id.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Input: UUID
- Output: Subscription
| Команда | Путь |
|---|---|
| getSubscriptionBuzzer-subscription | HTTP POST "/getSubscription" |
UpdateSubscription (Buzzer-subscription)
Передаем JSON с подпиской
{
"id": "69c33893-b769-4292-8259-3295fe0d7450",
"entityType": "DocumentFile",
"entityId": "a7833b48-aeb6-4048-99fd-e90bf1780b7e",
"eventType": "Create",
"enabled": true,
"userId": "fd460be0-99f6-4cfc-95eb-2e3f6a847efe",
"version": 1
}
Получаем результат
1
Обновить существующую подписку из Subscription.
Если значение, передаваемое в version, отличается от текущего, обновление не происходит.
При успешном обновлении version формы увеличивается на единицу.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Input: Subscription
- Output: Int
| Команда | Путь |
|---|---|
| updateSubscriptionBuzzer-subscription | HTTP POST "/updateSubscription" |
DeleteSubscription (Buzzer-subscription)
Передаем Id подписки
"954855b6-5390-45ca-9280-2746563e6905"
Получаем результат
1
Удалить существующую подписку по Id.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Input: UUID
- Output: Int
| Команда | Путь |
|---|---|
| deleteSubscriptionBuzzer-subscription | HTTP POST "/deleteSubscription" |
ListSubscription (Buzzer-subscription)
Получаем JSON со списком всех существующих подписок
[
{
"id": "69c33893-b769-4292-8259-3295fe0d7450",
"entityType": "Document",
"entityId": "53cc3dec-29c3-4814-a2e7-69f435f74a1f",
"eventType": "Update",
"enabled": true,
"userId": "fd460be0-99f6-4cfc-95eb-2e3f6a847efe",
"version": 2
},
{
"id": "018815b5-6fa3-4b8c-8bec-374bb3c20574",
"entityType": "Organization",
"entityId": "1bce425e-f1ae-4729-a36f-8a16dd6afa58",
"enabled": false,
"userId": "018815b5-6fa3-4b8c-8bec-374bb3c20574",
"version": 1
}
]
Возвращает список всех существующих настроек событий.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Input: -
- Output: List[Subscription]
| Команда | Путь |
|---|---|
| listSubscriptionBuzzer-subscription | HTTP POST "/listSubscription" |
Модели сервиса подписок
EventSettingsDTO (Buzzer-subscription)
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| entityType | String | да | Тип сущности |
| eventType | String | да | Тип события |
| enabled | Boolean | да | Активность подписки |
| notificationCode | String | да | Код уведомления |
EventSettings (Buzzer-subscription)
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | UUID | да | Id настроек события |
| entityType | String | да | Тип сущности |
| eventType | String | да | Тип события |
| enabled | Boolean | да | Активность подписки |
| notificationCode | String | да | Код уведомления |
| version | Int | да | Версия настроек события |
SubscriptionDTO (Buzzer-subscription)
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| entityType | String | да | Тип сущности |
| entityId | String | да | Id сущности |
| eventType | String | нет | Тип события |
| enabled | Boolean | да | Активность подписки |
| userId | UUID | да | Id пользователя |
GroupSubscriptionDTO (Buzzer-subscription)
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| entityType | String | да | Тип сущности |
| entityId | String | да | Id сущности |
| eventType | String | нет | Тип события |
| enabled | Boolean | да | Активность подписки |
| groupId | String | да | Id группы пользователей |
Subscription (Buzzer-subscription)
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | UUID | да | Id подписки |
| entityType | String | да | Тип сущности |
| entityId | String | да | Id сущности |
| eventType | String | нет | Тип события |
| enabled | Boolean | да | Активность подписки |
| userId | UUID | да | Id пользователя |
| version | Int | да | Версия настроек события |
GroupSubscription (Buzzer-subscription)
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | UUID | да | Id подписки |
| entityType | String | да | Тип сущности |
| entityId | String | да | Id сущности |
| eventType | String | нет | Тип события |
| enabled | Boolean | да | Активность подписки |
| groupId | String | да | Id группы пользователей |
| version | Int | да | Версия настроек события |
Buzzer: сервис уведомлений
Сервис получает через Kafka уведомления и перенаправляет их в сервисы отправки. На данный момент реализованы 2 таких сервиса - Buzzer email и Buzzer personal page.
Конфигурирование сервиса уведомлений
Требования к запуску
Для корректной минимальной работы сервиса требуется обязательное подключение к PostgreSQL, Kafka, Consul. Для настройки подключения к ним нужно заполнить обязательные переменные окружения из раздела ниже.
Для нормальной работы сервису дополнительно требуется окружение Verdi: CommandStatus и ApiGateway. В этом случае нужно уделить внимание настройкам, связанным с ServiceDiscovery и CommandDiscovery.
Список переменных окружения сервиса уведомлений
| Переменная | Значение по умолчанию | Описание |
|---|---|---|
| SERVER_PORT | 8080 | Порт для HttpListener |
| CONSUMER_TOPIC | "notification" | Название топика для уведомлений к отправке, поступающих из других сервисов |
| CONSUMER_SEND_NOTIFICATION_COMMAND_TOPIC | "send_notification_command" | Название топика для Verdi-команды отправки уведомления |
| CONSUMER_GROUP | "notification" | Название группы для чтения из топиков Kafka |
| PASSWORD_RECOVERY_TOPIC | "email" | Kafka topic используемый для отправки писем с восстановлением пароля. При старте приложения этим значением обновляется поле topic сущности sending с id='password-recovery' если оно отличается. |
| EMAIL_CONFIRM_TOPIC | "email" | Аналогично PASSWORD_RECOVERY_TOPIC, но для верификации электронной почты |
| VERDI_HOST | "localhost" | Адрес текущего инстанса сервиса, который будет виден через ServiceDiscovery |
| VERDI_TTL | 30 seconds | Период после последней отправки health check, в течение которого ServiceDiscovery считает данный сервис живым. |
| VERDI_HEALTH_CHECK | 10 seconds | Периодичность отправки health check в ServiceDiscovery |
| VERDI_CONSUL | http://localhost:8500 | Адрес Consul |
| VERDI_CONSUL_AUTH_USER | "" | Название учетной записи Сonsul. Если название не указано, то настройки авторизации не будут применены. |
| VERDI_CONSUL_AUTH_PASSWORD | "" | Пароль учетной записи Сonsul. |
| VERDI_KAFKA | "localhost:9092" | Адрес брокера Kafka. |
| VERDI_KAFKA_TOPIC | "commandevents" | Название топика для событий |
| VERDI_KAFKA_AUTH_USER | "" | Название учетной записи Kafka. Если название не указано, то настройки авторизации не будут применены. |
| VERDI_KAFKA_AUTH_PASSWORD | "" | Пароль учетной записи Kafka. |
| VERDI_KAFKA_AUTH_PRINCIPAL | "" | Principal учетной записи Kafka в Kerberos(в случае соединения с kafka через Kerberos). |
| VERDI_KAFKA_AUTH_KEYTAB_PATH | "" | Путь до keytab-файла (в случае соединения с kafka через Kerberos). |
| VERDI_KAFKA_AUTH_TRUSTSTORE_LOCATION | "" | Путь до хранилища сертификатов (Java key store). Если путь не указан, то сертификат применяться не будет. |
| VERDI_KAFKA_AUTH_TRUSTSTORE_PASSWORD | "" | Пароль к хранилищу сертификатов. |
| VERDI_KAFKA_AUTH_MODE | "static" | Режим аутентификации: static - одна учетная запись на все запросы, mapping - учетная запись зависит от запроса |
| VERDI_KAFKA_AUTH_CONFIG | "" | Настройки для аутентификации: если AuthMode = mapping, то необходим JSON с List[KafkaAuthConfig]. Переменная соответствует полю authConfig из KafkaAuthSettings. |
| VERDI_KAFKA_AUTH_CACHE_SIZE | Максимальный размер кеша для Kafka producer (количество активных соединений). | |
| VERDI_KAFKA_CONNECTION_CHECK_TEST_MESSAGES_INTERVAL | 4 minutes | Применяется только для producer-ов со способом аутентификации kerberos. Интервал отправки тестовых сообщений кафки в топик connectionCheck.testMessagesTopicName. Тестовые сообщения (null, service producer test) отправляются регулярно с этим интервалом. |
| VERDI_KAFKA_CONNECTION_CHECK_INTERVAL | 60 seconds | Применяется только для producer-ов со способом аутентификации kerberos. Интервал проверки того, сколько тестовых сообщений было отправлено за данный период. Если количество сообщений за этот период равно количеству сообщений за прошлый период, то начинается отсчет периода без сообщений. |
| VERDI_KAFKA_CONNECTION_CHECK_FAILED_AFTER_INTERVAL | 5 minutes | Применяется только для producer-ов со способом аутентификации kerberos. Максимальная продолжительность периода без успешно отправленных тестовых сообщений. По ее достижении сервис будет объявлен больным. |
| VERDI_KAFKA_AUTH_CACHE_TTL | Время жизни Kafka producer в кеше. | |
| VERDI_COMMAND_STORAGE_UPDATE_PERIOD | 1 minutes | Время кэширования данных по командам из CommandDiscovery |
| VERDI_SERVICE_DISCOVERY_UPDATE_PERIOD | 30 seconds | Время кэширования данных по сервисам из ServiceDiscovery |
| VERDI_ALLOW_INTERNAL_COMMANDS | true | Можно ли сервису отправлять внутрисистемные команды |
| VERDI_CONSIDER_ALL_COMMANDS_AS_INTERNAL | false | Флаг, определяющий будут ли все обращения в другие сервисы являться внутренними (т.е. не требовать авторизацию). Детальное описание механизма: Внутренние команды. |
| VERDI_CONSUL_CONNECTION_MAX_RETRY | 5 | Максимальное количество попыток подключений к Consul |
| VERDI_CONSUL_CONNECTION_RETRY_DELAY | 1 seconds | Таймаут между неудачными попытками подключения к Consul |
| DB_JDBC_URL | Адрес базы данных. Можно использовать вместо DB_HOST, DB_PORT и DB_NAME | |
| DB_HOST | Хост сервера базы данных | |
| DB_PORT | Порт сервера базы данных | |
| DB_NAME | Название базы данных | |
| DB_USER | Пользователь базы данных | |
| DB_PASSWORD | Пароль для пользователя базы данных | |
| DB_THREADS | 10 | Количество потоков в пуле потоков для соединения с БД |
| DB_QUEUE_SIZE | 300 | Размер очереди для действий базы данных, которые не могут быть выполнены немедленно, когда все потоки заняты. За пределами этого значения новые действия немедленно завершаются неудачей |
| DB_CONN_MAX | 10 | Максимальное количество одновременных подключений к БД |
| DB_CONN_TIMEOUT | 20 second | Максимальное время ожидания ответа для соединения к БД. Если это время превышено, а соединение не становится доступным, будет брошено исключение SQLException. 1000 мс — минимальное значение. |
| DB_ISOLATION | "READ_COMMITTED" | Уровень изоляции транзакций для новых подключений. Допустимые значения: NONE, READ_COMMITTED, READ_UNCOMMITTED, REPEATABLE_READ, SERIALIZABLE. |
| DB_READONLY | false | Read-only SQL транзакция может изменять только временные таблицы. Этот параметр управляет статусом «только для чтения» по умолчанию для каждой новой транзакции. |
| DB_CONN_MIN | = DB_THREADS | Минимальное количество одновременных подключений к БД |
| DB_VALIDATION_TIMEOUT | 1 seconds | Максимальное время, в течение которого соединение будет проверяться на работоспособность. 1000 мс — минимальное значение. |
| DB_IDLE_TIMEOUT | 10 minutes | Максимальное время, в течение которого соединению разрешено простаивать в пуле. Значение 0 означает, что простаивающие соединения никогда не удаляются из пула. |
| DB_MAX_LIFETIME | 30 minutes | Максимальное время жизни соединения в пуле. Когда простаивающее соединение достигает этого времени ожидания, даже если оно недавно использовалось, оно будет удалено из пула. Значение 0 указывает на отсутствие максимального срока службы. |
| DB_INITIALIZATION_FAIL_FAST | false | Deprecated, начиная с версии Slick 3.3.0. Определяет, будет ли пул «быстро выходить из строя», если пул не может быть успешно заполнен начальными соединениями. Если соединения не могут быть созданы во время запуска пула, будет выдано исключение RuntimeException. Это свойство не имеет никакого эффекта, если minConnections равно 0. |
| DB_LEAK_DETECTION_THRESHOLD | 0 | Время, в течение которого соединение может находиться вне пула, прежде чем будет зарегистрировано сообщение, указывающее на возможную утечку соединения. Значение 0 означает, что обнаружение утечек отключено. Наименьшее приемлемое значение для включения обнаружения утечек составляет 10 с. |
| DB_CONNECTION_TEST_QUERY | "SELECT 1" | Выражение, которое будет выполнено непосредственно перед получением соединения из пула для проверки того, что соединение с базой данных все еще активно. Оно зависит от базы данных и должно представлять собой запрос, требующий минимальной обработки базой данных (например, «VALUES 1»). Если этот параметр не установлен, вместо него используется метод JDBC4 Connection.isValid(). |
| DB_AUTO_COMMIT | boolean | Это свойство определяет то, как будут вести себя по умолчанию возвращаемые соединения относительно autocommit-а. |
| DB_SCHEMA | string | Устанавливает schema по умолчанию |
| DB_ISOLATE_INTERNAL_QUERIES | boolean | Определяет то, изолируются ли с помощью транзакций внутренние запросы пула (например запрос connection alive test). Свойство применяется только если autoCommit выключен. |
| DB_INITIALIZATION_FAIL_TIMEOUT | int | Работает, начиная с версии Slick 3.3.0. Определяет, будет ли пул «быстро выходить из строя», если пул не может быть успешно заполнен начальными соединениями. Любое положительное число считается числом миллисекунд для попытки получить начальное соединение;поток приложения будет заблокирован в течение этого периода. Если соединение не может быть получено до истечения этого времени, будет брошено исключение. Данный таймаут применяется после периода connectionTimeout. Если значение равно нулю (0),HikariCP попытается получить и проверить подключение. Если соединение получено, но проверка не пройдена, будет брошено исключение, и пул не будет запущен. Однако, если соединение не может быть получено, пул запустится, но последующие попытки получить соединение могут потерпеть неудачу. Значение меньше нуля пройдет любую первоначальную попытку подключения, и пул немедленно запустится, пытаясь получить соединения в фоновом режиме. Следовательно, последующие попытки получить соединение могут потерпеть неудачу. |
| DB_REGISTER_MBEANS | false | Зарегистрированы ли JMX Management Beans («MBeans») |
| VERDI_COMMANDS_HTTP_RETRY_ATTEMPTS | 5 | Поле attempts из RetrySettings |
| VERDI_COMMANDS_HTTP_RETRY_DELAY | "5 seconds" | Поле delay из RetrySettings |
| VERDI_COMMANDS_HTTP_RETRY_KIND | "OnSomeExceptions(ConnectException)" | CommandResultRetryConditionKind |
Список команд сервиса уведомлений
В сервисе реализованы следующие команды:
- Регистрация сервиса отправки
- Получение сервиса отправки
- Получение списка сервисов отправки
- Обновление сервиса отправки
- Отмена регистрации сервиса отправки
- Создание пользовательской настройки
- Получение пользовательской настройки
- Получение списка пользовательских настроек
- Поиск пользовательских настроек
- Обновление пользовательской настройки
- Удаление пользовательской настройки
- Создание системной настройки
- Получение системной настройки
- Получение системных списка настроек
- Поиск системных настроек
- Обновление системной настройки
- Удаление системной настройки
- Отправить уведомление
CreateSendingBuzzer
Передаем JSON с описанием сервиса отправки
{
"id": "profile",
"topic": "personal-page",
"version": 1
}
Получаем код сервиса
"profile"
Зарегистрировать сервис отправки.
Имя вызова команды: createSendingBuzzer.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: Sending.
- На выходе: String
GetSendingBuzzer
Передаем код сервиса отправки
"profile"
Получаем JSON с описанием сервиса отправки
{
"id": "profile",
"topic": "personal-page",
"version": 1
}
Получить описание сервиса отправки.
Имя вызова команды: getSendingBuzzer.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: String
- На выходе: Sending
ListSendingBuzzer
Получаем JSON со списком всех существующих сервисов отправки
[
{
"id": "profile",
"topic": "personal-page",
"version": 1
},
{
"id": "email",
"topic": "email",
"version": 1
}
]
Возвращает список всех зарегистрированных сервисов отправки
Имя вызова команды: listSendingBuzzer.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: -
- На выходе: List[Sending]
UpdateSendingBuzzer
Передаем JSON с описанием сервиса отправки
{
"id": "profile",
"topic": "personal-page",
"version": 1
}
Получаем результат
1
Обновить существующий сервис отправки.
Если значение, передаваемое в version, отличается от текущего, обновление не происходит.
При успешном обновлении version формы увеличивается на единицу.
Имя вызова команды: updateSendingBuzzer.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: Sending
- На выходе: 1 - в случае успеха, 0 - при неудаче
DeleteSendingBuzzer
Передаем код сервиса отправки
"email"
Получаем результат
1
Отменить регистрацию сервиса отправки.
Имя вызова команды: deleteSendingBuzzer.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: String
- На выходе: 1 - в случае успеха, 0 - при неудаче
CreateSettingBuzzer
Передаем JSON с данными для создания пользовательских настроек уведомления
{
"code": "buzzerNotification",
"sendingIds": [
"profile"
]
}
Получаем ID новой настройки
"4345011c-c579-4e1b-b84b-94e4eed2f2da"
Создать пользовательские настройки уведомления.
Имя вызова команды: createSettingBuzzer.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: SettingCreateDTO.
- На выходе: UUID
GetSettingBuzzer
Передаем ID настроек
"ed2de80e-0289-43c2-a944-70e9a4277d36"
Получаем JSON с настройками уведомления
{
"id": "e3901923-21dc-4f95-98d0-cb2ea29abe1e",
"code": "buzzerNotification",
"sendingIds": [
"profile",
"email"
],
"userId": "016d04f4-fc1a-4629-808b-e5e1c35bb348",
"version": 1
}
Получить настройки уведомления.
Имя вызова команды: getSettingBuzzer.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: UUID
- На выходе: Setting
ListSettingBuzzer
Получаем JSON со списком всех пользовательских настроек уведомлений
[
{
"id": "e3901923-21dc-4f95-98d0-cb2ea29abe1e",
"code": "buzzerNotification",
"sendingIds": [
"profile",
"email"
],
"userId": "016d04f4-fc1a-4629-808b-e5e1c35bb348",
"version": 1
}
]
Возвращает список всех существующих пользовательских настроек уведомлений.
Имя вызова команды: listSettingBuzzer.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: -
- На выходе: List[Setting]
SearchSettingBuzzer
Передаем поисковой запрос
{
"query": "sendingid",
"context": {
"sendingid": "profile"
},
"sorting": {
"fieldName": "code",
"order": "Asc"
},
"paging": {
"page": 1,
"count": 10
}
}
Получаем JSON со списком отфильтрованных пользовательских настроек уведомлений
{
"items": [
{
"id": "e3901923-21dc-4f95-98d0-cb2ea29abe1e",
"code": "buzzerNotification",
"sendingIds": [
"profile",
"email"
],
"userId": "016d04f4-fc1a-4629-808b-e5e1c35bb348",
"version": 2
},
{
"id": "ec44f7d8-4e8b-4259-8c86-2cd9b2472451",
"code": "buzzerNotification2",
"sendingIds": [
"profile"
],
"userId": "016d04f4-fc1a-4629-808b-e5e1c35bb348",
"version": 1
}
],
"total": 2
}
Возвращает отфильтрованный список пользовательских настроек уведомлений. Доступные для фильтрации поля и виды фильтров по ним:
| Поле | Виды фильтров |
|---|---|
| id | InSetQuery |
| code | InSetQuery, LikeQuery |
| sendingid | InSetQuery |
Доступные для сортировки поля:
- code
Имя вызова команды: searchSettingBuzzer.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
UpdateSettingBuzzer
Передаем JSON с пользовательскими настройками уведомления
{
"id": "e3901923-21dc-4f95-98d0-cb2ea29abe1e",
"code": "buzzerNotification",
"sendingIds": [
"profile",
"email"
],
"version": 1
}
Получаем результат
1
Обновить существующие пользовательские настройки уведомления.
Если значение, передаваемое в version, отличается от текущего, обновление не происходит.
При успешном обновлении version формы увеличивается на единицу.
Имя вызова команды: updateSettingBuzzer.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: SettingUpdateDTO
- На выходе: 1 - в случае успеха, 0 - при неудаче
DeleteSettingBuzzer
Передаем ID пользовательских настроек уведомления
"0ccd05ac-50c0-4e7e-906b-6893eaa8d9de"
Получаем результат
1
Удалить существующие пользовательские настройки события по их ID.
Имя вызова команды: deleteSettingBuzzer.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: UUID
- На выходе: 1 - в случае успеха, 0 - при неудаче
CreateSystemSettingBuzzer
Передаем JSON с данными для создания системных настроек
{
"code": "buzzerNotification",
"sendingIds": [
"profile",
"email"
]
}
Получаем ID новой системной настройки
"4345011c-c579-4e1b-b84b-94e4eed2f2da"
Создать системные настройки уведомления.
Имя вызова команды: createSystemSettingBuzzer.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: SettingCreateDTO.
- На выходе: UUID
GetSystemSettingBuzzer
Передаем ID системных настроек
"ed2de80e-0289-43c2-a944-70e9a4277d36"
Получаем JSON с системными настройками уведомления
{
"id": "e3901923-21dc-4f95-98d0-cb2ea29abe1e",
"code": "buzzerNotification",
"sendingIds": [
"profile",
"email"
],
"userId": null,
"version": 1
}
Получить системные настройки уведомления.
Имя вызова команды: getSystemSettingBuzzer.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: UUID
- На выходе: Setting
ListSystemSettingBuzzer
Получаем JSON со списком всех системных настроек уведомлений
[
{
"id": "e3901923-21dc-4f95-98d0-cb2ea29abe1e",
"code": "buzzerNotification",
"sendingIds": [
"profile",
"email"
],
"userId": null,
"version": 1
}
]
Возвращает список всех существующих системных настроек уведомлений.
Имя вызова команды: listSystemSettingBuzzer.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: -
- На выходе: List[Setting]
SearchSystemSettingBuzzer
Передаем поисковой запрос
{
"query": "sendingid",
"context": {
"sendingid": "profile"
},
"sorting": {
"fieldName": "code",
"order": "Asc"
},
"paging": {
"page": 1,
"count": 10
}
}
Получаем JSON со списком отфильтрованных системных настроек уведомлений
{
"items": [
{
"id": "e3901923-21dc-4f95-98d0-cb2ea29abe1e",
"code": "buzzerNotification",
"sendingIds": [
"profile",
"email"
],
"userId": null,
"version": 2
},
{
"id": "ec44f7d8-4e8b-4259-8c86-2cd9b2472451",
"code": "buzzerNotification2",
"sendingIds": [
"profile"
],
"userId": null,
"version": 1
}
],
"total": 2
}
Возвращает отфильтрованный список системных настроек уведомлений. Доступные для фильтрации поля и виды фильтров по ним:
| Поле | Виды фильтров |
|---|---|
| id | InSetQuery |
| code | InSetQuery, LikeQuery |
| sendingid | InSetQuery |
Доступные для сортировки поля:
- code
Имя вызова команды: searchSystemSettingBuzzer.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
UpdateSystemSettingBuzzer
Передаем JSON с системными настройками уведомления
{
"id": "e3901923-21dc-4f95-98d0-cb2ea29abe1e",
"code": "buzzerNotification",
"sendingIds": [
"profile",
"email"
],
"version": 1
}
Получаем результат
1
Обновить существующие системные настройки уведомления.
Если значение, передаваемое в version, отличается от текущего, обновление не происходит.
При успешном обновлении version формы увеличивается на единицу.
Имя вызова команды: updateSystemSettingBuzzer.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: SettingUpdateDTO
- На выходе: 1 - в случае успеха, 0 - при неудаче
DeleteSystemSettingBuzzer
Передаем ID системных настроек уведомления
"0ccd05ac-50c0-4e7e-906b-6893eaa8d9de"
Получаем результат
1
Удалить существующие системные настройки события по ID.
Имя вызова команды: deleteSystemSettingBuzzer.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: UUID
- На выходе: 1 - в случае успеха, 0 - при неудаче
SendNotification
Передаем данные отправляемого уведомления
{
"code": "buzzerNotification",
"userId": "016d04f4-fc1a-4629-808b-e5e1c35bb348",
"data": {
"field": "value"
}
}
Получаем результат
true
Отправка уведомления пользователю.
Имя вызова команды: sendNotification.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: Notification
- На выходе: true (признак завершения отправки)
Модели сервиса уведомлений
Sending (Buzzer)
Описание сервиса отправки
| Название поля | Тип | Обязательное | Описание |
|---|---|---|---|
| id | uuid | да | Идентификатор сервиса |
| topic | string | да | Очередь сервиса отправки в Kafka, в которую нужно перенаправить уведомление |
| version | number | нет | Версия описания (опциональная, по умолчанию - 1) |
Setting (Buzzer)
Настройка связи уведомления с сервисами отправки
| Название поля | Тип | Обязательное | Описание |
|---|---|---|---|
| id | uuid | да | Идентификатор настройки |
| code | string | да | Код уведомления |
| sendingIds | string[] | да | Список сервисов отправки |
| userId | uuid string | нет | Идентификатор пользователя, для которого определяется настройка. Отсутствует у системных настроек. |
| version | number | да | Версия настройки |
SettingCreateDTO (Buzzer)
Объект для создания настройки связи уведомления с сервисами отправки
| Название поля | Тип | Обязательное | Описание |
|---|---|---|---|
| code | string | да | Код уведомления |
| sendingIds | string[] | да | Список сервисов отправки |
SettingUpdateDTO (Buzzer)
Объект для обновления настройки связи уведомления с сервисами отправки
| Название поля | Тип | Обязательное | Описание |
|---|---|---|---|
| id | uuid | да | Идентификатор настройки |
| code | string | да | Код уведомления |
| sendingIds | string[] | да | Список сервисов отправки |
| version | number | да | Версия настройки |
Command-status: сервис статуса команд
Сервис обеспечивает трассировку выполнения команд и
хранение их промежуточных “текущих” состояний и результатов.
Также он позволяет простым и быстрым способом запрашивать данные
по этим текущим состояниям команд.
Иногда сервис может не успевать обрабатывать все события. Чтобы повысить скорость обработки входящих событий по
командам,
нужно запускать несколько инстансов. Производительность одной ноды и их общее количество подсчитывается индивидуально,
в зависимости от ресурсов на одну ноду и количества партиций в топике (точнее, сколько будет приходиться партиций на одну
ноду).
Например, для 8 CPU и 16gb RAM одна нода может вычитывать около 1500 сообщений в секунду из топика с 10 партициями (
читает все 10 партиций).
Обычно, чем меньше партиций читается одной нодой, тем меньше ядер CPU на нее нужно выделять (например, читает 2
партиции - выделяем 2 CPU).
Конфигурирование Command-status
Требования к запуску Command-status
Запуск локально из консоли с помощью SBT
COMMAND_STATUS_SERVICE_DB_HOST=localhost
COMMAND_STATUS_SERVICE_DB_PORT=5432
COMMAND_STATUS_SERVICE_DB_NAME=command-status_db
COMMAND_STATUS_SERVICE_DB_USER=postgres
COMMAND_STATUS_SERVICE_DB_PASSWORD=postgres
sbt boot/run
При запуске сервиса локально ожидается, что уже развернута необходимая инфраструктура:
- PostgreSQL база по
адресу
{COMMAND_STATUS_SERVICE_DB_HOST}:{COMMAND_STATUS_SERVICE_DB_PORT}/{COMMAND_STATUS_SERVICE_DB_NAME}(localhost:5432/command-status_db, если запуск как в примере) - Kafka по адресу
localhost:9092 - Consul по адресу
localhost:8500
Список переменных окружения для сервиса Command-status
| Переменная | Тип | Обязательная | Значение по умолчанию | Описание |
|---|---|---|---|---|
COMMAND_STATUS_SERVICE_PUBLISH_HOST |
string | Нет | "0.0.0.0" |
Хост, на котором слушает HTTP-сервер. |
COMMAND_STATUS_SERVICE_PUBLISH_PORT |
int | Нет | 8080 |
Порт, на котором слушает HTTP-сервер. |
COMMAND_STATUS_SERVICE_KAFKA_SERVERS |
string | Да | "localhost:9092" |
Адрес Kafka. |
COMMAND_STATUS_SERVICE_STATUS_TOPIC |
string | Да | "commandevents" |
Название кафка-топика, куда отправляются сообщения со статусами выполняемых команд. |
COMMAND_STATUS_SERVICE_CONSUMER_GROUP |
string | Нет | "statusGroup" |
Имя consumer-группы для чтения из кафка-топика команд. Не должна меняться и не должна быть пустой, иначе сервис перечитает свои команды при перезапуске. |
COMMAND_STATUS_SERVICE_TOPIC_PARTITIONS |
int | Нет | 10 |
Число читаемых партиций из кафка-топика со статусами. |
COMMAND_STATUS_SERVICE_KAFKA_CONSUMER_RESTART_MIN_BACKOFF |
duration string | Нет | 3 seconds |
Изначальная задержка до рестарта консьюмера после падения. С каждым рестартом, задержка увелчивается по формуле "delay = restartsNumber * initDelay" |
COMMAND_STATUS_SERVICE_KAFKA_CONSUMER_RESTART_MAX_BACKOFF |
duration string | Нет | 1 minute |
Максимальное задержка до рестарта консьюмера после падения. |
COMMAND_STATUS_SERVICE_KAFKA_CONSUMER_RESTART_MAX_RESTARTS |
int | Нет | 20 |
Максимальное число попыток переподключения консьюмера. После достижения максимального, роут /health будет возвращать 503, что приведет к рестарту сервиса в k8s. |
COMMAND_STATUS_SERVICE_KAFKA_AUTH_USER |
string | Нет | "" |
Название учетной записи Kafka. Если название не указано, то настройки авторизации не будут применены. |
COMMAND_STATUS_SERVICE_KAFKA_AUTH_PASSWORD |
string | Нет | "" |
Пароль учетной записи Kafka. |
COMMAND_STATUS_SERVICE_KAFKA_AUTH_PRINCIPAL |
string | Нет | "" |
Principal учетной записи Kafka в Kerberos(в случае соединения с kafka через Kerberos). |
COMMAND_STATUS_SERVICE_KAFKA_AUTH_KEYTAB_PATH |
string | Нет | "" |
Путь до keytab-файла(в случае соединения с kafka через Kerberos). |
COMMAND_STATUS_SERVICE_KAFKA_AUTH_TRUSTSTORE_LOCATION |
string | Нет | "" |
Путь до хранилища сертификатов (Java key store). Если путь не указан, то сертификат применяться не будет. |
COMMAND_STATUS_SERVICE_KAFKA_AUTH_TRUSTSTORE_PASSWORD |
string | Нет | "" |
Пароль к хранилищу сертификатов. |
COMMAND_STATUS_SERVICE_KAFKA_AUTH_MODE |
string | Нет | "" |
Режим аутентификации: static - одна учетная запись на все запросы, mapping - учетная запись зависит от запроса. |
COMMAND_STATUS_SERVICE_KAFKA_AUTH_CONFIG |
string | Нет | "" |
Настройки для аутентификации: если AuthMode = mapping, то необходим JSON с List[KafkaAuthConfig]. Переменная соответствует полю authConfig из KafkaAuthSettings. |
COMMAND_STATUS_SERVICE_KAFKA_AUTH_CACHE_SIZE |
int | Нет | Максимальный размер кеша для Kafka producer (количество активных соединений). | |
COMMAND_STATUS_SERVICE_KAFKA_CONNECTION_CHECK_TEST_MESSAGES_INTERVAL |
duration string | Нет | 4 minutes |
Применяется только для producer-ов со способом аутентификации kerberos. Интервал отправки тестовых сообщений кафки в топик connectionCheck.testMessagesTopicName. Тестовые сообщения (null, service producer test) отправляются регулярно с этим интервалом. |
COMMAND_STATUS_SERVICE_KAFKA_CONNECTION_CHECK_INTERVAL |
duration string | Нет | 60 seconds |
Применяется только для producer-ов со способом аутентификации kerberos. Интервал проверки того, сколько тестовых сообщений было отправлено за данный период. Если количество сообщений за этот период равно количеству сообщений за прошлый период, то начинается отсчет периода без сообщений. |
COMMAND_STATUS_SERVICE_KAFKA_CONNECTION_CHECK_FAILED_AFTER_INTERVAL |
duration string | Нет | 5 minutes |
Применяется только для producer-ов со способом аутентификации kerberos. Максимальная продолжительность периода без успешно отправленных тестовых сообщений. По ее достижении сервис будет объявлен больным. |
COMMAND_STATUS_SERVICE_KAFKA_AUTH_CACHE_TTL |
duration string | Нет | Время жизни Kafka producer в кеше. | |
COMMAND_STATUS_SERVICE_CONSUL_ADDRESS |
url string | Нет | "http://localhost:8500" |
Адрес Сonsul. |
COMMAND_STATUS_SERVICE_CONSUL_AUTH_USER |
string | Нет | "" |
Название учетной записи Сonsul. Если название не указано, то настройки авторизации не будут применены. |
COMMAND_STATUS_SERVICE_CONSUL_AUTH_PASSWORD |
string | Нет | "" |
Пароль учетной записи Сonsul. |
COMMAND_STATUS_SERVICE_DISCOVERABLE_ID |
string | Нет | "CommandStatusService" |
ID сервиса в ServiceDiscovery. |
COMMAND_STATUS_SERVICE_DISCOVERABLE_NAME |
string | Нет | "CommandStatusService" |
Имя сервиса в ServiceDiscovery. |
COMMAND_STATUS_SERVICE_DISCOVERABLE_HOST |
string | Да | "localhost" |
Хост, публикуемый в ServiceDiscovery. По нему на данный сервис будут обращаться другие через HTTP. Указанный адрес должен быть виден другим сервисам. Пример: имя kubernetes/docker_swarm service. |
COMMAND_STATUS_SERVICE_DISCOVERABLE_PORT |
int | Нет | Порт, публикуемый в ServiceDiscovery. По нему на данный сервис будут обращаться другие через HTTP. По умолчанию указывается порт, который слушает HTTP-сервер. | |
COMMAND_STATUS_SERVICE_DISCOVERABLE_LIVETIME |
duration string | Нет | 5 minutes |
Период после последней отправки health check, в течение которого ServiceDiscovery считает данный сервис живым. |
COMMAND_STATUS_SERVICE_DISCOVERABLE_HEALTHPASS |
duration string | Нет | 1 minute |
Периодичность отправки health check в ServiceDiscovery. |
COMMAND_STATUS_SERVICE_DISCOVERABLE_VERSION |
string | Нет | "v1" |
Версия сервиса, публикуемого в ServiceDiscovery. |
COMMAND_STATUS_SERVICE_AKKA_HTTP_MAXCON |
int | Нет | 1024 |
Максимальное число одновременных исходящих HTTP-соединений. |
COMMAND_STATUS_SERVICE_AKKA_HTTP_IDLE_TIMEOUT |
duration string | Нет | 60 seconds |
Максимальное время жизни бездействующего соединения. |
COMMAND_STATUS_SERVICE_AKKA_HTTP_REQUEST_TIMEOUT |
duration string | Нет | 30 seconds |
Максимальное время ожидания исполнения запроса; должно быть меньше COMMAND_STATUS_SERVICE_AKKA_HTTP_IDLE_TIMEOUT. |
COMMAND_STATUS_SERVICE_AKKA_DEFAULT_DISPATCHER_EXECUTOR |
string | Нет | "default-executor" |
AKKA DOC: Which kind of ExecutorService to use for this dispatcher. Valid options: "default-executor" requires a "default-executor" section; "fork-join-executor" requires a "fork-join-executor" section; "thread-pool-executor" requires a "thread-pool-executor" section; "affinity-pool-executor" requires an "affinity-pool-executor" section. |
COMMAND_STATUS_SERVICE_AKKA_DEFAULT_DISPATCHER_THROUGHPUT |
int | Нет | 5 |
AKKA DOC: Throughput defines the number of messages that are processed in a batch before the thread is returned to the pool. Set to 1 for as fair as possible. |
COMMAND_STATUS_SERVICE_AKKA_FJP_PARALLELISM_MIN |
int | Нет | 8 |
AKKA DOC: Min number of threads to cap factor-based parallelism number to. |
COMMAND_STATUS_SERVICE_AKKA_FJP_PARALLELISM_MAX |
int | Нет | 64 |
AKKA DOC: Max number of threads to cap factor-based parallelism number to. |
COMMAND_STATUS_SERVICE_AKKA_FJP_PARALLELISM_FACTOR |
float | Нет | 1.0 |
AKKA DOC: The parallelism factor is used to determine thread pool size using the following formula: ceil(available processors * factor). Resulting size is then bounded by the parallelism-min and parallelism-max values. |
COMMAND_STATUS_SERVICE_AKKA_FJP_PARALLELISM_QUEUE_MODE |
string | Нет | "FIFO" |
AKKA DOC: Setting to "FIFO" to use queue like peeking mode which "poll" or "LIFO" to use stack like peeking mode which "pop". |
COMMAND_STATUS_SERVICE_AKKA_DEFAULT_DISPATCHER_EXECUTOR |
string | Нет | "thread-pool-executor" |
AKKA DOC: Which kind of ExecutorService to use for this dispatcher. Valid options: "default-executor" requires a "default-executor" section; "fork-join-executor" requires a "fork-join-executor" section; "thread-pool-executor" requires a "thread-pool-executor" section; "affinity-pool-executor" requires an "affinity-pool-executor" section. |
COMMAND_STATUS_SERVICE_AKKA_DEFAULT_DISPATCHER_THROUGHPUT |
int | Нет | 1 |
AKKA DOC: Throughput defines the number of messages that are processed in a batch before the thread is returned to the pool. Set to 1 for as fair as possible. |
COMMAND_STATUS_SERVICE_AKKA_DEFAULT_BLOCKING_FIXED_POOL_SIZE |
int | Нет | 16 |
AKKA DOC: Define a fixed thread pool size with this property. The corePoolSize and the maximumPoolSize of the ThreadPoolExecutor will be set to this value, if it is defined. Then the other pool-size properties will not be used. Valid values are: off or a positive integer. |
COMMAND_STATUS_SERVICE_SENDERLIB_COMMANDS_CACHE_UPDATEPERIOD |
duration string | Нет | 10 minutes |
Время кэширования данных по командам из CommandDiscovery. |
COMMAND_STATUS_SERVICE_SENDERLIB_SERVICES_CACHE_UPDATEPERIOD |
duration string | Нет | 0 minutes |
Время кэширования данных по сервисам из ServiceDiscovery. |
COMMAND_STATUS_SERVICE_DB_HOST |
string | Да | Хост БД. | |
COMMAND_STATUS_SERVICE_DB_PORT |
int | Да | Порт БД. | |
COMMAND_STATUS_SERVICE_DB_NAME |
string | Да | Имя базы в БД. | |
COMMAND_STATUS_SERVICE_DB_URL |
jdbc url string | Нет | JDBC-url для соединения с БД. По умолчанию собирается из других обязательных переменных. Можно указать только его, если не хочется отдельно указывать хост/порт/имя базы. | |
COMMAND_STATUS_SERVICE_DB_USER |
string | Да | Пользователь БД. | |
COMMAND_STATUS_SERVICE_DB_PASSWORD |
string | Да | Пароль пользователя БД. | |
COMMAND_STATUS_SERVICE_DB_THREADS |
int | Нет | 10 |
Количество потоков в пуле потоков для соединения с БД. |
COMMAND_STATUS_SERVICE_DB_QUEUE_SIZE |
int | Нет | 300 |
Размер очереди для действий базы данных, которые не могут быть выполнены немедленно, когда все потоки заняты. За пределами этого значения новые действия немедленно завершаются неудачей. |
COMMAND_STATUS_SERVICE_DB_CONN_MAX |
int | Нет | 10 |
Максимальное количество одновременных подключений к БД. |
COMMAND_STATUS_SERVICE_DB_CONN_MIN |
int | Нет | ${COMMAND_STATUS_SERVICE_DB_THREADS} |
Минимальное количество одновременных подключений к БД. |
COMMAND_STATUS_SERVICE_DB_CONN_TIMEOUT |
duration string | Нет | 20 seconds |
Максимальное время ожидания ответа для соединения к БД. Если это время превышено, а соединение не становится доступным, будет брошено исключение SQLException. 1000 мс — минимальное значение. |
COMMAND_STATUS_SERVICE_DB_ISOLATION |
string | Нет | "READ_COMMITTED" |
Уровень изоляции транзакций для новых подключений. Допустимые значения: NONE, READ_COMMITTED, READ_UNCOMMITTED, REPEATABLE_READ, SERIALIZABLE. |
COMMAND_STATUS_SERVICE_DB_READONLY |
boolean | Нет | false |
Read-only SQL транзакция может изменять только временные таблицы. Этот параметр управляет статусом «только для чтения» по умолчанию для каждой новой транзакции. |
COMMAND_STATUS_SERVICE_DB_VALIDATION_TIMEOUT |
duration string | Нет | 1 seconds |
Максимальное время, в течение которого соединение будет проверяться на работоспособность. 1000 мс — минимальное значение. |
COMMAND_STATUS_SERVICE_DB_IDLE_TIMEOUT |
duration string | Нет | 10 minutes |
Максимальное время, в течение которого соединению разрешено простаивать в пуле. Значение 0 означает, что простаивающие соединения никогда не удаляются из пула. |
COMMAND_STATUS_SERVICE_DB_MAX_LIFETIME |
duration string | Нет | 30 minutes |
Максимальное время жизни соединения в пуле. Когда простаивающее соединение достигает этого времени ожидания, даже если оно недавно использовалось, оно будет удалено из пула. Значение 0 указывает на отсутствие максимального срока службы. |
COMMAND_STATUS_SERVICE_DB_INITIALIZATION_FAIL_FAST |
boolean | Нет | false |
Deprecated, начиная с версии Slick 3.3.0. Определяет, будет ли пул «быстро выходить из строя», если пул не может быть успешно заполнен начальными соединениями. Если соединения не могут быть созданы во время запуска пула, будет выдано исключение RuntimeException. Это свойство не имеет никакого эффекта, если minConnections равно 0. |
COMMAND_STATUS_SERVICE_DB_LEAK_DETECTION_THRESHOLD |
int | Нет | 0 |
Время, в течение которого соединение может находиться вне пула, прежде чем будет зарегистрировано сообщение, указывающее на возможную утечку соединения. Значение 0 означает, что обнаружение утечек отключено. Наименьшее приемлемое значение для включения обнаружения утечек составляет 10 с. |
COMMAND_STATUS_SERVICE_DB_CONNECTION_TEST_QUERY |
string | Нет | "SELECT 1" |
Выражение, которое будет выполнено непосредственно перед получением соединения из пула для проверки того, что соединение с базой данных все еще активно. Оно зависит от базы данных и должно представлять собой запрос, требующий минимальной обработки базой данных (например, «VALUES 1»). Если этот параметр не установлен, вместо него используется метод JDBC4 Connection.isValid(). |
COMMAND_STATUS_SERVICE_DB_AUTO_COMMIT |
boolean | Нет | true |
Это свойство определяет то, как будут вести себя по умолчанию возвращаемые соединения относительно autocommit-а. |
COMMAND_STATUS_SERVICE_DB_SCHEMA |
string | Нет | "public" |
Устанавливает schema по умолчанию. |
COMMAND_STATUS_SERVICE_DB_ISOLATE_INTERNAL_QUERIES |
boolean | Нет | false |
Определяет то, изолируются ли с помощью транзакций внутренние запросы пула(например запрос connection alive test). Свойство применяется только если autoCommit выключен. |
COMMAND_STATUS_SERVICE_DB_INITIALIZATION_FAIL_TIMEOUT |
int | Нет | 1 |
Работает, начиная с версии Slick 3.3.0. Определяет, будет ли пул «быстро выходить из строя», если пул не может быть успешно заполнен начальными соединениями. Любое положительное число считается числом миллисекунд для попытки получить начальное соединение;поток приложения будет заблокирован в течение этого периода. Если соединение не может быть получено до истечения этого времени,будет брошено исключение. Данный таймаут применяется после периода connectionTimeout. Если значение равно нулю (0),HikariCP попытается получить и проверить подключение. Если соединение получено,но проверка не пройдена, будет брошено исключение, и пул не будет запущен. Однако,если соединение не может быть получено, пул запустится,но последующие попытки получить соединение могут потерпеть неудачу.Значение меньше нуля пройдет любую первоначальную попытку подключения, и пул немедленно запустится,пытаясь получить соединения в фоновом режиме.Следовательно, последующие попытки получить соединение могут потерпеть неудачу. |
COMMAND_STATUS_SERVICE_DB_REGISTER_MBEANS |
boolean | Нет | false |
Зарегистрированы ли JMX Management Beans («MBeans»). |
COMMAND_STATUS_SERVICE_STATUS_CACHE_TTL |
duration string | Нет | 2 hours |
Время жизни статуса команд в базе данных сервиса статусов (после получения последнего статуса из кафка). |
COMMAND_STATUS_SERVICE_STATUS_CACHE_CLEAN_CHECK |
duration string | Нет | 5 minutes |
Период проверки базы данных со статусами команд для удаления статусов, время жизни которых превысило COMMAND_STATUS_SERVICE_STATUS_CACHE_TTL. |
COMMAND_STATUS_SERVICE_STATUS_CACHE_SUBSCRIPTION_CHECK |
duration string | Нет | 1 second |
Время задержки между проверками кеша со статусами команд для уведомления подписчиков на статусы. Период проверки статуса = время обхода всех команд, для которых существуют подписки + время задержки. |
COMMAND_STATUS_SERVICE_COMMAND_CLEANER_CHECK |
duration string | Нет | 1 hour |
Период проверки Command discovery для очистки команд, привязаных к сервисам которые не считаются "живыми". |
COMMAND_STATUS_SERVICE_COMMAND_CLEANER_DELETE_ERRORS |
boolean | Нет | true |
Удалять ли принудительно команды из Command discovery, с которыми возникли ошибки во время "очистки". |
COMMAND_STATUS_SERVICE_SENDERLIB_COMMANDS_HTTP_RETRY_ATTEMPTS |
int | Нет | 5 |
Поле attempts из RetrySettings. |
COMMAND_STATUS_SERVICE_SENDERLIB_COMMANDS_HTTP_RETRY_DELAY |
duration string | Нет | 5 seconds |
Поле delay из RetrySettings. |
COMMAND_STATUS_SERVICE_SENDERLIB_COMMANDS_HTTP_RETRY_KIND |
string | Нет | "OnSomeExceptions(ConnectException)" |
CommandResultRetryConditionKind. |
COMMAND_STATUS_SERVICE_SENDERLIB_CONSIDER_ALL_COMMANDS_AS_INTERNAL |
boolean | Нет | false |
Флаг, определяющий будут ли все обращения в другие сервисы являться внутренними (т.е. не требовать авторизацию). Детальное описание механизма: Внутренние команды. |
COMMAND_STATUS_SERVICE_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS |
int | Нет | 2 |
Максимальное количество раз, которое консьюмер перезапустится с неизменной очередью сообщений(в пределах COMMAND_STATUS_SERVICE_KAFKA_CONSUMER_RESTART_MAX_RESTARTS_WITHIN), прежде чем проигнорировать сообщение, на котором происходит ошибка (Указано количество рестартов, а не прочтений. Если ALEXANDRINA_KAFKA_CONSUMER_RESTART_MAX_RESTARTS = 2, то ошибочное сообщение будет обработано 3 раза, после чего произойдет 3ий рестарт и оно будет проигнорировано). Если указать 0, то перезапуск произойдет, но сообщение будет обработано только в первый раз, когда произошла ошибка. Если указать значение меньше 0, то перезапуски все равно будут происходить, но игнорирование сообщений, вызывающих ошибку, будет отключено. |
COMMAND_STATUS_SERVICE_KAFKA_CONSUMER_PER_MESSAGE_RESTART_CACHE_SIZE |
int | Нет | 100 |
Для каждого сообщения счетчик перепрочтений хранится в кэше. Максимальное количество значений в этом кэше. |
COMMAND_STATUS_SERVICE_KAFKA_CONSUMER_PER_MESSAGE_RESTART_CACHE_TTL |
duration string | Нет | 5 minutes |
Для каждого сообщения счетчик перепрочтений хранится в кэше.Максимальное время жизни элемента в этом кэше. В случае отсутствия значения время жизни элемента не будет ограничено. |
COMMAND_STATUS_SERVICE_KAFKA_CONSUMER_POLL_TIMEOUT |
duration string | нет | 10 milliseconds |
timeout запроса poll для kafka consumer |
COMMAND_STATUS_SERVICE_KAFKA_CONSUMER_POLL_INTERVAL |
duration string | нет | 100 milliseconds |
интервал между запросами poll для kafka consumer |
COMMAND_STATUS_SERVICE_KAFKA_CONSUMER_PROPS |
string | нет | "max.poll.records=500;max.partition.fetch.bytes=524288" |
дополнительные параметры для kafka consumer в формате "key1=value1;key2=value2" |
COMMAND_STATUS_SERVICE_WRITE_STATUS_INMEMORY_CACHE_MAX_SIZE |
int | Нет | 1000 |
Максимальный размер кэша, который поддерживается при записи статусов. К этому кэшу происходит обращение для проверки приоритета статуса. (Статус записывается в БД только если его приоритет выше, чем у последнего статуса этой команды уже записанного в БД). |
COMMAND_STATUS_SERVICE_WRITE_STATUS_INMEMORY_CACHE_TTL |
duration string | Нет | 60 seconds |
Время жизни элемента в кэше, который поддерживается при записи статусов. |
COMMAND_STATUS_SERVICE_WRITE_STATUS_INMEMORY_CACHE_SCHEDULER_ENABLED |
boolean | Нет | true |
Будет ли запущен scheduler, который убирает элементы из кэша в момент истечения ttl, или элементы будет удаляться только в момент обращения к кэшу при записи статусов. |
COMMAND_STATUS_SERVICE_READ_STATUS_INMEMORY_CACHE_MAX_SIZE |
int | Нет | 10 |
Максимальный размер кэша, который поддерживается при чтении статусов. При чтении статусов обращение к БД происходит только если в кэше нет статуса по этой команде. |
COMMAND_STATUS_SERVICE_READ_STATUS_INMEMORY_CACHE_TTL |
duration string | Нет | 10 milliseconds |
Время жизни элемента в кэше, который поддерживается при чтении статусов. |
COMMAND_STATUS_SERVICE_READ_STATUS_INMEMORY_CACHE_SCHEDULER_ENABLED |
boolean | Нет | true |
Будет ли запущен scheduler, который убирает элементы из кэша в момент истечения ttl, или элементы будет удаляться только в момент обращения к кэшу при чтении статусов. |
NOT_LOG_VALUE_FOR_STATUSES |
string | Нет | "" |
Список CommandStatus, для которых не нужно логировать поле "value". Статусы перечисляются в одной строке через запятую ",". |
APP_LOGIC_LOG_LEVEL |
string | Нет | "INFO" |
Уровень логгирования бизнес логики сервиса. |
BACKGROUND_LOGIC_LOG_LEVEL |
string | Нет | "INFO" |
Уровень логгирования бэкграунд процессов сервиса. |
Список команд сервиса Command-status (commands-list)
Список команд сервиса Command-status аналогичен списку команд в библиотеке command-status-core.
Модели сервиса Command-status
Набор моделей сервиса Command-status аналогичен набору моделей в библиотеке command-status-core.
Command-status-core: базовая библиотека сервисов сервисов статуса команд command-status
В библиотеку вынесен шаблон структуры и кода для сервисов статуса команд и реализации по умолчанию.
Сервис разбит на несколько модулей, в виде sbt проектов:
domain, в котором содержатся все доменные модели и их различные представления.infrastructure, в котором содержатся базовые компоненты для взаимодействия с инфраструктурой.storage, содержит сервисы для сохранения и чтения из разных хранилищ доменных моделей.service, содержит сервисы бизнес логики, которые определяют правила взаимодействия компонентов между собой.route, содержит HTTP роуты.boot, содержит зависимости и описание для сборки и запуска сервиса.testkit, моки и настройки окружения для тестов
Публикуются эти проекты как одна библиотека command-status-core.
Сервис обеспечивает трассировку выполнения команд и
хранение их промежуточных “текущих” состояний и результатов.
Также он позволяет простым и быстрым способом запрашивать данные
по этим текущим состояниям команд.
Иногда сервис может не успевать обрабатывать все события. Чтобы повысить скорость обработки входящих событий по
командам,
нужно запускать несколько инстансов. Производительность одной ноды и их общее количество подсчитывается индивидуально,
в зависимости от ресурсов на одну ноду и количества партиций в топике (точнее, сколько будет приходиться партиций на одну
ноду).
Например, для 8 CPU и 16gb RAM одна нода может вычитывать около 1500 сообщений в секунду из топика с 10 партициями (
читает все 10 партиций).
Обычно, чем меньше партиций читается одной нодой, тем меньше ядер CPU на нее нужно выделять (например, читает 2
партиции - выделяем 2 CPU).
Подключение (command-status-core)
Для того чтобы использовать библиотеку command-status-core, нужно добавить зависимость
"com.embedika.commandstatus" %% "command-status-core" % verdiVersion
Liquibase (command-status-core)
Реализация command-status-core, поставляемая в данной библиотеке, предполагает наличие определенных таблиц в базе данных, которая
указана в
application.conf по пути database.db.url. Эти таблицы command-status-core создает с помощью
com.embedika.verdi.persistence.migration.LiquibasePlugin.
Для корректной работы плагина в сервисе, созданном на основе command-status-core, по пути boot/src/main/resources/liquibase
должен лежать файл changelog.xml,
иначе при запуске упадет исключение
liquibase.exception.ChangeLogParseException: The file liquibase/changelog.xml was not found.
Для корректной работы всех команд в сервисе, созданном на основе command-status-core, предоставленный файл changelog.xml должен
включать в себя все
stages, находящиеся в command-status-core по пути /boot/src/main/resources/liquibase/stages.
При необходимости после указанных stages можно добавить в changelog.xml свои кастомные stages.
Пример содержимого файла changelog.xml.
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
<include file="stages/202504.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>
Модули (command-status-core)
Для инициализации сервиса command-status-core используются модули izumi-distage.
В каждом модуле описывается создание сущностей, необходимых для работы сервиса.
Более подробное описание работы с модулями можно найти в Модули (mon-core)
Список команд библиотеки Command-status-core (commands list)
Список реализованных в сервисе команд.
| Назначение команды | Имя вызова команды |
|---|---|
| Получение статуса команды (без ожидания) | GetStatus |
| Получение статуса команды (ожидание конечного статуса в течение переданного таймаута) | PollStatus |
GetStatus
Payload для команды
import com.embedika.senderlib.{Discpatcher, VerdiFactory}
import com.embedika.senderlib.models.command._
val factory: VerdiFactory = VerdiFactory.create(
/** params here */
)
val dispatcher: Dispatcher = factory.dispatcher
dispatcher.status(CommandId("a9f813eb-22ff-4982-9828-c3471cec76fe"))
// or
dispatcher.sendCommandSync(CommandName("getStatus"), CommandId("a9f813eb-22ff-4982-9828-c3471cec76fe"))
"a9f813eb-22ff-4982-9828-c3471cec76fe"
Результат выполнения команды
val result: Future[Either[DispatchError, (CommandId, CommandStatusRepresentation)]] =
dispatcher.sendCommandSync(CommandName("getStatus"), CommandId("a9f813eb-22ff-4982-9828-c3471cec76fe"))
result.transform {
case Success(Some(Right(id, result))) =>
val status = result.status
val json = result.json
// process result
case _ => // process errors
}
{
"status": "Completed",
"timestamp": 1657797778943,
"value": "test completed"
}
Получает текущий статус исполняемой команды. Dispatcher для команд
имеет вспомогательный метод .status() для упрощенного
вызова этой команды.
Свойства команды
| Свойство | Значение | Описание |
|---|---|---|
| Версия | v1 | |
| Название команды | getStatus | Название команды для прямого вызова |
| Тип вызова | HTTP | |
| HTTP-метод | POST | |
| Url | /v1/status | |
| Права доступа | [] | |
| Внутренняя команда | нет | |
| Сервисная команда | да | для служебных команд не ведется жизненный цикл, не пишутся состояния |
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: CommandId
- На выходе: CommandAggregatedStatus
PollStatus
Передаем ID команды и таймаут поллинга
{
"commandId": "efef5704-5827-49f8-8b3f-a00df3db7f5a",
"timeoutSeconds": 5
}
Результат выполнения команды
{
"status": "Completed",
"timestamp": 1657797778943,
"value": "test completed"
}
Ожидает завершение команды в течение указанного времени (long-polling) и возвращает результат.
Если команда не завершилась за указанное время, вернет ее текущий статус.
Свойства команды
| Свойство | Значение | Описание |
|---|---|---|
| Версия | v1 | |
| Название команды | pollStatus | Название команды для прямого вызова |
| Тип вызова | HTTP | |
| HTTP-метод | POST | |
| Url | /v1/pollStatus | |
| Права доступа | [] | |
| Внутренняя команда | нет | |
| Сервисная команда | да | для служебных команд не ведется жизненный цикл, не пишутся состояния |
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: CommandId
- На выходе: CommandAggregatedStatus
Модели сервиса command-status-core (models)
PollStatus (command-status-core)
| Поле | Тип | Обязательное | Значение по умолчанию | Описание | Ограничения |
|---|---|---|---|---|---|
| commandId | CommandId | Да | ID команды, статус которой необходимо получить | ||
| timeoutSeconds | Int | Да | Таймаут, в течение которого будет производиться ожидание одного из финальных статусов команды |
CommandAggregatedStatus (command-status-core)
CommandAggregatedStatus без поля httpHeaders.
Data-model: сервис модели данных
Сервис модели данных (Data Model Service) позволяет настроить какие сущности, с какими полями и отношениями будут
храниться в системе на основе Verdi. На основе данных о сущностях сервис будет формировать описание модели данных и
возвращать его в
формате JsonSchema. Также сервис управляет созданием/изменением/удалением объектов сущностей в реестрах.
Сущности, полученные из внешних источников (клиентов), таких как сетевая папка или 1С, называются внешними.
Отличие от внутренних сущностей состоит в том, что помимо внутреннего ID, они имеют ID из внешнего источника,
по которому этот источник может совершать запросы.
Конфигурирование Data-model
Требования к запуску Data-model
Запуск сервиса осуществляется локально через sbt, на стенде в docker на jvm.
Для корректной минимальной работы сервиса требуется обязательное подключение к PostgreSQL, Kafka, Consul. Для настройки подключения к ним нужно заполнить обязательные переменные окружения из раздела ниже.
Для нормальной работы сервису дополнительно требуется окружение Verdi: CommandStatus и ApiGateway. В этом случае нужно уделить внимание настройкам, связанным с ServiceDiscovery и CommandDiscovery.
Список переменных окружения для сервиса Data-model
Все доступные переменные окружения для настройки сервиса модели данных.
| Переменная | Тип | Обязательная | Значение по умолчанию | Описание |
|---|---|---|---|---|
DATA_MODEL_HTTP_HOST |
String |
Нет | 0.0.0.0 |
Хост, на котором слушает HTTP-сервер. |
DATA_MODEL_HTTP_PORT |
Int |
Нет | 8192 |
Порт, на котором слушает HTTP-сервер. |
DATA_MODEL_KAFKA_SERVERS |
String |
Да | localhost:9092 |
Адрес Kafka. |
DATA_MODEL_KAFKA_TOPIC |
String |
Нет | data_model_service_commands |
Название кафка-топика для получения команд. Сервис получает кафка-команды по нему, но и также сам публикует это название в CommandDiscovery. |
DATA_MODEL_KAFKA_CONSUMER_GROUP |
String |
Нет | data-model-service |
Имя consumer-группы для чтения из кафка-топика команд. Не должна меняться и не должна быть пустой, иначе сервис перечитает свои команды при перезапуске. |
DATA_MODEL_KAFKA_PARTITIONS |
Int |
Нет | 10 |
Число читаемых партиций из кафка-топика команд. |
DATA_MODEL_KAFKA_CONSUMER_RESTART_MIN_BACKOFF |
Duration String |
Нет | 1 second |
Изначальная задержка до рестарта консьюмера после падения (увеличивается в 2 раза после каждого рестарта). |
DATA_MODEL_KAFKA_CONSUMER_RESTART_MAX_BACKOFF |
Duration String |
Нет | 30 seconds |
Максимальная задержка до рестарта консьюмера после падения. |
DATA_MODEL_KAFKA_CONSUMER_RESTART_RANDOM_FACTOR |
Double |
Нет | 0.2 |
Коэффициент величины дополнительной случайной задержки(jitter) относительно основной задержки (При значении 0.2 задержка может быть до 20% больше, чем при 0). Если после умножения задержки на DATA_MODEL_KAFKA_CONSUMER_RESTART_RANDOM_FACTOR получится меньше 1 миллисекунды, то jitter будет приравнен к нулю. |
DATA_MODEL_KAFKA_CONSUMER_RESTART_MAX_RESTARTS |
Int |
Нет | 5 |
Максимальное число рестартов консьюмера после падения (в пределах DATA_MODEL_KAFKA_CONSUMER_RESTART_MAX_RESTARTS_WITHIN).После превышения этого числа сервис будет объявлен больным. Все рестарты для каждого отдельного сообщения увеличивают и общий счетчик рестартов консьюмера, поэтому при использовании DATA_MODEL_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS нужно указывать DATA_MODEL_KAFKA_CONSUMER_RESTART_MAX_RESTARTS > DATA_MODEL_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS или не указывать DATA_MODEL_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS совсем. |
DATA_MODEL_KAFKA_CONSUMER_RESTART_MAX_RESTARTS_WITHIN |
Duration String |
Нет | 5 minutes |
Временной отрезок, в который DATA_MODEL_KAFKA_CONSUMER_RESTART_MAX_RESTARTS ограничивает число рестартов. |
DATA_MODEL_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS |
Int |
Нет | 2 |
Максимальное количество раз, которое консьюмер перезапустится с неизменной очередью сообщений(в пределах DATA_MODEL_KAFKA_CONSUMER_RESTART_MAX_RESTARTS_WITHIN), прежде чем проигнорировать сообщение, на котором происходит ошибка (Указано количество рестартов, а не прочтений. Если DATA_MODEL_KAFKA_CONSUMER_RESTART_MAX_RESTARTS = 2, то ошибочное сообщение будет обработано 3 раза, после чего произойдет 3ий рестарт и оно будет проигнорировано). Если указать 0, то перезапуск произойдет, но сообщение будет обработано только в первый раз, когда произошла ошибка. Если указать значение меньше 0, то перезапуски все равно будут происходить, но игнорирование сообщений, вызывающих ошибку, будет отключено. |
DATA_MODEL_KAFKA_CONSUMER_PER_MESSAGE_RESTART_CACHE_SIZE |
Int |
Нет | 100 |
Для каждого сообщения счетчик перепрочтений хранится в кэше. Максимальное количество значений в этом кэше. |
DATA_MODEL_KAFKA_CONSUMER_PER_MESSAGE_RESTART_CACHE_TTL |
Duration String |
Нет | 5 minutes |
Для каждого сообщения счетчик перепрочтений хранится в кэше.Максимальное время жизни элемента в этом кэше. В случае отсутствия значения время жизни элемента не будет ограничено. |
DATA_MODEL_KAFKA_CONSUMER_POLL_TIMEOUT |
Duration String |
Нет | 10 milliseconds |
timeout запроса poll для kafka consumer. |
DATA_MODEL_KAFKA_CONSUMER_POLL_INTERVAL |
Duration String |
Нет | 100 milliseconds |
Интервал между запросами poll для kafka consumer. |
DATA_MODEL_KAFKA_CONSUMER_PROPS |
String |
Нет | max.poll.records=500;max.partition.fetch.bytes=524288 |
Дополнительные параметры для kafka consumer в формате key1=value1;key2=value2. |
DATA_MODEL_KAFKA_PRODUCER_PROPS |
String |
Нет | batch.size=524288;linger.ms=10;max.request.size=1048576 |
Дополнительные параметры для kafka producer в формате key1=value1;key2=value2. |
DATA_MODEL_KAFKA_COMMANDEVENT_TOPIC |
String |
Да | commandevents |
Название кафка-топика для отправки сообщений со статусами выполняемых команд. ОБЯЗАТЕЛЬНО должно соответствовать названию этого топика в сервисе статуса команд. |
DATA_MODEL_KAFKA_FILE_EVENTS_TOPIC |
String |
Нет | fileEvents |
Название кафка-топика для отправки сообщений об удалении файлов. |
DATA_MODEL_KAFKA_AUTH_USER |
String |
Нет | Название учетной записи Kafka. Если название не указано, то настройки авторизации не будут применены. | |
DATA_MODEL_KAFKA_AUTH_PASSWORD |
String |
Нет | Пароль учетной записи Kafka. | |
DATA_MODEL_KAFKA_AUTH_PRINCIPAL |
String |
Нет | Principal учетной записи Kafka в Kerberos(в случае соединения с kafka через Kerberos). | |
DATA_MODEL_KAFKA_AUTH_KEYTAB_PATH |
String |
Нет | Путь до keytab-файла(в случае соединения с kafka через Kerberos). | |
DATA_MODEL_KAFKA_AUTH_TRUSTSTORE_LOCATION |
String |
Нет | Путь до хранилища сертификатов (Java key store). Если путь не указан, то сертификат применяться не будет. | |
DATA_MODEL_KAFKA_AUTH_TRUSTSTORE_PASSWORD |
String |
Нет | Пароль к хранилищу сертификатов. | |
DATA_MODEL_KAFKA_AUTH_MODE |
String |
Нет | Режим аутентификации: static - одна учетная запись на все запросы, mapping - учетная запись зависит от запроса. | |
DATA_MODEL_KAFKA_AUTH_CONFIG |
String |
Нет | Настройки для аутентификации: если AuthMode = mapping, то необходим JSON с List[KafkaAuthConfig]. Переменная соответствует полю authConfig из KafkaAuthSettings. |
|
DATA_MODEL_KAFKA_AUTH_CACHE_SIZE |
Int |
Нет | Максимальный размер кэша для Kafka producer (количество активных соединений). | |
DATA_MODEL_KAFKA_AUTH_CACHE_TTL |
Duration String |
Нет | Время жизни Kafka producer в кэше. | |
DATA_MODEL_KAFKA_CONNECTION_CHECK_TEST_MESSAGES_INTERVAL |
Duration String |
Нет | 4 minutes |
Применяется только для producer-ов со способом аутентификации kerberos. Интервал отправки тестовых сообщений кафки в топик connectionCheck.testMessagesTopicName. Тестовые сообщения (null, service producer test) отправляются регулярно с этим интервалом. |
DATA_MODEL_KAFKA_CONNECTION_CHECK_INTERVAL |
Duration String |
Нет | 60 seconds |
Применяется только для producer-ов со способом аутентификации kerberos. Интервал проверки того, сколько тестовых сообщений было отправлено за данный период. Если количество сообщений за этот период равно количеству сообщений за прошлый период, то начинается отсчет периода без сообщений. |
DATA_MODEL_KAFKA_CONNECTION_CHECK_FAILED_AFTER_INTERVAL |
Duration String |
Нет | 5 minutes |
Применяется только для producer-ов со способом аутентификации kerberos. Максимальная продолжительность периода без успешно отправленных тестовых сообщений. По ее достижении сервис будет объявлен больным. |
DATA_MODEL_KAFKA_PRODUCER_PROPS |
String |
Нет | max.request.size=1048576 |
Дополнительные параметры для Kafka producer. Заполняются по шаблону "key1=value1;key2=value2". |
DATA_MODEL_KAFKA_PRODUCER_MESSAGE_MAX_BYTES |
Int |
Нет | 1048576 |
Лимит в байтах для Kafka сообщений. |
DATA_MODEL_CONSUL_ADDR |
URL |
Нет | http://localhost:8500 |
Адрес Сonsul. |
DATA_MODEL_CONSUL_AUTH_USER |
String |
Нет | Название учетной записи Сonsul. Если название не указано, то настройки авторизации не будут применены. | |
DATA_MODEL_CONSUL_AUTH_PASSWORD |
String |
Нет | Пароль учетной записи Сonsul. | |
DATA_MODEL_TRACE_DURATION |
Boolean |
Нет | false |
Признак необходимости трассировки выполнения команд. |
DATA_MODEL_BATCH_PARALLELISM |
Int |
Нет | 4 |
Параллелизм для батч-обработок (например обновление нескольких объектов в одном запросе). |
DATA_MODEL_DISCOVERABLE_ID |
String |
Нет | another_data_model _service_instance |
ID сервиса в ServiceDiscovery. |
DATA_MODEL_DISCOVERABLE_NAME |
String |
Нет | dataModel |
Имя сервиса в ServiceDiscovery. |
DATA_MODEL_DISCOVERABLE_HOST |
String |
Да | localhost |
Хост, публикуемый в ServiceDiscovery. По нему на данный сервис будут обращаться другие через HTTP. Указанный адрес должен быть виден другим сервисам. Пример: имя kubernetes/docker_swarm service. |
DATA_MODEL_DISCOVERABLE_PORT |
Int |
Нет | Порт, публикуемый в ServiceDiscovery. По нему на данный сервис будут обращаться другие через HTTP. По умолчанию указывается порт, который слушает HTTP-сервер. | |
DATA_MODEL_DISCOVERABLE_LIVETIME |
Duration String |
Нет | 2 minutes |
Период после последней отправки health check, в течение которого ServiceDiscovery считает данный сервис живым. |
DATA_MODEL_DISCOVERABLE_HEALTHPASS |
String |
Нет | 1 minute |
Периодичность отправки health check в ServiceDiscovery. |
DATA_MODEL_AKKA_HTTP_CLIENT_MAXCON |
Int |
Нет | 512 |
Максимальное число одновременных исходящих HTTP-соединений. |
DATA_MODEL_AKKA_HTTP_CLIENT_MAXREQ |
Int |
Нет | 1024 |
Максимальное число одновременных исходящих HTTP-запросов. |
DATA_MODEL_AKKA_HTTP_SERVER_MAXCON |
Int |
Нет | 1024 |
Максимальное число одновременных входящих HTTP-соединений. |
DATA_MODEL_AKKA_HTTP_SERVER_IDLE_TIMEOUT |
Duration String |
Нет | 5 minutes |
Максимальное время жизни входящего http-соединения. |
DATA_MODEL_AKKA_HTTP_SERVER_REQUEST_TIMEOUT |
Duration String |
Нет | 5 minutes |
Максимальное время обработки входящего http-запроса. Должно быть не больше предыдущего значения, иначе входящее соединение оборвется по таймауту времени жизни запроса. |
DATA_MODEL_INTERNALCMD_ALLOW |
Boolean |
Нет | false |
Можно ли сервису отправлять внутрисистемные команды. |
DATA_MODEL_SENDERLIB_COMMANDS_CACHE_UPDATEPERIOD |
Duration String |
Нет | 10 minutes |
Время кэширования данных по командам из CommandDiscovery. |
DATA_MODEL_SENDERLIB_SERVICES_CACHE_UPDATEPERIOD |
Duration String |
Нет | 30 seconds |
Время кэширования данных по сервисам из ServiceDiscovery. |
DATA_MODEL_SENDERLIB_CONSIDER_ALL_COMMANDS_AS_INTERNAL |
Boolean |
Нет | false |
Флаг, определяющий будут ли все обращения в другие сервисы являться внутренними (т.е. не требовать авторизацию). Детальное описание механизма: Внутренние команды. |
DATA_MODEL_DB_HOST |
String |
Да | Хост БД. | |
DATA_MODEL_DB_PORT |
Int |
Да | Порт БД. | |
DATA_MODEL_DB_NAME |
String |
Да | Имя базы в БД. | |
DATA_MODEL_DB_URL |
JBDC URL |
Нет | JDBC-url для соединения с БД. По умолчанию собирается из других обязательных переменных. Можно указать только его, если не хочется отдельно указывать хост/порт/имя базы. | |
DATA_MODEL_DB_USER |
String |
Да | Пользователь БД. | |
DATA_MODEL_DB_PASSWORD |
String |
Да | Пароль пользователя БД. | |
DATA_MODEL_DB_THREADS |
Int |
Нет | 10 |
Количество потоков в пуле потоков для соединения с БД. |
DATA_MODEL_DB_QUEUE_SIZE |
Int |
Нет | 300 |
Размер очереди для действий базы данных, которые не могут быть выполнены немедленно, когда все потоки заняты. За пределами этого значения новые действия немедленно завершаются неудачей. |
DATA_MODEL_DB_CONN_MAX |
Int |
Нет | 10 |
Максимальное количество одновременных подключений к БД. |
DATA_MODEL_DB_CONN_TIMEOUT |
Duration String |
Нет | 20 second |
Максимальное время ожидания ответа для соединения к БД. Если это время превышено, а соединение не становится доступным, будет брошено исключение SQLException. 1000 мс — минимальное значение. |
DATA_MODEL_DB_ISOLATION |
String |
Нет | READ_COMMITTED |
Уровень изоляции транзакций для новых подключений. Допустимые значения: NONE, READ_COMMITTED, READ_UNCOMMITTED, REPEATABLE_READ, SERIALIZABLE. |
DATA_MODEL_DB_READONLY |
Boolean |
Нет | false |
Read-only SQL транзакция может изменять только временные таблицы. Этот параметр управляет статусом «только для чтения» по умолчанию для каждой новой транзакции. |
DATA_MODEL_DB_CONN_MIN |
Int |
Нет | = DB_THREADS |
Минимальное количество одновременных подключений к БД. |
DATA_MODEL_DB_VALIDATION_TIMEOUT |
Duration String |
Нет | 1 seconds |
Максимальное время, в течение которого соединение будет проверяться на работоспособность. 1000 мс — минимальное значение. |
DATA_MODEL_DB_IDLE_TIMEOUT |
Duration String |
Нет | 10 minutes |
Максимальное время, в течение которого соединению разрешено простаивать в пуле. Значение 0 означает, что простаивающие соединения никогда не удаляются из пула. |
DATA_MODEL_DB_MAX_LIFETIME |
Duration String |
Нет | 30 minutes |
Максимальное время жизни соединения в пуле. Когда простаивающее соединение достигает этого времени ожидания, даже если оно недавно использовалось, оно будет удалено из пула. Значение 0 указывает на отсутствие максимального срока службы. |
DATA_MODEL_DB_INITIALIZATION_FAIL_FAST |
String |
Нет | false |
Deprecated, начиная с версии Slick 3.3.0. Определяет, будет ли пул «быстро выходить из строя», если пул не может быть успешно заполнен начальными соединениями. Если соединения не могут быть созданы во время запуска пула, будет выдано исключение RuntimeException. Это свойство не имеет никакого эффекта, если minConnections равно 0. |
DATA_MODEL_DB_LEAK_DETECTION_THRESHOLD |
Int |
Нет | 0 |
Время, в течение которого соединение может находиться вне пула, прежде чем будет зарегистрировано сообщение, указывающее на возможную утечку соединения. Значение 0 означает, что обнаружение утечек отключено. Наименьшее приемлемое значение для включения обнаружения утечек составляет 10 с. |
DATA_MODEL_DB_CONNECTION_TEST_QUERY |
String |
Нет | SELECT 1 |
Выражение, которое будет выполнено непосредственно перед получением соединения из пула для проверки того, что соединение с базой данных все еще активно. Оно зависит от базы данных и должно представлять собой запрос, требующий минимальной обработки базой данных (например, «VALUES 1»). Если этот параметр не установлен, вместо него используется метод JDBC4 Connection.isValid(). |
DATA_MODEL_DB_AUTO_COMMIT |
Boolean |
Нет | true |
Это свойство определяет то, как будут вести себя по умолчанию возвращаемые соединения относительно autocommit-а. |
DATA_MODEL_DB_SCHEMA |
String |
Нет | public |
Устанавливает schema по умолчанию. |
DATA_MODEL_DB_ISOLATE_INTERNAL_QUERIES |
Boolean |
Нет | false |
Определяет то, изолируются ли с помощью транзакций внутренние запросы пула(например запрос connection alive test). Свойство применяется только если autoCommit выключен. |
DATA_MODEL_DB_INITIALIZATION_FAIL_TIMEOUT |
Int |
Нет | 1 |
Работает, начиная с версии Slick 3.3.0. Определяет, будет ли пул «быстро выходить из строя», если пул не может быть успешно заполнен начальными соединениями. Любое положительное число считается числом миллисекунд для попытки получить начальное соединение;поток приложения будет заблокирован в течение этого периода. Если соединение не может быть получено до истечения этого времени,будет брошено исключение. Данный таймаут применяется после периода connectionTimeout. Если значение равно нулю (0),HikariCP попытается получить и проверить подключение. Если соединение получено,но проверка не пройдена, будет брошено исключение, и пул не будет запущен. Однако,если соединение не может быть получено, пул запустится,но последующие попытки получить соединение могут потерпеть неудачу.Значение меньше нуля пройдет любую первоначальную попытку подключения, и пул немедленно запустится,пытаясь получить соединения в фоновом режиме.Следовательно, последующие попытки получить соединение могут потерпеть неудачу. |
DATA_MODEL_DB_REGISTER_MBEANS |
Boolean |
Нет | false |
Зарегистрированы ли JMX Management Beans («MBeans»). |
DATA_MODEL_FS_REQUIRED |
Boolean |
Нет | false |
Обязательно ли использовать реальное файлохранилище. Можно отключать для локального использования (НЕЛЬЗЯ! НЕ РАБОТАЕТ). |
DATA_MODEL_FS_URI |
URL |
Нет | http://localhost:9000 |
Адрес для подключения к Minio. |
DATA_MODEL_FS_ACCESS_KEY_ID |
String |
Нет | minioadmin |
Ключ доступа к хранилищу файлов Minio (aka пользователь). |
DATA_MODEL_FS_SECRET_ACCESS_KEY |
String |
Нет | minioadmin |
Секретный код доступа к хранилищу файлов Minio (aka пароль). |
DATA_MODEL_FS_UPLOAD_PARALLELISM |
Int |
Нет | 4 |
Максимально возможный параллелизм при загрузке файлов в хранилище. |
DATA_MODEL_FS_AUTH_MODE |
String |
Нет | static |
Режим аутентификации: static - одна учетная запись на все запросы, mapping - учетная запись зависит от запроса. |
DATA_MODEL_FS_AUTH_CONFIG |
String |
Нет | Настройки для аутентификации: если AuthMode = mapping, то необходим JSON с List[FSBucketConfig] соответствует полю authConfig FSConfigRep. |
|
DATA_MODEL_FS_CACHE_SIZE |
Int |
Нет | 1 |
Максимальный размер кэша клиентов для хранилища файлов (количество активных соединений). |
DATA_MODEL_FS_CACHE_TTL |
Duration String |
Нет | Время жизни клиента в кэше. | |
DATA_MODEL_FS_RETRY_ATTEMPTS |
Int |
Нет | 5 |
Количество ретраев, которое будет произведено в случае Exception-а в операции FSClient-а и при вычитывании стрима в get операциях FSClient-а. |
DATA_MODEL_FS_RETRY_DELAY |
Duration String |
Нет | 10 millis |
Задержка между ретраями операций FSClient-а. |
DATA_MODEL_FS_ZIO_SHORT_MESSAGE_MODE |
Boolean |
Нет | false |
Флаг включения режима сохранения ошибок работы с файловым хранилищем в сервисе журналирования nestor. При включении режима ошибки в логах будут отображаться в сокращенном формате: Short zio message mode. ExceptionType: ТИП ОШИБКИ, Exception id: 'СГЕНЕРИРОВАННЫЙ UUID' added to journal. Указанный id будет фиксироваться в event записи nestor'а в поле data.id. |
DATA_MODEL_TEMP_BUCKET |
String |
Нет | temp |
Название бакета в Minio, в котором находятся временные файлы. |
DATA_MODEL_ENTITY_OBJECTS_BUCKET |
String |
Нет | datamodel |
Название бакета в Minio, в котором сохраняются на постоянной основе файлы объектов модели данных. |
DATA_MODEL_RELATION_SYSTEM_FIELDS_PREFIX |
String |
Нет | _ |
Префикс для системных полей relation-объектов, используемые в результате RichGet команд. |
DATA_MODEL_AUTHORIZER_KIND |
String |
Нет | authzforce |
Вид авторизатора, который используется в сервисе. Допустимые значения: authzforce, oberto. При указании неизвестного значения будет использовано значение по-умолчанию. |
DATA_MODEL_SENDERLIB_COMMANDS_HTTP_RETRY_ATTEMPTS |
Int |
Нет | 5 |
Поле attempts из RetrySettings. |
DATA_MODEL_SENDERLIB_COMMANDS_HTTP_RETRY_DELAY |
Duration String |
Нет | 5 seconds |
Поле delay из RetrySettings. |
DATA_MODEL_SENDERLIB_COMMANDS_HTTP_RETRY_KIND |
String |
Нет | OnSomeExceptions(ConnectException) |
CommandResultRetryConditionKind. |
DATA_MODEL_SENDERLIB_CONSUL_CONNECTION_RETRY_MAX |
Int |
Нет | 5 |
Количество попыток переподключения к Consul. |
DATA_MODEL_SENDERLIB_CONSUL_CONNECTION_RETRY_DELAY |
Duration String |
Нет | 1 second |
Задержка при попытках переподключения к Consul. |
DATA_MODEL_JOURNAL_MODE |
String |
Нет | WriteToJournal |
Режим журналирования Nestor. Допустимые значения: WriteToJournal (Отправка в сервис журналирования), WriteToTopic (Отправка события в очередь). |
DATA_MODEL_JOURNAL_TOPIC |
String |
Да, если переменная DATA_MODEL_JOURNAL_MODE = WriteToTopic |
Название очереди журналирования. Для режима WriteToJournal значение игнорируется. |
Команды сервиса Data-model
Список реализованных в сервисе команд, моделей EntityType и действий Actions, которые можно использовать при настройке
авторизации.
Не все поля EntityType доступны для использования в настройке авторизации.
Если указан прочерк "-", то данное значение не влияет на авторизацию:
- если не указан Action, то никакой Action не проверяется (= без авторизации);
- если не указан EntityType, то на авторизацию влияет только Action.
| Назначение команды | Имя вызова команды | EntityType | Actions |
|---|---|---|---|
| Получение типов полей для сущностей модели данных. | getFieldTypes |
- | DataModel_GetFieldTypes |
| Получение типов отношений между сущностями в модели данных. | getRelationTypes |
- | DataModel_GetRelationTypes |
| Создание или изменение модели данных с использованием миграции. | createDataModel |
- | DataModel_CreateModel |
| Получение описания модели данных для конкретной сущности в виде JSON-Schema. | getDataModel |
- | DataModel_GetModel |
| Получение созданных типов сущностей. | listDataModels |
- | DataModel_GetDataModel |
| Получение JSON-Schema для всех моделей данных. | getAllDataModels |
- | DataModel_GetAllModels |
| Получение примера объекта сущности. | getExampleObject |
- | DataModel_GetExampleObj |
| Сохранение объекта сущности. | saveObject |
Произвольный EntityType из ObjectStorage. |
DataModel_SaveObject |
| Сохранение списка объектов сущности. | saveObjectBatch |
- | - |
| Сохранение списка объектов сущности. | saveObjectBatchV2 |
- | - |
| Сохранение объекта сущности, полученного из внешнего источника. | saveExternalObject |
- | DataModel_SaveExternalObj |
| Получение данных объекта сущности. | getObject |
Произвольный EntityType из ObjectStorage. |
DataModel_GetObject |
| Получение данных объекта сущности. | internalGetObject |
- | - |
| Получение данных объектов по их ID и типу сущности. | getObjectsBatch |
- | DataModel_GetObjects |
| Получение данных объекта сущности. | richGetObject |
Произвольный EntityType из ObjectStorage. |
DataModel_RichGetObject |
| Получение данных объекта сущности. | internalRichGetObject |
- | - |
| Получение данных объектов по их ID, типу сущности и списку требуемых полей. | richGetObjectsBatch |
Произвольный EntityType из ObjectStorage. |
DataModel_RichGetObjectsBatch |
| Получение данных объекта сущности. | getExternalObject |
- | DataModel_GetExternalObj |
| Изменение объекта сущности. | updateObject |
Произвольный EntityType из ObjectStorage. |
DataModel_UpdateObj |
| Изменение полей в объекте сущности. | updateObjectFields |
Произвольный EntityType из ObjectStorage. |
DataModel_UpdateObjField |
| Изменение полей в объекте сущности. | internalUpdateObjectFields |
- | - |
| Массовое изменение полей в объектах сущности, попадающих под списочный запрос. | updateObjectFieldsList |
Произвольный EntityType из ObjectStorage. |
DataModel_UpdateObjFieldList |
| Массовое изменение полей в объектах сущности по ID объектов. | updateObjectFieldsBatch |
Произвольный EntityType из ObjectStorage. |
DataModel_UpdateObjFieldBatch |
| Изменение внешнего объекта. | updateExternalObject |
Произвольный EntityType из ObjectStorage. |
DataModel_UpdateExternalObj |
| Отмечает в БД объект сущности как удаленный. | softDeleteObject |
Произвольный EntityType из ObjectStorage. |
DataModel_DeleteObject |
| Удаление объекта сущности. | deleteObject |
Произвольный EntityType из ObjectStorage. |
DataModel_DeleteObject |
| Отмечает в БД сущности из списка как удаленные. | softDeleteObjectBatch |
- | - |
| Удаление объектов сущностей по списку. | deleteObjectBatch |
- | - |
| Отмечает сущности полученные поиском по реестру как удаленные. | softDeleteObjectSearch |
Произвольный EntityType из ObjectStorage. |
- |
| Удаление объектов сущности поиском по реестру. | deleteObjectSearch |
Произвольный EntityType из ObjectStorage. |
- |
| Удаление внешнего объекта сущности. | deleteExternalObject |
- | DataModel_DeleteExternal |
| Сохранение дополнительных полей объекта сущности. | saveAdditionalInfo |
- | DataModel_SaveInfo |
| Сохранение метаданных объекта сущности. | saveObjectMetadata |
- | - |
| Сохранение метаданных объектов сущностей батчем. | saveObjectMetadataBatch |
- | - |
| Добавление информации о дополнительных файлах файловых полей. | saveFilesAdditionalInfo |
- | DataModel_SaveFilesInfo |
| Привязывание дополнительных файлов к исходным. | saveFilesAdditionalInfoV2 |
- | DataModel_SaveFilesInfo |
| Получение списка объектов запрашиваемой сущности. | listObjects |
Произвольный EntityType (берется на проверку из input.entityType) из ObjectStorage. |
DataModel_ListObjects |
| Получение списка объектов запрашиваемой сущности. | internalListObjects |
- | - |
| Получение списка объектов запрашиваемой сущности. | richListObjects |
- | DataModel_RichListObjects |
| Получение списка объектов запрашиваемой сущности. | internalRichListObjects |
- | - |
| Получение списка метаданных объектов запрашиваемой сущности. | listObjectsMeta |
Произвольный EntityType (берется на проверку из input.entityType) из ObjectStorage. |
DataModel_ListObjMeta |
| Получение списка наименований объектов. | listObjectTitles |
- | DataModel_ListObjTitles |
| Получение списка наименований объектов. | listObjectTitlesV2 |
Произвольный EntityType (берется на проверку из input.entityType) из ObjectStorage. |
DataModel_ListObjTitles |
| Получение позиции объекта в списке объектов. | getObjectPosition |
- | DataModel_GetObjPosition |
| Получения списка ID файлов, которые отсутствуют в сервисе. | listNonExistingFileId |
- | - |
| Получение статистики полей модели данных. | getEntityFieldAggregation |
- | DataModel_GetFieldAggregation |
| Сохранение отношения между объектами двух сущностей. | saveRelation |
- | DataModel_SaveRelation |
| Сохранение отношения между объектами двух сущностей. | internalSaveRelation |
- | - |
| Сохранение нескольких отношений между объектами двух сущностей. | saveRelationBatch |
- | DataModel_SaveRelations |
| Сохранение нескольких отношений между объектами двух сущностей. | internalSaveRelationBatch |
- | - |
| Получение отношения между объектами двух сущностей. | getRelation |
- | DataModel_GetRelation |
| Получение всех отношений объекта с указанной сущностью. | listRelations |
Произвольный EntityType (берется на проверку из input.entityType и input.relatedEntityType) из ObjectStorage. |
DataModel_ListRelations |
| Массовое получение всех отношений объекта с указанной сущностью. | listRelationsBatch |
Произвольный EntityType (берется на проверку из input.entityType и input.relatedEntityType) из ObjectStorage. |
DataModel_ListRelations |
| Получение всех отношений объекта. | listAllRelations |
Произвольный EntityType (берется на проверку из input.entityType) из ObjectStorage. |
DataModel_ListAllRelations |
| Удаление отношения между объектами двух сущностей. | deleteRelation |
- | DataModel_DeleteRelation |
| Удаление отношений объекта с перечисленными сущностями. | deleteRelations |
- | DataModel_DeleteRelations |
| Удаление всех отношений объекта. | deleteAllRelations |
- | DataModel_DeleteAllRelations |
| Обновление списка отношений одного объекта с указанной сущностью. | updateExternalRelations |
Произвольный EntityType из ObjectStorage. |
DataModel_UpdateExternalObjectRelations |
| Переиндексация объекта. | reindexObject |
Произвольный EntityType из ObjectStorage. |
DataModel_ReindexObject |
| Получение связи между объектами по ID. | getObjectLink |
- | DataModel_GetLink |
| Получение всех связей объекта. | getObjectLinks |
- | DataModel_GetLinks |
| Получение всех связей между указанными типами. | listRelationsByType |
Произвольный EntityType (берется на проверку из input.entityFrom и input.entityTo) из ObjectStorage. |
DataModel_ListRelations |
| Получение связи между объектами по ID. | createObjectLink |
- | DataModel_CreateLink |
| Создание связей между объектами. | createObjectsLinks |
- | DataModel_CreateLinks |
| Удаление связи между объектами по ID. | deleteObjectLink |
- | DataModel_DeleteLink |
| Удаление связей объекта. | deleteAllObjectLinks |
- | DataModel_DeleteAllLinks |
| Получение списка подробной информацией с тегами и родительском объекте файлов. | listFilesInfoWithTags |
- | DataModel_ViewFiles |
| Получение списка тегов с количеством файлов. | listTagsWithFilesCount |
- | DataModel_ViewFiles |
| Получение списка уникальных расширений загруженных в систему файлов. | listFileExtensions |
- | DataModel_ViewFileExtensions |
| Перезаписывание текущих тегов файлов объекта новым списком. | writeFileTags |
- | DataModel_WriteFileTags |
| Удаление тегов из текущего набора тегов для файла объекта. | removeFileTags |
- | DataModel_RemoveFileTags |
| Удаление всех тегов для указанных файлов. | removeAllFileTags |
- | DataModel_RemoveAllFileTags |
| Получение родительских сущностей сущности. | getEntityParents |
- | DataModel_GetParents |
| Скачивание файла. | getFile |
Произвольный EntityType из ObjectStorage. |
DataModel_GetFile |
| Перезаписывание текущих ключевых слов объекта новым списком слов. | updateKeywords |
Произвольный EntityType из ObjectStorage. |
- |
| Получение ключевых слов объекта. | listObjectKeywords |
- | DataModel_ListObjectKeywords |
| Получение по параметрам поискового запроса списка ключевых слов. | listKeywords |
- | DataModel_ListKeywords |
Получение максимального значения для поля объекта из data или additionalData. |
internalGetMaxNumericFieldValue |
- | - |
GetFieldTypes (Data-model command)
На выходе
[
{
"id": "string",
"description": "Строка",
"databaseType": "Varchar(64)",
"settings": {}
},
{
"id": "dateTime",
"description": "Дата/время",
"databaseType": "DateTime",
"settings": {}
}
]
Получение списка доступных типов полей для сущностей модели данных.
Имя команды для вызова: getFieldTypes.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Команда не принимает параметров.
- На выходе:
List[FieldType].
GetRelationTypes (Data-model command)
На выходе
[
{
"id": "one-to-one",
"title": "1 к 1",
"description": "Один к одному"
},
{
"id": "many-to-one",
"title": "Многие к 1",
"description": "Многие к одному"
},
{
"id": "many-to-many",
"title": "Многие ко многим",
"description": "Многие ко многим"
}
]
Получение доступных типов отношений между сущностями в модели данных.
Имя команды для вызова: getRelationTypes.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Команда не принимает параметров.
- На выходе:
List[RelationType].
CreateDataModel (Data-model command)
На входе MigrationDSL в виде списка операций
[
{
"operation": "CreateEntity",
"entityType": "Order",
"title": "Договор",
"settings": {
"titleRule": "title"
}
},
{
"operation": "AddField",
"entityType": "Order",
"fieldId": "date",
"fieldType": "dateTime",
"title": "Дата договора",
"description": "Дата заключения договора",
"example": 1582966800,
"nullable": false
},
{
"operation": "AddField",
"entityType": "Order",
"fieldId": "number",
"fieldType": "number",
"title": "Номер договора",
"example": 555,
"nullable": false
},
{
"operation": "AddField",
"entityType": "Order",
"fieldId": "title",
"fieldType": "string",
"title": "Название договора",
"example": "Договор аренды",
"nullable": false,
"settings": {
"maxLength": 200
}
},
{
"operation": "AddField",
"entityType": "Order",
"fieldId": "places",
"fieldType": "catalog",
"title": "Места заключения договора",
"nullable": true,
"settings": {
"code": "city",
"multiple": true
}
},
{
"operation": "CreateEntity",
"entityType": "Person",
"title": "Человек"
},
{
"operation": "AddField",
"entityType": "Person",
"fieldId": "name",
"fieldType": "string",
"title": "ФИО",
"nullable": false
},
{
"operation": "AddRelation",
"relationType": "many-to-one",
"entity1": "Order",
"entity2": "Person",
"title1": "Автор договора",
"title2": "Договора автора",
"entity1Field": "author",
"entity2Field": "orders",
"entity1Settings": {
"dependencies": [
{
"priority": 1,
"dependencyType": "autofill",
"dependentFieldCode": "places",
"dependentEntityTypeRelationField": "authorPlaces"
}
]
},
"entity2Settings": {}
}
]
На выходе признак успешного создания модели данных
true
Создание или изменение модели данных с использованием Migration DSL. Может использоваться для создания новых сущностей
или для модификации уже существующих. Фактически, команда применяет переданную ей миграцию для модели данных,
модифицируя текущую. Migration DSL позволяет описать создание или изменение модели данных в виде последовательности
операций/шагов.
Доступные операции Migration DSL:
- Создать сущность
CreateEntity. - Изменить сущность
UpdateEntity. - Удалить сущность
DeleteEntity. - Добавить поле сущности
AddField. - Добавить дополнительное поле сущности
AddAdditionalField. - Удалить поле у сущности
DeleteField. - Изменить поле у сущности
UpdateField. - Добавить отношение между сущностями
AddRelation. - Изменить отношение между сущностями
UpdateRelation. - Удалить отношение между сущностями
DeleteRelation. - Выполнить операцию для сущностей с префиксом
PrefixMigration.
Каждой операции соответствует JSON-объект, список которых и образует MigrationDSL-запрос на создание модели данных.
Объекты для операций указаны возле них в списке. Они различаются по коду операции, передаваемому в поле
operation. Все объекты для описания шагов наследуются от общего типа
MigrationDslOperation.
Команда получает текущее состояние схемы МД, проверяет, какие из
MigrationDslOperation
еще не применялись и пробует их применить.
Порядок операций важен! Нельзя добавить поле перед созданием сущности.
Имя команды для вызова: createDataModel.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
- На входе:
List[MigrationDslOperation]. - На выходе:
Boolean.
GetDataModel (Data-model command)
На входе код типа сущностей
"Order"
На выходе JSON-schema
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"definitions": {
"date": {
"type": "integer",
"minimum": 0
},
"relation": {
"type": "string",
"format": "uuid"
},
"catalog": {
"type": "string",
"format": "uuid"
},
"multi-catalog": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
}
},
"file": {
"type": "object",
"properties": {
"fileId": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"extension": {
"type": "string"
},
"size": {
"type": "integer",
"minimum": 0
},
"url": {
"type": "string"
},
"additional": {
"type": "object"
},
"created": {
"type": "integer",
"minimum": 0
},
"modified": {
"type": "integer",
"minimum": 0
},
"md5": {
"type": "string",
"pattern": "^[0-9a-fA-F]{32}$"
}
},
"required": [
"fileId"
]
}
},
"relations": [
{
"name": "Order_to_Person_on_author",
"entity1": "Order",
"entity2": "Person",
"relationType": "many-to-one",
"entity1Field": "author",
"entity2Field": "orders"
}
],
"type": "object",
"properties": {
"author": {
"$ref": "#/definitions/relation",
"additional": false,
"rawType": "relation",
"nullable": true,
"readOnly": true,
"multiple": false,
"title": "Authorship",
"to": "Person",
"settings": {
"dependencies": [],
"to": "Person"
}
},
"date": {
"$ref": "#/definitions/date",
"title": "Дата",
"description": "Дата/время",
"additional": false,
"rawType": "dateTime"
},
"number": {
"type": "number",
"description": "Число",
"additional": false,
"rawType": "number"
},
"places": {
"$ref": "#/definitions/multi-catalog",
"code": "city",
"multiple": true,
"title": "Места заключения договора",
"additional": false,
"rawType": "catalog",
"settings": {
"code": "city",
"multiple": true
}
},
"title": {
"type": "string",
"maxLength": 200,
"title": "Название договора",
"additional": false,
"rawType": "string",
"example": "Договор аренды",
"exampleType": "string",
"settings": {
"maxLength": 200
}
}
},
"required": [
"date",
"number",
"title"
],
"settings": {
"titleRule": "title",
"revisionConfig": {
"parentFieldCode": "document",
"actualityFieldCode": "isActual"
}
}
}
Или ошибка, если такой модели данных не существует
{
"businessError": null,
"message": "ERROR: Entity object not found",
"stackTrace": null,
"data": null
}
Получение описания модели данных для конкретной сущности в виде JSON-Schema.
Имя команды для вызова: getDataModel.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе:
JSONстрока. - На выходе:
JSON schema.
ListDataModels (Data-model command)
На выходе
[
{
"id": "Order",
"title": "Договор",
"description": "Описывает договор между несколькими агентами",
"settings": {
"titleRule": "title"
}
},
{
"id": "Person",
"title": "Человек",
"description": "Дополнительные человеческие аттрибуты для пользователя",
"settings": {}
}
]
Получение созданных типов сущностей.
Имя команды для вызова: listDataModels.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Команда не принимает параметров.
- На выходе:
List[EntityType].
GetAllDataModels (Data-model command)
На выходе
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"definitions": {
"date": {
"type": "integer",
"minimum": 0
},
"relation": {
"type": "string",
"format": "uuid"
},
"catalog": {
"type": "string",
"format": "uuid"
},
"multi-catalog": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
}
},
"file": {
"type": "object",
"properties": {
"fileId": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"extension": {
"type": "string"
},
"size": {
"type": "integer",
"minimum": 0
},
"url": {
"type": "string"
},
"additional": {
"type": "object"
},
"created": {
"type": "integer",
"minimum": 0
},
"modified": {
"type": "integer",
"minimum": 0
},
"md5": {
"type": "string",
"pattern": "^[0-9a-fA-F]{32}$"
}
},
"required": [
"fileId"
]
},
"Person": {
"type": "object",
"properties": {
"name": {
"type": "string",
"maxLength": 64,
"description": "Строка",
"additional": false,
"rawType": "string"
}
},
"required": [
"name"
],
"settings": {}
},
"Order": {
"type": "object",
"properties": {
"number": {
"type": "number",
"description": "Число",
"additional": false,
"rawType": "number"
},
"date": {
"$ref": "#/definitions/date",
"description": "Дата/время",
"additional": false,
"rawType": "dateTime"
},
"author": {
"$ref": "#/definitions/relation",
"additional": false,
"rawType": "relation",
"nullable": true,
"readOnly": true,
"multiple": false,
"title": "Authorship",
"to": "Person",
"settings": {
"dependencies": [],
"to": "Person"
}
}
},
"required": [
"number",
"date"
],
"settings": {}
}
},
"relations": [
{
"name": "Order_to_Person_on_author",
"entity1": "Order",
"entity2": "Person",
"relationType": "many-to-one",
"entity1Field": "author",
"entity2Field": "orders"
}
],
"oneOf": [
{
"$ref": "#/definitions/Order"
},
{
"$ref": "#/definitions/Person"
}
]
}
Получение JSON-Schema для всех моделей данных.
Имя команды для вызова: getAllDataModels.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Команда не принимает параметров.
- На выходе:
JSON schema.
GetExampleObject (Data-model command)
На входе тип сущности
"Order"
На выходе пример объекта данной сущности
{
"id": "d4db2633-62c7-4b61-956d-cb5461fe2a3e",
"externalId": "0000000000000000",
"entityType": "Order",
"title": "Order d4db2633-62c7-4b61-956d-cb5461fe2a3e",
"source": "example",
"created": 1630326492,
"modified": 1630326492,
"data": {
"date": 1577869200,
"number": 555,
"author": "00000000-0000-0000-0000-000000000000"
},
"additionalData": {},
"metadata": {},
"version": 1,
"removed": false
}
Получение примера объекта сущности. Объект собирается из примеров полей (example), которые указываются
при добавлении поля сущности (AddField).
Генерация полей:
| Поле | Значение |
|---|---|
id |
Случайный UUID. |
externalId |
0000000000000000 |
entityType |
Равен значению на входе. |
title |
См. ниже. |
source |
example |
created |
Текущий TimeStamp. |
modified |
Текущий TimeStamp. |
data |
Поля этого типа объекта. |
additionalData |
Дополнительные поля этого типа объекта. |
version |
1 |
Поле title зависит от поля data.titleRule. Если этого поля нет, то title имеет вид
<entityType> <id>.
Значения полей в data зависят от параметра example при создании поля (AddField).
Имя команды для вызова: getExampleObject.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: строка с типом сущности.
- На выходе:
EntityObject.
SaveObject (Data-model command)
На входе общие свойства сохраняемого объекта и основные атрибуты
{
"entityType": "Order",
"source": "manual",
"attributes": {
"date": 1577869200,
"number": 514,
"itemsRelation": [
"d1d70690-d972-4ee3-9ec1-ccd972979e72",
"05c989a2-74cc-4888-a49c-c160bf7f918a"
],
"personRelation": "18b1011b-9db3-4186-a53c-971016030068"
},
"createRelations": true
}
Для добавления объекта с файловым полем нужно передать такие входные данные.
{
"entityType": "NewEntityType",
"source": "manual",
"attributes": {
"someFileField": [
{
"fileId": "d22f86e6-7375-44f1-a4c0-681a670a1484"
}
]
}
}
Id файла можно получить загрузив его в систему с помощью рута apigateway/upload.
На выходе ID созданного объекта
"18b1011b-9db3-4186-a53c-971016030068"
Сохранение объекта сущности.
Имя команды для вызова: saveObject.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
- На входе:
AddEntityObject. - На выходе:
UUIDсозданного объекта.
SaveObjectBatch (Data-model command)
На входе общие свойства сохраняемых объектов и основные атрибуты
{
"entityType": "Order",
"source": "manual",
"attributes": [
{
"date": 1577869200,
"number": 512,
"itemsRelation": [
"d1d70690-d972-4ee3-9ec1-ccd972979e72",
"05c989a2-74cc-4888-a49c-c160bf7f918a"
],
"personRelation": "18b1011b-9db3-4186-a53c-971016030068"
},
{
"date": 1577869200,
"number": 513
},
{
"date": 1577869200,
"number": 514
}
],
"createRelations": true
}
На выходе список ID созданных объектов
[
"18b1011b-9db3-4186-a53c-971016030068",
"20f95899-cd42-4afc-9903-84269db53543",
"370a9981-ea0a-4830-93fe-e4e27ece167f"
]
Сохранение списка объектов сущности. Порядок в списке возвращаемых идентификаторов соответствует порядку в списке
атрибутов attributes.
Имя команды для вызова: saveObjectBatch.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway), не требует аутентификации.
- На входе:
AddEntityObjectBatch. - На выходе:
List[UUID]созданных объектов.
SaveObjectBatchV2 (Data-model command)
На входе общие свойства сохраняемых объектов и основные атрибуты
[
{
"entityType": "Order",
"source": "manual",
"attributes": {
"date": 1577869200,
"number": 512,
"itemsRelation": [
"d1d70690-d972-4ee3-9ec1-ccd972979e72",
"05c989a2-74cc-4888-a49c-c160bf7f918a"
],
"personRelation": "18b1011b-9db3-4186-a53c-971016030068"
},
"createRelations": true
},
{
"entityType": "Order",
"source": "manual",
"attributes": {
"date": 1577869200,
"number": 513
},
"metadata": {
"warnings": []
},
"createRelations": true
},
{
"objectId": "370a9981-ea0a-4830-93fe-e4e27ece167f",
"entityType": "Order",
"source": "manual",
"attributes": {
"date": 1577869200,
"number": 514
},
"metadata": {
"warnings": []
},
"createRelations": true
}
]
На выходе список ID созданных объектов
[
"18b1011b-9db3-4186-a53c-971016030068",
"20f95899-cd42-4afc-9903-84269db53543",
"370a9981-ea0a-4830-93fe-e4e27ece167f"
]
Сохранение списка объектов сущности. Порядок в списке возвращаемых идентификаторов соответствует исходному порядку.
Имя команды для вызова: saveObjectBatchV2.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway), не требует аутентификации.
- На входе:
List[AddEntityObjectForBatchV2]. - На выходе:
List[UUID].
SaveExternalObject (Data-model command)
На входе общие свойства сохраняемого объекта и основные атрибуты
{
"entityType": "Order",
"externalId": "ExternalOrder",
"source": "order-client",
"attributes": {
"date": 1577869200,
"number": 514,
"title": "External Order",
"itemsRelation": [
"d1d70690-d972-4ee3-9ec1-ccd972979e72",
"05c989a2-74cc-4888-a49c-c160bf7f918a"
],
"personRelation": "18b1011b-9db3-4186-a53c-971016030068"
},
"createRelations": true
}
На выходе внутренний ID созданного объекта
"18b1011b-9db3-4186-a53c-971016030068"
Сохранение объекта сущности, полученного из внешнего источника.
Имя команды для вызова: saveExternalObject.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway), не требует аутентификации.
- На входе:
AddExternalEntityObject. - На выходе: внутренний
UUIDсозданного объекта.
GetObject (Data-model command)
На входе ID получаемого объекта и его тип сущности
{
"entityType": "Order",
"objectId": "18b1011b-9db3-4186-a53c-971016030068"
}
На выходе данные запрашиваемого объекта
{
"id": "18b1011b-9db3-4186-a53c-971016030068",
"externalId": "ExternalOrder",
"entityType": "Order",
"title": "Аренда лошади",
"source": "manual",
"created": 1630326492,
"modified": 1630326492,
"data": {
"date": 1577869200,
"number": 514,
"title": "Аренда лошади",
"persons": [
"18b1011b-9db3-4186-a53c-971016030068"
],
"horse": "478bf14a-b1f9-46d4-b7fb-3b7ff3d8ca79",
"files": {
"2155c943-5c30-49aa-bc43-28c7447b26eb": "datamodel/Order/18b1011b-9db3-4186-a53c-971016030068"
}
},
"additionalData": {},
"metadata": {},
"version": 1,
"removed": false
}
Пример получения объекта с файловым полем
{
"id": "5ed35749-c65e-443b-8521-5aa90002e218",
"externalId": null,
"entityType": "NewEntityType",
"title": "NewEntityType 5ed35749-c65e-443b-8521-5aa90002e218",
"source": "manual",
"created": 1733812732202,
"modified": 1733812732202,
"data": {
"someFileField": [
{
"fileId": "4d3f61a5-fd61-45e2-a397-bd6f55a7df88",
"name": "rose31.docx",
"extension": "docx",
"size": 26070,
"url": "datamodel\\NewEntityType\\4d3f61a5-fd61-45e2-a397-bd6f55a7df88",
"additional": {
"fileContent": "datamodel\\NewEntityType\\601ee896-2002-4ca6-85ac-fb9370ccbddc"
},
"created": 1733812732416,
"modified": 1733812732416,
"md5": "017D2B9B383249F6F85487A9081906DF"
}
]
},
"additionalData": {},
"metadata": {},
"version": 1,
"removed": false
}
Получить файл по указанному url можно, вызвав у apigateway рут /download/\[значение из data.someFileField.url\].
Или ошибка, если объект отсутствует
{
"businessError": null,
"message": "ERROR: Entity object not found",
"stackTrace": null,
"data": null
}
Получение данных объекта сущности.
Имя команды для вызова: getObject.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе:
EntityObjectIdentity. - На выходе:
EntityObject.
InternalGetObject (Data-model command)
На входе ID получаемого объекта и его тип сущности
{
"entityType": "Order",
"objectId": "18b1011b-9db3-4186-a53c-971016030068"
}
На выходе данные запрашиваемого объекта
{
"id": "18b1011b-9db3-4186-a53c-971016030068",
"externalId": "ExternalOrder",
"entityType": "Order",
"title": "Аренда лошади",
"source": "manual",
"created": 1630326492,
"modified": 1630326492,
"data": {
"date": 1577869200,
"number": 514,
"title": "Аренда лошади",
"persons": [
"18b1011b-9db3-4186-a53c-971016030068"
],
"horse": "478bf14a-b1f9-46d4-b7fb-3b7ff3d8ca79",
"files": {
"2155c943-5c30-49aa-bc43-28c7447b26eb": "datamodel/Order/18b1011b-9db3-4186-a53c-971016030068"
}
},
"additionalData": {},
"metadata": {},
"version": 1,
"removed": false
}
Или ошибка, если объект отсутствует
{
"businessError": null,
"message": "ERROR: Entity object not found",
"stackTrace": null,
"data": null
}
Получение данных объекта сущности. В отличии от команды getObject, в этой команде не проверяется авторизация.
Имя команды для вызова: internalGetObject.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway) и отличается от внешней
getObject только
отсутствием аутентификации.
- На входе:
EntityObjectIdentity. - На выходе:
EntityObject.
GetObjectsBatch (Data-model command)
На входе список из ID и типов сущности получаемых объектов
[
{
"entityType": "Order",
"objectId": "18b1011b-9db3-4186-a53c-971016030068"
},
{
"entityType": "Person",
"objectId": "c11df8f6-e8be-4e8e-a815-40e0d0a0cfb6"
}
]
На выходе список объектов
[
{
"id": "18b1011b-9db3-4186-a53c-971016030068",
"externalId": "ExternalOrder",
"entityType": "Order",
"title": "Аренда лошади",
"source": "manual",
"created": 1630326492,
"modified": 1630326492,
"data": {
"date": 1577869200,
"number": 514,
"title": "Аренда лошади"
},
"additionalData": {},
"metadata": {},
"version": 1,
"removed": false
},
{
"id": "c11df8f6-e8be-4e8e-a815-40e0d0a0cfb6",
"externalId": null,
"entityType": "Person",
"title": "Person c11df8f6-e8be-4e8e-a815-40e0d0a0cfb6",
"source": "manual",
"created": 1645526774115,
"modified": 1645526774115,
"data": {
"name": "Строка длиной не больше 64",
"orders": [
"18b1011b-9db3-4186-a53c-971016030068"
]
},
"additionalData": {},
"metadata": {},
"version": 1,
"removed": false
}
]
Получение данных объектов по их ID и типу сущности. Порядок объектов в ответе совпадает с порядком идентификаторов в запросе.
Имя команды для вызова: getObjectsBatch.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе:
List[EntityObjectIdentity]. - На выходе:
List[EntityObject].
RichGetObject (Data-model command)
На входе ID получаемого объекта, тип его сущности и необходимые поля
{
"id": {
"entityType": "Order",
"objectId": "18b1011b-9db3-4186-a53c-971016030068"
},
"fields": [
"person.title",
"number",
"date"
],
"fieldSearches": {
"person": {
"query": "title",
"context": {
"title": "John"
}
}
}
}
На выходе данные запрашиваемого объекта
{
"id": "18b1011b-9db3-4186-a53c-971016030068",
"externalId": "ExternalOrder",
"entityType": "Order",
"title": "Аренда лошади",
"source": "manual",
"created": 1630326492,
"modified": 1630326492,
"data": {
"person": {
"_id": "478bf14a-b1f9-46d4-b7fb-3b7ff3d8ca79",
"_externalId": null,
"_entityType": "Person",
"_title": "John",
"_source": "manual",
"_created": 1634553248859,
"_modified": 1634553248859,
"_version": 1
},
"number": 514,
"date": 1577869200
},
"additionalData": {},
"metadata": {},
"version": 1,
"removed": false
}
Или ошибка, если объект отсутствует
{
"businessError": null,
"message": "ERROR: Entity object not found",
"stackTrace": null,
"data": null
}
Или ошибка, если какое-либо из запрашиваемых полей отсутствует в JSON schema
{
"businessError": null,
"message": "ERROR: fields [first_field,second_field] for entityType 'Order' not found",
"stackTrace": null,
"data": null
}
Получение данных объекта сущности.
Для указания списка допустимых полей см. Методы Rich*.
Имя команды для вызова: richGetObject.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе:
EntityObjectFields. - На выходе:
EntityObject.
InternalRichGetObject (Data-model command)
На входе ID получаемого объекта, тип его сущности и необходимые поля
{
"id": {
"entityType": "Order",
"objectId": "18b1011b-9db3-4186-a53c-971016030068"
},
"fields": [
"person.title",
"number",
"date"
],
"fieldSearches": {
"person": {
"query": "title",
"context": {
"title": "John"
}
}
}
}
На выходе данные запрашиваемого объекта
{
"id": "18b1011b-9db3-4186-a53c-971016030068",
"externalId": "ExternalOrder",
"entityType": "Order",
"title": "Аренда лошади",
"source": "manual",
"created": 1630326492,
"modified": 1630326492,
"data": {
"person": {
"_id": "478bf14a-b1f9-46d4-b7fb-3b7ff3d8ca79",
"_externalId": null,
"_entityType": "Person",
"_title": "John",
"_source": "manual",
"_created": 1634553248859,
"_modified": 1634553248859,
"_version": 1
},
"number": 514,
"date": 1577869200
},
"additionalData": {},
"metadata": {},
"version": 1,
"removed": false
}
Или ошибка, если объект отсутствует
{
"businessError": null,
"message": "ERROR: Entity object not found",
"stackTrace": null,
"data": null
}
Или ошибка, если какое-либо из запрашиваемых полей отсутствует в JSON schema
{
"businessError": null,
"message": "ERROR: fields [first_field,second_field] for entityType 'Order' not found",
"stackTrace": null,
"data": null
}
Получение данных объекта сущности.
Для указания списка допустимых полей см. Методы Rich*.
Имя команды для вызова: internalRichGetObject.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway) и отличается от внешней
richGetObject
только отсутствием аутентификации.
- На входе:
EntityObjectFields. - На выходе:
EntityObject.
RichGetObjectsBatch (Data-model command)
На входе список из типов сущностей, идентификаторов и требуемых полей у получаемых объектов
[
{
"entityType": "Order",
"ids": [
"18b1011b-9db3-4186-a53c-971016030068"
],
"fields": [
"person.title",
"date",
"number"
],
"fieldSearches": {}
},
{
"entityType": "Person",
"ids": [
"c11df8f6-e8be-4e8e-a815-40e0d0a0cfb6"
],
"fields": [
"person.title",
"name",
"orders"
],
"fieldSearches": {
"person": {
"query": "title",
"context": {
"title": "John"
}
}
}
}
]
На выходе список объектов, сгруппированный по типам сущностей
{
"Order": [
{
"id": "18b1011b-9db3-4186-a53c-971016030068",
"externalId": "ExternalOrder",
"entityType": "Order",
"title": "Аренда лошади",
"source": "manual",
"created": 1630326492,
"modified": 1630326492,
"data": {
"date": 1577869200,
"number": 514,
"person": {
"_id": "478bf14a-b1f9-46d4-b7fb-3b7ff3d8ca79",
"_externalId": null,
"_entityType": "Person",
"_title": "John",
"_source": "manual",
"_created": 1634553248859,
"_modified": 1634553248859,
"_version": 1
}
},
"additionalData": {},
"metadata": {},
"version": 1,
"removed": false
}
],
"Person": [
{
"id": "c11df8f6-e8be-4e8e-a815-40e0d0a0cfb6",
"externalId": null,
"entityType": "Person",
"title": "Person c11df8f6-e8be-4e8e-a815-40e0d0a0cfb6",
"source": "manual",
"created": 1645526774115,
"modified": 1645526774115,
"data": {
"orders": [
"18b1011b-9db3-4186-a53c-971016030068"
],
"name": "Строка длиной не больше 64",
"person": {
"_id": "478bf14a-b1f9-46d4-b7fb-3b7ff3d8ca79",
"_externalId": null,
"_entityType": "Person",
"_title": "John",
"_source": "manual",
"_created": 1634553248859,
"_modified": 1634553248859,
"_version": 1
}
},
"additionalData": {},
"metadata": {},
"version": 1,
"removed": false
}
]
}
Получение данных объектов по их ID, типу сущности и списку требуемых полей. Порядок объектов в ответе совпадает с
порядком идентификаторов в запросе.
Для указания списка допустимых полей см. Методы Rich*.
Имя команды для вызова: richGetObjectsBatch.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе:
List[EntityObjectsBatchWithFields]. - На выходе:
Map[EntityTypeId, List[EntityObject]].
GetExternalObject (Data-model command)
На входе внешний ID получаемого объекта и его тип сущности
{
"entityType": "Order",
"externalId": "ExternalOrder"
}
На выходе данные запрашиваемого объекта
{
"id": "982fa393-423b-4e6b-8e7d-d2b65ff061c8",
"externalId": "ExternalOrder",
"entityType": "Order",
"title": "External Order",
"source": "order-client",
"created": 1639748410280,
"modified": 1639748410280,
"data": {
"date": 1577869200,
"title": "External Order",
"number": 514
},
"additionalData": {},
"metadata": {},
"version": 1,
"removed": false
}
Получение данных объекта сущности.
Имя команды для вызова: getExternalObject.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway), не требует аутентификации.
- На входе:
EntityObjectExternalIdentity. - На выходе:
EntityObject.
UpdateObject (Data-model command)
На входе общие свойства сохраняемого объекта и основные атрибуты
{
"entityType": "Order",
"objectId": "18b1011b-9db3-4186-a53c-971016030068",
"version": 2,
"attributes": {
"date": 1577869200,
"number": 514,
"itemsRelation": [
"d1d70690-d972-4ee3-9ec1-ccd972979e72",
"05c989a2-74cc-4888-a49c-c160bf7f918a"
],
"personRelation": "18b1011b-9db3-4186-a53c-971016030068"
},
"createRelations": true
}
На выходе признак успешного сохранения
true
Или ошибка, если объект не существует
{
"businessError": null,
"message": "ERROR: Entity object not found",
"stackTrace": null,
"data": null
}
Или ошибка, если объект был обновлен из другого места
{
"businessError": null,
"message": "ERROR: object version is not actual (Optimistic Lock)",
"stackTrace": null,
"data": null
}
Изменение объекта сущности. Использует оптимистичную блокировку. Если изменяемый объект
был изменен параллельно (например, из другой формы другим пользователем),
тогда вернется ошибка ERROR: object version is not actual (Optimistic Lock), показывающая,
что не произошло обновления из-за некорректной версии.
Имя команды для вызова: updateObject.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
- На входе:
UpdateEntityObject. - На выходе:
Boolean,true- обновление успешно,false- неуспешно.
UpdateObjectFields (Data-model command)
На входе общие свойства обновляемого объекта, а также JSON-объект, где ключ - это изменяемое поле, а значение - новое значение этого поля
{
"entityType": "Order",
"objectId": "18b1011b-9db3-4186-a53c-971016030068",
"version": 2,
"updates": {
"date": 1577869200,
"title": "External Order",
"itemsRelation": [
"d1d70690-d972-4ee3-9ec1-ccd972979e72",
"05c989a2-74cc-4888-a49c-c160bf7f918a"
],
"personRelation": "18b1011b-9db3-4186-a53c-971016030068"
},
"createRelations": true
}
На выходе признак успешного сохранения
true
Или ошибка, если объект не существует
{
"businessError": null,
"message": "ERROR: Entity object not found",
"stackTrace": null,
"data": null
}
Или ошибка, если объект был обновлен из другого места
{
"businessError": null,
"message": "ERROR: object version is not actual (Optimistic Lock)",
"stackTrace": null,
"data": null
}
Изменение полей в объекте сущности. Если поле нужно удалить, то его значение указывается как null.
Использует оптимистичную блокировку. Если изменяемый объект
был изменен параллельно (например, из другой формы другим пользователем),
тогда вернется ошибка ERROR: object version is not actual (Optimistic Lock), показывающая,
что не произошло обновления из-за некорректной версии.
Имя команды для вызова: updateObjectFields.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
- На входе:
UpdateEntityObjectFields. - На выходе:
Boolean,true- обновление успешно,false- неуспешно.
InternalUpdateObjectFields (Data-model command)
Имя команды для вызова: internalUpdateObjectFields.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway).
Логика команды и вход/выход идентичен UpdateObjectFields.
UpdateObjectFieldsList (Data-model command)
На входе параметры списочного запроса, а также JSON-объект, где ключ - это изменяемое поле, а значение - новое значение этого поля
{
"entityType": "Order",
"search": {
"query": "title",
"context": {
"title": "External Order"
}
},
"updates": {
"date": 1577869200,
"title": "Updated External Order",
"itemsRelation": [
"d1d70690-d972-4ee3-9ec1-ccd972979e72",
"05c989a2-74cc-4888-a49c-c160bf7f918a"
],
"personRelation": "18b1011b-9db3-4186-a53c-971016030068"
},
"createRelations": true
}
На выходе количество измененных объектов
42
Массовое изменение полей в объектах сущности, попадающих под списочный запрос.
Имя команды для вызова: updateObjectFieldsList.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway), не требует аутентификации.
- На входе:
UpdateEntityObjectFieldsList. - На выходе:
Number, количество измененных объектов.
Для фильтрации по полям сущности подробности описаны тут.
UpdateObjectFieldsBatch (Data-model command)
На входе перечень ID обновляемых объектов, а также JSON-объект, где ключ - это изменяемое поле, а значение - новое значение этого поля
{
"entityType": "Order",
"objectIds": [
"0808bb23-3e32-4fea-b682-a8287b5f7d05",
"6895b246-ecb5-4a9b-8094-ed4aeabf2c46"
],
"updates": {
"date": 1577869200,
"title": "Updated External Order"
}
}
На выходе результаты обновления по каждому отдельному объекту
[
{
"entityId": "Order",
"objectId": "0808bb23-3e32-4fea-b682-a8287b5f7d05",
"result": true
},
{
"entityId": "Order",
"objectId": "6895b246-ecb5-4a9b-8094-ed4aeabf2c46",
"result": false,
"error": "ERROR: Entity object not found",
"errorCode": 404
}
]
Массовое изменение полей в объектах сущности по ID объектов.
Имя команды для вызова: updateObjectFieldsBatch.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway), не требует аутентификации.
- На входе:
UpdateEntityObjectFieldsBatch. - На выходе:
List[ObjectProcessingResult].
UpdateExternalObject (Data-model command)
На входе общие свойства сохраняемого объекта и основные атрибуты
{
"entityType": "Order",
"externalId": "ExternalOrder",
"attributes": {
"date": 1577869200,
"number": 514,
"title": "External Order v2",
"itemsRelation": [
"d1d70690-d972-4ee3-9ec1-ccd972979e72",
"05c989a2-74cc-4888-a49c-c160bf7f918a"
],
"personRelation": "18b1011b-9db3-4186-a53c-971016030068"
},
"createRelations": true
}
На выходе признак успешного сохранения
true
Изменение внешнего объекта.
Имя команды для вызова: updateExternalObject.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway), не требует аутентификации.
- На входе:
UpdateExternalEntityObject. - На выходе:
Boolean,true- обновление успешно,false- неуспешно.
SoftDeleteObject (Data-model command)
На входе ID получаемого объекта и его тип сущности
{
"entityType": "Order",
"objectId": "18b1011b-9db3-4186-a53c-971016030068"
}
На выходе признак успешного удаления
true
Или ошибка, если объекта не существует
{
"businessError": null,
"message": "ERROR: Entity object not found",
"stackTrace": null,
"data": null
}
Отмечает в БД объект сущности как удаленный.
Из-за этого файлы, ссылки и отношения, связанные с этим объектом, не будут участвовать в командах на получение данных (
кроме команд internalGetObject и
internalRichGetObject).
Генерируемые события будут созданы как и при обычном удалении.
Имя команды для вызова: softDeleteObject.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
- На входе:
EntityObjectIdentity. - На выходе:
Boolean,true- удаление успешно,false- неуспешно.
DeleteObject (Data-model command)
На входе ID получаемого объекта и его тип сущности
{
"entityType": "Order",
"objectId": "18b1011b-9db3-4186-a53c-971016030068"
}
На выходе признак успешного удаления
true
Или ошибка, если объекта не существует
{
"businessError": null,
"message": "ERROR: Entity object not found",
"stackTrace": null,
"data": null
}
Удаление объекта сущности. Если у объекта есть связи, они тоже будут удалены.
Имя команды для вызова: deleteObject.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
- На входе:
EntityObjectIdentity. - На выходе:
Boolean,true- удаление успешно,false- неуспешно.
SoftDeleteObjectBatch (Data-model command)
На входе список EntityObjectIdentity удаляемых объектов
[
{
"entityType": "Patent",
"objectId": "7cba68ef-10fe-4629-9680-3346e73756bd"
},
{
"entityType": "Document",
"objectId": "b7bb4a5a-dc0f-4bfc-b7e3-f2258700b47b"
}
]
На выходе количество успешно удаленных объектов, которые существовали на момент вызова команды
2
Отмечает в БД сущности из списка как удаленные.
Из-за этого файлы, ссылки и отношения, связанные с этими объектами, не будут участвовать в командах на получение
данных (кроме команд internalGetObject и
internalRichGetObject).
Генерируемые события будут созданы как и при обычном удалении.
Принцип работы команды аналогичен работе команды softDeleteObject.
Если входные данные для команды содержит идентификаторы объектов, которые не существуют (например, были удалены ранее
или были помечены как удаленные), то считаем что записи отсутствуют и возвращается ошибка с кодом NotFound.
Имя команды для вызова: softDeleteObjectBatch.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway), не требует аутентификации.
- На входе:
List[EntityObjectIdentity]. - На выходе: количество удаленных объектов.
DeleteObjectBatch (Data-model command)
На входе список EntityObjectIdentity удаляемых объектов
[
{
"entityType": "Patent",
"objectId": "7cba68ef-10fe-4629-9680-3346e73756bd"
},
{
"entityType": "Document",
"objectId": "b7bb4a5a-dc0f-4bfc-b7e3-f2258700b47b"
}
]
На выходе количество успешно удаленных объектов, которые существовали на момент вызова команды
2
Удаление объектов сущностей по списку. Если у объектов есть связи, они тоже будут удалены.
Если входные данные для команды содержит идентификаторы объектов, которые не существуют (например, были удалены ранее),
то считаем что записи отсутствуют и возвращается ошибка с кодом NotFound.
Позволяет удалять сущности помеченные на удаление.
Имя команды для вызова: deleteObjectBatch.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway), не требует аутентификации.
- На входе:
List[EntityObjectIdentity]. - На выходе: количество удаленных объектов.
SoftDeleteObjectSearch (Data-model command)
На входе EntityTypeId и Search для поиска удаляемых объектов
{
"entityType": "Patent",
"search": {
"query": "title",
"context": {
"title": "like %48588d61-6c76-48d0-9318-e9dcfcbe688d%"
}
}
}
На выходе количество успешно удаленных объектов
2
Или ошибка, если объекта (объектов) не существует
{
"businessError": null,
"message": "ERROR: 'Entity object' not found",
"stackTrace": null,
"data": null
}
Отмечает сущности полученные поиском по реестру как удаленные.
Из-за этого файлы, ссылки и отношения, связанные с этими объектами, не будут участвовать в командах на получение
данных (кроме команд internalGetObject и
internalRichGetObject).
Генерируемые события будут созданы как и при обычном удалении.
Если во входных данных есть пейджинг или сортировка, то они будут проигнорированы.
Имя команды для вызова: softDeleteObjectSearch.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
- На входе:
ListObjects. - На выходе: количество удаленных объектов.
DeleteObjectSearch (Data-model command)
На входе EntityTypeId и Search для поиска удаляемых объектов
{
"entityType": "Patent",
"search": {
"query": "title",
"context": {
"title": "like %48588d61-6c76-48d0-9318-e9dcfcbe688d%"
}
}
}
На выходе количество успешно удаленных объектов
2
Или ошибка, если объекта (объектов) не существует
{
"businessError": null,
"message": "ERROR: 'Entity object' not found",
"stackTrace": null,
"data": null
}
Удаление объектов сущности поиском по реестру.
Имя команды для вызова: deleteObjectSearch.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
- На входе:
ListObjects. - На выходе: количество удаленных объектов.
Запрос принимает параметры фильтров в параметре Search.
Применяется к полям модели ObjectStore.
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров |
|---|---|
id или objectid |
InSetQuery, LikeQuery |
externalid |
InSetQuery, LikeQuery |
title |
InSetQuery, LikeQuery |
source |
InSetQuery, LikeQuery |
created |
InSetQuery, LikeQuery, RangeQuery |
modified |
InSetQuery, LikeQuery, RangeQuery |
Для фильтрации по полям сущности подробности описаны тут.
DeleteExternalObject (Data-model command)
На входе внешний ID удаляемого объекта и его тип сущности
{
"entityType": "Order",
"externalId": "ExternalOrder"
}
На выходе признак успешного удаления
true
Удаление внешнего объекта сущности. Если у объекта есть связи, они тоже будут удалены.
Имя команды для вызова: deleteExternalObject.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway), не требует аутентификации.
- На входе:
EntityObjectExternalIdentity. - На выходе:
Boolean,true- удаление успешно,false- неуспешно.
SaveAdditionalInfo (Data-model command)
На входе дополнительные свойства сохраняемого объекта и его ID
{
"entityType": "Order",
"objectId": "18b1011b-9db3-4186-a53c-971016030068",
"additionalData": {
"keywords": [
"Договор",
"аренда",
"лошадь"
]
}
}
На выходе признак успешного сохранения
true
Сохранение дополнительных полей объекта сущности. Дополняет текущий список дополнительных полей новым. Если поле уже есть, тогда перезаписывает. Передавать полный список не нужно.
Имя команды для вызова: saveAdditionalInfo.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway), не требует аутентификации.
- На входе:
SaveObjectAdditionalInfo. - На выходе:
Boolean,true- обновление успешно,false- неуспешно.
SaveObjectMetadata (Data-model command)
На входе метаданные сохраняемого объекта и его ID
{
"entityType": "Order",
"objectId": "18b1011b-9db3-4186-a53c-971016030068",
"metadata": {
"warnings": [
{
"fieldCode": "code"
}
]
}
}
На выходе признак успешного сохранения
true
Сохранение метаданных объекта сущности. Полностью обновляет метаданные.
Имя команды для вызова: saveObjectMetadata.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway), не требует аутентификации.
- На входе:
SaveObjectMetadata. - На выходе:
Boolean,true- обновление успешно,false- неуспешно.
SaveObjectMetadataBatch (Data-model command)
На входе массив объектов с метаданными сохраняемых объектов и их ID
[
{
"entityType": "Tag",
"objectId": "7e02feee-3453-42b3-b990-1d9ec83fc0d8",
"metadata": {
"warnings": [
{
"fieldCode": "title"
}
]
}
},
{
"entityType": "Order",
"objectId": "18b1011b-9db3-4186-a53c-971016030068",
"metadata": {
"warnings": [
{
"fieldCode": "code"
}
]
}
}
]
На выходе признак успешного сохранения
true
Сохранение метаданных объектов сущностей батчем. Полностью обновляет метаданные.
Имя команды для вызова: saveObjectMetadataBatch.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway), не требует аутентификации.
- На входе:
List[SaveObjectMetadata]. - На выходе:
Boolean,true- обновление успешно,false- неуспешно. Записи в батче сохраняются транзакционно: cохраняются либо все элементы либо ни один. Если ответ командыtrue, то все элементы были успешно сохранены.
SaveFilesAdditionalInfo (Data-model command)
На входе информация о дополнительных файлах файловых полей
{
"entityType": "Order",
"objectId": "18b1011b-9db3-4186-a53c-971016030068",
"data": [
{
"field": "documentFile",
"key": "documentFileContent",
"files": {
"2155c943-5c30-49aa-bc43-28c7447b26eb": "datamodel/Order/47fdb0ce-4b1b-4338-ad9b-31ad5c9e2550"
}
}
]
}
На выходе количество обновленных файлов
1
Имя команды для вызова: saveFilesAdditionalInfo.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway), не требует аутентификации.
- На входе:
SaveFilesAdditionalInfo. - На выходе:
Intкол-во обновленных файлов.
SaveFilesAdditionalInfoV2 (Data-model command)
На входе информация о дополнительных файлах файловых полей
[
{
"key": "documentFileContent",
"files": {
"2155c943-5c30-49aa-bc43-28c7447b26eb": "datamodel/Order/47fdb0ce-4b1b-4338-ad9b-31ad5c9e2550"
}
},
{
"key": "anotherFileContent",
"files": {
"2155c943-5c30-49aa-bc43-28c7447b26eb": "datamodel/Order/47fdb0ce-4b1b-4338-ad9b-31ad5c9e2550"
}
}
]
На выходе количество обновленных файлов
2
Команда привязывает дополнительные файлы к исходным, добавляя их в поле additionalInfo.
В отличии от предыдущей версии, команда не требует указывать
данные объекта, к которому привязаны исходные файлы.
Имя команды для вызова: saveFilesAdditionalInfoV2.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway), не требует аутентификации.
- На входе:
List[SaveFilesAdditionalInfoV2]. - На выходе:
Intкол-во обновленных файлов.
ListObjects (Data-model command)
На входе тип сущности объектов и параметры спискового запроса
{
"entityType": "Order",
"search": {
"query": "",
"context": {},
"paging": {
"page": 1,
"count": 2
}
}
}
На выходе странца со списком объектов запрашиваемой сущности с учетом параметров и общее количество элементов
{
"items": [
{
"id": "18b1011b-9db3-4186-a53c-971016030068",
"externalId": "ExternalOrder",
"entityType": "Order",
"title": "Аренда лошади",
"source": "manual",
"created": 1630326492,
"modified": 1630326492,
"data": {
"date": 1577869200,
"number": 514,
"title": "Аренда лошади"
},
"additionalData": {
"keywords": "Договор, аренда, лошадь"
},
"metadata": {},
"version": 1,
"removed": false
},
{
"id": "cbf73923-e043-481e-97b2-8ec5968a10ca",
"externalId": null,
"entityType": "Order",
"title": "",
"source": "import",
"created": 1630567604,
"modified": 1630326492,
"data": {
"date": 1567330200,
"number": 321
},
"additionalData": {
"keywords": "Договор, вагон, паровоз"
},
"metadata": {},
"version": 1,
"removed": false
}
],
"total": 3
}
Получение списка объектов запрашиваемой сущности. Запрос принимает параметры сортировки, фильтров и пейджинга
в параметре Search.
Имя команды для вызова: listObjects.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе:
ListObjects. - На выходе:
Page[EntityObject].
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров |
|---|---|
id или objectid |
InSetQuery |
externalid |
InSetQuery |
title |
InSetQuery, LikeQuery |
source |
InSetQuery |
created |
InSetQuery, RangeQuery |
modified |
InSetQuery, RangeQuery |
Для фильтрации по полям сущности подробности описаны тут.
Доступные поля для сортировки:
| Поле | Примечание |
|---|---|
id или objectid |
- |
externalid |
- |
title |
- |
modified |
- |
created |
- |
source |
При сортировке по возрастанию сначала идут Manual, потом Auto. |
Если поле sorting отсутствует, то список сортируется по полю created в порядке возрастания.
Если fieldName не совпадает с вышеперечисленными, то список сортируется по этому полю в data.
InternalListObjects (Data-model command)
Имя команды для вызова: internalListObjects.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway).
Логика команды и вход/выход идентичен ListObjects command.
- На входе:
ListObjects. - На выходе:
Page[EntityObject].
RichListObjects (Data-model command)
На входе тип сущности объектов, список необходимых полей и параметры спискового запроса
{
"entityType": "Order",
"fields": [
"number",
"person.title"
],
"search": {
"query": "",
"context": {},
"paging": {
"page": 1,
"count": 2
}
},
"fieldSearches": {
"person": {
"query": "title",
"context": {
"title": "John"
}
}
}
}
На выходе странца со списком объектов запрашиваемой сущности с учетом параметров и общее количество элементов.
{
"items": [
{
"id": "18b1011b-9db3-4186-a53c-971016030068",
"externalId": "ExternalOrder",
"entityType": "Order",
"title": "Аренда лошади",
"source": "manual",
"created": 1630326492,
"modified": 1630326492,
"data": {
"number": 514,
"person": {
"_id": "478bf14a-b1f9-46d4-b7fb-3b7ff3d8ca79",
"_externalId": null,
"_entityType": "Person",
"_title": "John",
"_source": "manual",
"_created": 1634553248859,
"_modified": 1634553248859,
"_version": 1
}
},
"additionalData": {
"keywords": "Договор, аренда, лошадь"
},
"metadata": {},
"version": 1,
"removed": false
},
{
"id": "cbf73923-e043-481e-97b2-8ec5968a10ca",
"externalId": null,
"entityType": "Order",
"title": "",
"source": "import",
"created": 1630567604,
"modified": 1630326492,
"data": {
"number": 321,
"person": null
},
"additionalData": {
"keywords": "Договор, вагон, паровоз"
},
"metadata": {},
"version": 1,
"removed": false
}
],
"total": 3
}
Получение списка объектов запрашиваемой сущности. В JSON объекте data, для каждого объекта содержатся только
указанные в запросе поля.
Запрос принимает параметры сортировки, фильтров и пейджинга в параметре Search.
Для фильтрации/сортировки по relation полям см. Relation поля.
Для указания списка допустимых полей см. Методы Rich*.
Имя команды для вызова: richListObjects.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе:
RichListObjects. - На выходе:
Page[EntityObject].
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров |
|---|---|
id или objectid |
InSetQuery |
externalid |
InSetQuery |
title |
InSetQuery, LikeQuery |
source |
InSetQuery |
created |
InSetQuery, RangeQuery |
modified |
InSetQuery, RangeQuery |
Для фильтрации по полям сущности подробности описаны тут.
Доступные поля для сортировки:
| Поле | Примечание |
|---|---|
id или objectid |
- |
externalid |
- |
title |
- |
modified |
- |
created |
- |
source |
При сортировке по возрастанию сначала идут Manual, потом Auto. |
Если поле sorting отсутствует, то список сортируется по полю created в порядке возрастания.
InternalRichListObjects (Data-model command)
Имя команды для вызова: internalRichListObjects.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway).
Логика команды и вход/выход идентичен RichListObjects command.
ListObjectsMeta (Data-model command)
На входе тип сущности объектов и параметры спискового запроса
{
"entityType": "Order",
"search": {
"query": "",
"context": {},
"paging": {
"page": 1,
"count": 2
}
}
}
На выходе странца со списком объектов запрашиваемой сущности с учетом параметров и общее количество элементов
{
"items": [
{
"id": "18b1011b-9db3-4186-a53c-971016030068",
"entityType": "Order",
"title": "Аренда лошади",
"source": "manual",
"created": 1630326492,
"modified": 1630326492,
"version": 1,
"removed": false
},
{
"id": "cbf73923-e043-481e-97b2-8ec5968a10ca",
"entityType": "Order",
"title": "",
"source": "import",
"created": 1630567604,
"modified": 1630326492,
"version": 1,
"removed": false
}
],
"total": 3
}
Получение списка метаданных объектов запрашиваемой сущности. Запрос принимает параметры сортировки, фильтров и пейджинга
в параметре Search.
Имя команды для вызова: listObjectsMeta.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе:
ListObjects. - На выходе:
Page[EntityObjectMeta].
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров |
|---|---|
id или objectid |
InSetQuery |
externalid |
InSetQuery |
title |
InSetQuery, LikeQuery |
source |
InSetQuery |
created |
InSetQuery, RangeQuery |
modified |
InSetQuery, RangeQuery |
Для фильтрации по полям сущности подробности описаны тут.
Доступные поля для сортировки:
| Поле | Примечание |
|---|---|
id или objectid |
- |
externalid |
- |
title |
- |
modified |
- |
created |
- |
source |
При сортировке по возрастанию сначала идут Manual, потом Auto. |
Если поле sorting отсутствует, то список сортируется по полю created в порядке возрастания.
Если fieldName не совпадает с вышеперечисленными, то список сортируется по этому полю в data.
ListObjectTitles (Data-model command)
На входе параметры спискового запроса
{
"query": "",
"context": {},
"paging": {
"page": 1,
"count": 2
}
}
На выходе страница со списком объектов запрашиваемой сущности с учетом параметров и общее количество элементов
{
"items": [
{
"entityType": "Order",
"objectId": "18b1011b-9db3-4186-a53c-971016030068",
"title": "Аренда лошади"
},
{
"entityType": "Order",
"objectId": "cbf73923-e043-481e-97b2-8ec5968a10ca",
"title": ""
}
],
"total": 3
}
Получение списка наименований объектов с учетом параметров сортировки, фильтров и пейджинга.
Имя команды для вызова: listObjectTitles.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе:
Search. - На выходе:
Page[TitledEntityObjectIdentity].
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров |
|---|---|
id или objectid |
InSetQuery |
externalid |
InSetQuery |
title |
InSetQuery, LikeQuery |
source |
InSetQuery |
created |
InSetQuery, RangeQuery |
modified |
InSetQuery, RangeQuery |
Для фильтрации по полям сущности подробности описаны тут.
Доступные поля для сортировки:
| Поле | Примечание |
|---|---|
id или objectid |
- |
externalid |
- |
title |
- |
modified |
- |
created |
- |
source |
При сортировке по возрастанию сначала идут Manual, потом Auto. |
Если поле sorting отсутствует, то список сортируется по полю created в порядке возрастания.
Если fieldName не совпадает с вышеперечисленными, то список сортируется по этому полю в data.
ListObjectTitlesV2 (Data-model command)
На входе тип сущности объектов и параметры спискового запроса
{
"entityType": "Order",
"search": {
"query": "",
"context": {},
"paging": {
"page": 1,
"count": 2
}
}
}
На выходе страница со списком объектов запрашиваемой сущности с учетом параметров и общее количество элементов
{
"items": [
{
"entityType": "Order",
"objectId": "18b1011b-9db3-4186-a53c-971016030068",
"title": "Аренда лошади"
},
{
"entityType": "Order",
"objectId": "cbf73923-e043-481e-97b2-8ec5968a10ca",
"title": ""
}
],
"total": 3
}
Получение списка наименований объектов с учетом параметров сортировки, фильтров и пейджинга.
Имя команды для вызова: listObjectTitlesV2.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе:
ListObjects. - На выходе:
Page[TitledEntityObjectIdentity].
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров |
|---|---|
id или objectid |
InSetQuery |
externalid |
InSetQuery |
title |
InSetQuery, LikeQuery |
source |
InSetQuery |
created |
InSetQuery, RangeQuery |
modified |
InSetQuery, RangeQuery |
Для фильтрации по полям сущности подробности описаны тут.
Доступные поля для сортировки:
| Поле | Примечание |
|---|---|
id или objectid |
- |
externalid |
- |
title |
- |
modified |
- |
created |
- |
source |
При сортировке по возрастанию сначала идут Manual, потом Auto. |
Если поле sorting отсутствует, то список сортируется по полю created в порядке возрастания.
Если fieldName не совпадает с вышеперечисленными, то список сортируется по этому полю в data.
GetObjectPosition (Data-model command)
На входе тип сущности объекта, ID искомого объекта и параметры спискового запроса
{
"entityType": "Order",
"objectId": "cbf73923-e043-481e-97b2-8ec5968a10ca",
"search": {
"query": "",
"context": {},
"sorting": "title"
}
}
На выходе позиция объекта в отфильтрованном и отсортированном списке, начиная с 0:
{
"position": 1,
"total": 3
}
Получение позиции объекта в списке объектов, с учетом фильтрации и сортировки.
Имя команды для вызова: getObjectPosition.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе:
GetObjectPosition. - На выходе:
PositionInList.
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров |
|---|---|
id или objectid |
InSetQuery |
externalid |
InSetQuery |
title |
InSetQuery, LikeQuery |
source |
InSetQuery |
created |
InSetQuery, RangeQuery |
modified |
InSetQuery, RangeQuery |
Для фильтрации по полям сущности подробности описаны тут.
Доступные поля для сортировки:
| Поле | Примечание |
|---|---|
id или objectid |
- |
externalid |
- |
title |
- |
modified |
- |
created |
- |
source |
При сортировке по возрастанию сначала идут Manual, потом Auto. |
Если поле sorting отсутствует, то список сортируется по полю created в порядке возрастания.
Если fieldName не совпадает с вышеперечисленными, то список сортируется по этому полю в data.
ListNonExistingFileId (Data-model command)
На входе список идентификаторов
ObjectFileMeta, которые нужно проверить на наличие
[
"00001111-2222-3333-4444-555566667777",
"184c85c1-9c75-48aa-8052-e96fe29cc026"
]
На выходе список идентификаторов, которые отсутствуют в БД
[
"00001111-2222-3333-4444-555566667777"
]
Внутренняя команда для получения списка ID файлов, которые отсутствуют в сервисе.
Необходима для фильтрации данных полученных из LAMP командами сервиса fullTextSearch: plagiarismSearchV2 и
similaritySearchV2.
Имя команды для вызова: listNonExistingFileId.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: массив
UUID(ObjectFileMeta.fileId). - На выходе: массив
UUID(ObjectFileMeta.fileId).
GetEntityFieldAggregation (Data-model command)
На входе тип сущности, параметры фильтрации, и перечень полей по которым требуется агрегация
{
"entityType": "Order",
"search": {
"query": "",
"context": {}
},
"fields": [
"title"
]
}
На выходе статистика значений указанных полей с учетом фильтрации
{
"title": [
{
"value": "Договор",
"count": 5
},
{
"value": "Заявление",
"count": 10
}
]
}
Получение статистики полей модели данных.
Имя команды для вызова: getEntityFieldAggregation.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе:
GetEntityFieldAggregation. - На выходе: object, где ключи - наименования полей, а значения -
List[FieldAggregatedValue].
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров |
|---|---|
id или objectid |
InSetQuery |
externalid |
InSetQuery |
title |
InSetQuery, LikeQuery |
source |
InSetQuery |
created |
InSetQuery, RangeQuery |
modified |
InSetQuery, RangeQuery |
Для фильтрации по полям сущности подробности описаны тут.
SaveRelation (Data-model command)
На входе параметры сущности, отношение между которыми сохраняется, а также ID конкретных объектов, входящих в отношение
{
"entity1Type": "Order",
"entity2Type": "Item",
"entity1Field": "items",
"object1Id": "18b1011b-9db3-4186-a53c-971016030068",
"object2Id": "48911128-39a1-418c-93f1-c9773cda224e",
"source": "manual"
}
На выходе признак успешного сохранения
true
Сохранение отношения между объектами двух сущностей.
Имя команды для вызова: saveRelation.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
- На входе:
AddObjectRelation. - На выходе:
Boolean,true- сохранение успешно,false- неуспешно.
InternalSaveRelation (Data-model command)
Сохранение отношения между объектами двух сущностей.
Логика и вход/выход такие же как в SaveRelation.
Имя команды для вызова: internalSaveRelation.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway).
- На входе:
AddObjectRelation. - На выходе:
Boolean,true- сохранение успешно,false- неуспешно.
SaveRelationBatch (Data-model command)
На входе массив параметров сущностей, отношение между которыми сохраняется, а также ID конкретных объектов, входящих в отношение
[
{
"entity1Type": "Order",
"entity2Type": "Item",
"entity1Field": "items",
"object1Id": "18b1011b-9db3-4186-a53c-971016030068",
"object2Id": "48911128-39a1-418c-93f1-c9773cda224e",
"source": "manual"
},
{
"entity1Type": "Person",
"entity2Type": "Item",
"entity1Field": "items",
"object1Id": "d1d70690-d972-4ee3-9ec1-ccd972979e72",
"object2Id": "05c989a2-74cc-4888-a49c-c160bf7f918a",
"source": "manual"
}
]
На выходе перечень результатов сохранения для каждого отдельного отношения
[
{
"relation": {
"entity1Type": "Order",
"entity2Type": "Item",
"entity1Field": "items",
"object1Id": "18b1011b-9db3-4186-a53c-971016030068",
"object2Id": "48911128-39a1-418c-93f1-c9773cda224e",
"source": "manual"
},
"result": true
},
{
"relation": {
"entity1Type": "Person",
"entity2Type": "Item",
"entity1Field": "items",
"object1Id": "d1d70690-d972-4ee3-9ec1-ccd972979e72",
"object2Id": "05c989a2-74cc-4888-a49c-c160bf7f918a",
"source": "manual"
},
"result": false,
"error": "Relation between Person and Item does not exist "
}
]
Сохранение нескольких отношений между объектами двух сущностей.
Имя команды для вызова: saveRelationBatch.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
- На входе:
List[AddObjectRelation]. - На выходе:
List[AddObjectRelationResult].
InternalSaveRelationBatch (Data-model command)
Сохранение нескольких отношений между объектами двух сущностей.
Логика и вход/выход такие же как в SaveRelationBatch.
Имя команды для вызова: internalSaveRelationBatch.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway).
- На входе:
List[AddObjectRelation]. - На выходе:
List[AddObjectRelationResult].
GetRelation (Data-model command)
На входе параметры сущности, а также ID конкретных объектов, входящих в отношение
{
"entity1Type": "Order",
"entity2Type": "Item",
"entity1Field": "items",
"object1Id": "18b1011b-9db3-4186-a53c-971016030068",
"object2Id": "48911128-39a1-418c-93f1-c9773cda224e"
}
На выходе найденное отношение
{
"entity1Type": "Order",
"entity2Type": "Item",
"entity1Field": "items",
"entity2Field": "order",
"object1Id": "18b1011b-9db3-4186-a53c-971016030068",
"object2Id": "48911128-39a1-418c-93f1-c9773cda224e",
"source": "test"
}
Или ошибка, если отношения не существует
{
"businessError": null,
"message": "ERROR: Entity object not found",
"stackTrace": null,
"data": null
}
Получение отношения между объектами двух сущностей.
Имя команды для вызова: getRelation.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе:
DeleteObjectRelation. - На выходе:
ObjectRelation.
ListRelations (Data-model command)
На входе параметры объекта и сущности, для которых нужно получить отношения
{
"entityType": "Order",
"objectId": "48911128-39a1-418c-93f1-c9773cda224e",
"relatedEntityType": "Person",
"fieldName": "Author",
"reversed": false,
"paging": null
}
На выходе список отношений объекта с указанной сущностью
[
{
"id": "134b960a-922d-4bca-b1e8-072de5a5efc1",
"entityType1": "Order",
"entityType2": "Person",
"entity1Field": "author",
"entity2Field": "orders",
"object1Id": "48911128-39a1-418c-93f1-c9773cda224e",
"object2Id": "83a7a3e9-ab24-4e83-b8e9-7470136aeb57",
"source": "manual"
}
]
Получение всех отношений объекта с указанной сущностью.
Имя команды для вызова: listRelations.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе:
ListObjectRelations. - На выходе:
List[ObjectRelation].
ListRelationsBatch (Data-model command)
На входе перечень параметров объекта и сущности, для которых нужно получить отношения
[
{
"entityType": "Order",
"objectId": "48911128-39a1-418c-93f1-c9773cda224e",
"relatedEntityType": "Person",
"fieldName": "Author",
"reversed": false,
"paging": null
}
]
На выходе список отношений указанных объектов с указанными для них сущностями
[
{
"id": "134b960a-922d-4bca-b1e8-072de5a5efc1",
"entityType1": "Order",
"entityType2": "Person",
"entity1Field": "author",
"entity2Field": "orders",
"object1Id": "48911128-39a1-418c-93f1-c9773cda224e",
"object2Id": "83a7a3e9-ab24-4e83-b8e9-7470136aeb57",
"source": "manual"
}
]
Аналогично ListRelations, но массовое. Порядок relation-ов в ответе совпадает с
порядком
идентификаторов в запросе.
Имя команды для вызова: listRelationsBatch.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе:
List[ListObjectRelations]. - На выходе:
List[ObjectRelation].
ListAllRelations (Data-model command)
На входе параметры объекта, для которого нужно получить все отношения
{
"entityType": "Order",
"objectId": "48911128-39a1-418c-93f1-c9773cda224e"
}
На выходе список отношений объекта
[
{
"id": "134b960a-922d-4bca-b1e8-072de5a5efc1",
"entityType1": "Order",
"entityType2": "Person",
"entity1Field": "author",
"entity2Field": "orders",
"object1Id": "48911128-39a1-418c-93f1-c9773cda224e",
"object2Id": "83a7a3e9-ab24-4e83-b8e9-7470136aeb57",
"source": "manual"
}
]
Получение всех отношений объекта.
Имя команды для вызова: listAllRelations.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе:
EntityObjectIdentity. - На выходе:
List[ObjectRelation].
DeleteRelation (Data-model command)
На входе параметры сущности, отношение между которыми удаляется, а также ID конкретных объектов, входящих в отношение
{
"entity1Type": "Order",
"entity2Type": "Item",
"entity1Field": "items",
"object1Id": "18b1011b-9db3-4186-a53c-971016030068",
"object2Id": "48911128-39a1-418c-93f1-c9773cda224e"
}
На выходе признак успешного удаления отношения
true
Или ошибка, если отношения не существует
{
"businessError": null,
"message": "ERROR: Entity object not found",
"stackTrace": null,
"data": null
}
Удаление отношения между объектами двух сущностей.
Имя команды для вызова: deleteRelation.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
- На входе:
DeleteObjectRelation. - На выходе:
Boolean,true- удаление успешно,false- неуспешно.
DeleteRelations (Data-model command)
На входе параметры объекта, для которого нужно удалить отношения, и перечень связных сущностей
{
"entityType": "Order",
"objectId": "48911128-39a1-418c-93f1-c9773cda224e",
"relatedEntityTypes": [
"Person"
]
}
На выходе список удаленных отношений
[
{
"id": "134b960a-922d-4bca-b1e8-072de5a5efc1",
"entityType1": "Order",
"entityType2": "Person",
"entity1Field": "author",
"entity2Field": "orders",
"object1Id": "48911128-39a1-418c-93f1-c9773cda224e",
"object2Id": "83a7a3e9-ab24-4e83-b8e9-7470136aeb57",
"source": "manual"
}
]
Удаление отношений объекта с перечисленными сущностями.
Имя команды для вызова: deleteRelations.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
- На входе:
DeleteObjectRelations. - На выходе:
List[ObjectRelation].
DeleteAllRelations (Data-model command)
На входе параметры объекта, для которого нужно удалить все отношения
{
"entityType": "Order",
"objectId": "48911128-39a1-418c-93f1-c9773cda224e"
}
На выходе список удаленных отношений
[
{
"id": "134b960a-922d-4bca-b1e8-072de5a5efc1",
"entityType1": "Order",
"entityType2": "Person",
"entity1Field": "author",
"entity2Field": "orders",
"object1Id": "48911128-39a1-418c-93f1-c9773cda224e",
"object2Id": "83a7a3e9-ab24-4e83-b8e9-7470136aeb57",
"source": "manual"
}
]
Удаление всех отношений объекта.
Имя команды для вызова: deleteAllRelations.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
- На входе:
EntityObjectIdentity. - На выходе:
List[ObjectRelation].
UpdateExternalRelations (Data-model command)
На входе поля для идентификации связи, и ID объектов, между которыми устанавливается связь
{
"entity1Type": "Order",
"entity2Type": "Item",
"entity1Field": "items",
"objectId": "Order1",
"reversed": false,
"relatedObjectIds": [
"Item1",
"Item2"
],
"source": "manual"
}
На выходе перечень результатов сохранения для каждого отдельного отношения
[
{
"relatedObjectId": "Item1",
"success": true
},
{
"relatedObjectId": "Item2",
"success": false,
"error": "Not found object with entity type Item and id Item2"
}
]
Обновление списка отношений одного объекта с указанной сущностью.
Команда полностью заменяет список отношений объекта; таким образом, указанные в теле команды отношения будут созданы, а
не указанные — удалены.
Имя команды для вызова: updateExternalRelations.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway), не требует аутентификации.
- На входе:
UpdateExternalObjectRelations. - На выходе:
List[UpdateExternalObjectRelationResult].
ReindexObject (Data-model command)
На входе ID объекта и его тип сущности
{
"entityType": "Order",
"objectId": "18b1011b-9db3-4186-a53c-971016030068"
}
На выходе признак успешной отправки события переиндексации
true
Имя команды для вызова: reindexObject.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
- На входе:
EntityObjectIdentity. - На выходе:
Boolean.
GetObjectLink (Data-model command)
На входе ID получаемой связи
"4faf020e-d0f6-4cb7-ab54-8412d50a28f4"
На выходе данные запрашиваемой связи между объектами
{
"id": "4faf020e-d0f6-4cb7-ab54-8412d50a28f4",
"entityType1": "Order",
"object1Id": "18b1011b-9db3-4186-a53c-971016030068",
"entityType2": "Act",
"object2Id": "e776d20e-28ec-4e90-87d2-35962d7ca60e",
"linkType": "plagiarism",
"source": "auto",
"owner": "plagiarism_mapper",
"additional": {
"intersections": 0.85
}
}
Получение связи между объектами по ID.
Имя команды для вызова: getObjectLink.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе:
UUID. - На выходе:
ObjectLink.
GetObjectLinks (Data-model command)
На входе объект, связи которого нужно получить, список типов связей, и признак прямой или обратной связи
{
"entityType": "Document",
"objectId": "18b1011b-9db3-4186-a53c-971016030068",
"forwardLinks": true
}
На выходе список связей запрашиваемого объекта
[
{
"id": "4faf020e-d0f6-4cb7-ab54-8412d50a28f4",
"entityType1": "Order",
"object1Id": "18b1011b-9db3-4186-a53c-971016030068",
"entityType2": "Act",
"object2Id": "e776d20e-28ec-4e90-87d2-35962d7ca60e",
"linkType": "plagiarism",
"source": "auto",
"owner": "plagiarism_mapper",
"additional": {
"intersections": 0.85
}
},
{
"id": "b9841e89-1e05-4519-8b0e-f15804410039",
"entityType1": "Order",
"object1Id": "18b1011b-9db3-4186-a53c-971016030068",
"entityType2": "Act",
"object2Id": "e776d20e-28ec-4e90-87d2-35962d7ca60e",
"linkType": "similarity",
"source": "auto",
"owner": "faiss_similarity",
"additional": {
"similarity": 0.33
}
}
]
Получение всех связей объекта. Объект идентифицируется его ID и типом сущности. Можно указать список типов связи, тогда вернутся связи только указанных типов. Если этот список пустой или отсутствует, тогда вернутся все связи. Обязательно указывать направление связи (все связи всегда направленные). Прямое направление показывает, что искомый объект ищется среди первого узла связи (entity1), а обратное - среди второго (entity2).
Имя команды для вызова: getObjectLinks.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе:
GetObjectLinksList. - На выходе:
List[ObjectLink].
ListRelationsByType (Data-model command)
На входе название поля связи и типы объектов, между которыми нужно получить связи
{
"entityFrom": "ProjectParticipant",
"entityTo": "Project",
"field": "project"
}
На выходе список всех связей для указанных типов с данными об объектах
{
"items": [
{
"id": "4faf020e-d0f6-4cb7-ab54-8412d50a28f4",
"entityType1": "ProjectParticipant",
"object1": {
"id": "d4db2633-62c7-4b61-956d-cb5461fe2a3e",
"externalId": "0000000000000000",
"entityType": "ProjectParticipant",
"title": "Order d4db2633-62c7-4b61-956d-cb5461fe2a3e",
"source": "example",
"created": 1630326492,
"modified": 1630326492,
"data": {
"date": 1577869200,
"number": 555,
"author": "00000000-0000-0000-0000-000000000000"
},
"additionalData": {},
"version": 1
},
"entityType2": "Project",
"object2": {
"id": "d4db2633-62c7-4b61-956d-cb5461fe2a3e",
"externalId": "0000000000000000",
"entityType": "Project",
"title": "Order d4db2633-62c7-4b61-956d-cb5461fe2a3e",
"source": "example",
"created": 1630326492,
"modified": 1630326492,
"data": {
"date": 1577869200,
"number": 555,
"author": "00000000-0000-0000-0000-000000000000"
},
"additionalData": {},
"version": 1
},
"linkType": "plagiarism",
"source": "auto"
}
],
"total": 1
}
Получение всех связей между указанными типами.
Имя команды для вызова: listRelationsByType.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе:
GetObjectRelationsByType. - На выходе:
Page[ObjectLinkWithObjects].
CreateObjectLink (Data-model command)
На входе параметры создаваемой связи
{
"entityType1": "Order",
"object1Id": "18b1011b-9db3-4186-a53c-971016030068",
"entityType2": "Act",
"object2Id": "e776d20e-28ec-4e90-87d2-35962d7ca60e",
"linkType": "plagiarism",
"source": "auto",
"owner": "plagiarism_mapper",
"additional": {
"intersections": 0.85
}
}
На выходе ID созданной связи
"4faf020e-d0f6-4cb7-ab54-8412d50a28f4"
Создание связи между объектами. Уникальность связи определяется набором полей: entityType1, object1Id, entityType2, object2Id, linkType, source.
Имя команды для вызова: createObjectLink.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
- На входе:
CreateObjectLink. - На выходе:
UUID.
CreateObjectsLinks (Data-model command)
На входе список создаваемых связей
[
{
"entityType1": "Order",
"object1Id": "18b1011b-9db3-4186-a53c-971016030068",
"entityType2": "Act",
"object2Id": "e776d20e-28ec-4e90-87d2-35962d7ca60e",
"linkType": "plagiarism",
"source": "auto",
"owner": "plagiarism_mapper",
"additional": {
"intersections": 0.85
}
},
{
"entityType1": "Order",
"object1Id": "18b1011b-9db3-4186-a53c-971016030068",
"entityType2": "Act",
"object2Id": "da2cf038-973a-4202-a4ac-0bab6960c30c",
"linkType": "plagiarism",
"source": "auto",
"owner": "plagiarism_mapper",
"additional": {
"intersections": 0.85
}
}
]
На выходе количество созданных связей
2
Создание связей между объектами.
Имя команды для вызова: createObjectsLinks.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway), не требует аутентификации.
- На входе:
List[CreateObjectLink]. - На выходе:
Int.
DeleteObjectLink (Data-model command)
На входе ID удаляемой связи
"4faf020e-d0f6-4cb7-ab54-8412d50a28f4"
На выходе признак успешного удаления
true
Или ошибка, если связи не существует не существует
{
"businessError": null,
"message": "ERROR: Entity object not found",
"stackTrace": null,
"data": null
}
Удаление связи между объектами по ID.
Имя команды для вызова: deleteObjectLink.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
- На входе:
UUID. - На выходе:
Boolean,true- удаление успешно,false- неуспешно.
DeleteAllObjectLinks (Data-model command)
На входе параметры объекта и его связей для удаления (тип сущности, ID объекта, необязательный тип связей и признак прямых или обратных связей)
{
"entityType": "Document",
"objectId": "18b1011b-9db3-4186-a53c-971016030068",
"linkType": "plagiarism",
"forwardLinks": true
}
На выходе количество удаленных ссылок
3
Или ошибка, если объекта не существует не существует
{
"businessError": null,
"message": "ERROR: Entity object not found",
"stackTrace": null,
"data": null
}
Удаление связей объекта. Объект идентифицируется его ID и типом сущности. Можно опционально выбрать только связи
определенного типа. Обязательно указывать направление связи (все связи всегда направленные). Прямое направление
показывает,
что искомый объект ищется среди первого узла связи (entity1), а обратное - среди второго (entity2).
Имя команды для вызова: deleteAllObjectLinks.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
- На входе:
DeleteObjectLinks. - На выходе:
Int, количество удаленных ссылок.
ListFilesInfoWithTags (Data-model command)
На входе параметры для поиска файлов (фильтры, сортировка, номер страницы)
{
"query": "name",
"context": {
"code": "like Doc1%"
},
"sorting": null,
"paging": null
}
На выходе результат поиска файлов по переданным параметрам
{
"items": [
{
"objectIdentity": {
"entityType": "Document",
"objectId": "18b1011b-9db3-4186-a53c-971016030068"
},
"entityTypeTitle": "Документ",
"objectTitle": "Document 54a4da2d-05da-448e-88af-b44757ceef40",
"fileInfo": {
"fileId": "54a4da2d-05da-448e-88af-b44757ceef40",
"size": 11830,
"name": "Doc1.docx",
"extension": "docx",
"url": "datamodel/Document/54a4da2d-05da-448e-88af-b44757ceef40",
"additional": {},
"created": 1636378607649,
"modified": 1636378607649,
"md5": "7EF292CD265BC138C92F069CCF08D32C"
},
"tags": [
"TextFile",
"DocxFile"
]
}
],
"total": 1
}
Возвращает список файлов с подробной информацией о файле, тегах данного файла и родительском объекте.
Имя команды для вызова: listFilesInfoWithTags.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе:
Search. - На выходе:
Page[FileInfoWithTags].
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров |
|---|---|
fileId |
InSetQuery |
size |
InSetQuery |
name |
InSetQuery, LikeQuery |
extension |
InSetQuery, LikeQuery |
url |
InSetQuery, LikeQuery |
created |
InSetQuery, RangeQuery |
modified |
InSetQuery, RangeQuery |
md5 |
InSetQuery |
Доступные поля для сортировки:
| Поле |
|---|
size |
name |
extension |
url |
modified |
Если поле sorting отсутствует, то список сортируется по полю created в порядке возрастания.
Если поле paging отсутствует, то будет применено ограничение по-умолчанию { "page": 1, "count": 10 }.
ListTagsWithFilesCount (Data-model command)
На входе фильтры для поиска файлов
{
"query": "name",
"context": {
"code": "like Doc1%"
},
"sorting": null,
"paging": null
}
На выходе список тегов с количеством привязанных файлов, которые были найдены по переданным параметрам
{
"TextFile": 1,
"NULL": 10
}
Возвращает список тегов с количеством файлов.
Теги попадают в список, только если есть хотя бы один файл с таким тегом.
Если есть файлы, которые не привязаны ни к одному тегу,
будет добавлен тег NULL с количеством таких файлов.
Имя команды для вызова: listTagsWithFilesCount.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе:
Search(поляsortingиpagingдля данной команды не используются). - На выходе:
Map[String, Int]Список пар из названия тега и количества привязанных файлов.
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров |
|---|---|
fileId |
InSetQuery |
size |
InSetQuery |
name |
InSetQuery, LikeQuery |
extension |
InSetQuery, LikeQuery |
url |
InSetQuery, LikeQuery |
created |
InSetQuery, RangeQuery |
modified |
InSetQuery, RangeQuery |
md5 |
InSetQuery |
Сортировка и пагинация для данной команды не применяются.
ListFileExtensions (Data-model command)
На входе никаких параметры не требуется
null
На выходе список уникальных расширений загруженных в систему файлов
[
"docx",
"txt",
"pdf"
]
Возвращает список уникальных расширений загруженных в систему файлов.
Имя команды для вызова: listFileExtensions.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе:
NULL. - На выходе:
List[String]Список расширений файлов.
WriteFileTags (Data-model command)
На входе список идентификаторов файла с новыми тегами
[
{
"fileId": "54a4da2d-05da-448e-88af-b44757ceef40",
"tags": [
"TextFile",
"DocxFile"
]
}
]
На выходе количество записаных тегов
2
Перезаписывает текущие теги файла объекта новым списком, полученным в параметрах команды.
Имя команды для вызова: writeFileTags.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
- На входе:
List[ObjectFileWithTags]. - На выходе:
Int.
RemoveFileTags (Data-model command)
На входе список идентификаторов файлов с тегами, которые нужно удалить
[
{
"fileId": "54a4da2d-05da-448e-88af-b44757ceef40",
"tags": [
"DocxFile"
]
}
]
На выходе количество успешно удаленных тегов
1
Удаляет из текущего набора тегов для файла объекта те теги, которые переданы в параметрах команды.
Имя команды для вызова: removeFileTags.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
- На входе:
List[ObjectFileWithTags]. - На выходе:
Int.
RemoveAllFileTags (Data-model command)
На входе список идентификаторов файла
[
"54a4da2d-05da-448e-88af-b44757ceef40"
]
На выходе количество успешно удаленных тегов
2
Удаляет все теги для указанных файлов.
Имя команды для вызова: removeAllFileTags.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
- На входе:
List[String]. - На выходе:
Int.
GetEntityParents (Data-model command)
На входе код типа сущностей
"RfbrDocument"
На выходе все родительские сущности
[
{
"entityType": "Patent",
"fieldId": "patent",
"nested": [
{
"entityType": "links",
"fieldId": "links",
"nested": []
}
]
},
{
"entityType": "1thesis",
"fieldId": "thesis",
"nested": []
}
]
Имя команды для вызова: getEntityParents.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе:
String. - На выходе:
List[ParentRelation].
GetFile (Data-model command)
На входе полный идентификатор файла
{
"fileId": "54a4da2d-05da-448e-88af-b44757ceef40",
"entityType": "1thesis",
"objectId": "54a4da2d-05da-448e-88af-b44757ceef40"
}
На выходе информация о файле (предназначена только для сервиса api-gateway)
{
"id": "1c689788-9617-4c93-bcee-6eae8909a0ba",
"path": "temp/1c689788-9617-4c93-bcee-6eae8909a0ba",
"bucket": "temp"
}
Данная команда предназначена для скачивания файла после проверки прав.
Имя команды для вызова: getFile.
Поддерживается только синхронный вызов.
Результат выполнения команды журналируется.
- На входе:
FileIdentity. - На выходе:
StoredFile.
Скачивание файла (Data-model)
Эта команда имеет тип возвращаемого значения "файл". Она все еще возвращает JSON, но с помощью информации в этом JSON сервис apigateway вернет содержимое файла при успешном выполнении (но при ошибке будет возвращен JSON). В итоге чтобы скачать файл надо просто вызвать эту команду через apigateway.
UpdateKeywords (Data-model command)
На входе тип и идентификатор объекта и список его ключевых слов (фраз)
{
"entityType": "Patent",
"objectId": "6f1c4255-952b-4b5c-b463-3fd1662ccd4e",
"keywords": [
{
"keyword": "Сталь",
"pos": "NOUN",
"weight": 0.94
},
{
"keyword": "Дерево",
"pos": "NOUN",
"weight": 0.78
},
{
"keyword": "бронзА и олово",
"pos": "NOUN",
"weight": 1
}
]
}
На выходе количество созданных связей между ключевым словом и объектом
3
Перезаписывает текущие ключевые слова объекта новым списком слов, полученным в параметрах команды. Так же новые ключевые слова добавляются в реестр ключевых слов. Все слова приводятся к нижнему регистру.
Имя команды для вызова: updateKeywords.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway), не требует аутентификации.
- На входе:
ObjectWithKeywordsDTO. - На выходе:
Int.
ListObjectKeywords (Data-model command)
На входе тип и идентификатор объекта
{
"entityType": "Patent",
"objectId": "8505d418-371f-466e-9cb3-6a8cbbf7a610"
}
На выходе объект с ключевыми словами
{
"objectId": "8505d418-371f-466e-9cb3-6a8cbbf7a610",
"keywords": [
{
"keywordId": "894c334c-cd9d-4e9a-9ecd-d35623412ad6",
"keyword": "сталь",
"pos": "NOUN",
"weight": 1.0
},
{
"keywordId": "fce6be0f-a2ca-4f9d-92ff-0aaa4c8cb2b8",
"keyword": "пластик",
"pos": "NOUN",
"weight": 0.78
}
]
}
Команда позволяет по типу и идентификатору объекта получить его ключевые слова.
Имя команды для вызова: listObjectKeywords.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
- На входе:
EntityObjectIdentity. - На выходе:
ObjectWithKeywords.
ListKeywords (Data-model command)
На входе параметры поискового запроса (объект Search)
{
"query": "title",
"context": {
"title": "like %ронза%"
},
"paging": {
"page": 1,
"count": 10
}
}
На выходе страница найденых ключевых слов
{
"items": [
{
"id": "ebad64c4-9fa4-450d-bb49-94aa439a7289",
"title": "бронза",
"pos": "NOUN"
},
{
"id": "434e6425-774c-43b3-b94c-40bd4ee869f2",
"title": "бронза и олово",
"pos": "NOUN"
}
],
"total": 2
}
Команда позволяет по параметрам поискового запроса получить список ключевых слов (страницу и общее количество).
Имя команды для вызова: listKeywords.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
По умолчанию сортировка производится по полю title.
Запрос принимает параметры сортировки, фильтров и пейджинга в параметре Search.
Применяется к полям модели Keyword.
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров |
|---|---|
keywordId |
InSetQuery, LikeQuery |
title |
InSetQuery, LikeQuery |
Доступные поля для сортировки:
| Поле |
|---|
title |
InternalGetMaxNumericFieldValue (Data-model command)
На входе название поля, тип объекта и параметры поискового запроса (объект Search)
{
"field": "numm",
"entityType": "Tag",
"search": {
"query": "tagType.id",
"context": {
"tagType.id": "01f6c03f-d6db-44eb-b8c4-7ee6e5fc2454"
}
}
}
На выходе найденное максимальное значение или 'null' если нет данных или не заполнено ни одного значения
6
Или ошибка, если такого поля в модели данных не существует
{
"businessError": null,
"message": "ERROR: fields [numm] for entityType 'Tag' not found",
"stackTrace": null,
"data": null
}
Команда позволяет по типу объекта и параметрам поискового запроса получить максимальное значение для поля объекта из
data или additionalData. Метод необходим для нумерации объектов сторонним сервисом.
Имя команды для вызова: internalGetMaxNumericFieldValue.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway).
- На входе:
GetMaxNumericFieldValue. - На выходе:
Long.
Объекты сервиса модели данных
Типы данных, которые принимает на вход команда сервиса модели данных или возвращает в результате работы команды.
FieldType (Data-model)
Тип поля сущности.
| Поле | Тип | Описание |
|---|---|---|
id |
String |
Строковый код типа поля. |
description |
String |
Название типа поля для вывода в UI. |
databaseType |
String |
Тип поля в БД. |
settings |
JSON |
Произвольные настройки, применяемые для данного типа поля. |
RelationType (Data-model)
Тип отношения между сущностями.
| Поле | Тип | Описание |
|---|---|---|
id |
String |
Строковый код типа отношения. |
title |
String |
Название типа отношения. |
description |
String |
Развернутое описание типа отношения. |
MigrationDslOperation (Data-model)
Базовый тип операции Migration DSL для создания модели данных. Реализации:
CreateEntityUpdateEntityDeleteEntityAddFieldDeleteFieldAddAdditionalFieldUpdateFieldAddRelationUpdateRelationDeleteRelationPrefixMigration
CreateEntity (Data-model)
Операция создания типа сущности.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
operation |
String |
Да | Должно быть CreateEntity. |
entityType |
String |
Да | Строковый код создаваемого типа сущности. |
title |
String |
Да | Название типа сущности для вывода в UI. |
description |
String |
Нет | Развернутое описание типа сущности. |
settings |
JSON |
Нет | Настройки типа сущности. |
UpdateEntity (Data-model)
Операция изменения типа сущности.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
operation |
String |
Да | Должно быть UpdateEntity. |
entityType |
String |
Да | Строковый код изменяемого типа сущности. |
title |
String |
Да | Название типа сущности для вывода в UI. |
description |
String |
Нет | Развернутое описание типа сущности. |
settings |
JSON |
Нет | Настройки типа сущности. |
DeleteEntity (Data-model)
Операция удаления типа сущности.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
operation |
String |
Да | Должно быть DeleteEntity. |
entityType |
String |
Да | Строковый код удаляемого типа сущности. |
AddField (Data-model)
Операция добавления поля к типу сущности. Для разных типов полей предусмотрены разные допустимые настройки.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
operation |
String |
Да | Должно быть AddField. |
entityType |
String |
Да | Строковый код типа сущности, которому добавляется поле. |
fieldId |
String |
Да | Строковый код (название) добавляемого поля. |
fieldType |
String |
Да | Строковый код типа добавляемого поля. Все доступные типы полей можно получить с помощью команды Список типов полей. |
title |
String |
Да | Название добавляемого поля для вывода в UI. |
description |
String |
Нет | Развернутое описание добавляемого поля. |
example |
требуемый тип | Нет | Пример значения поля, см. ниже. |
nullable |
Boolean |
Нет | Необязательное или обязательное. Необязательное, когда указано true. |
settings |
JSON |
Нет | Произвольные настройки. |
defaultValue |
требуемый тип | если поле обязательное и уже есть объекты сущности | Значение поля, которое установится для уже имеющихся объектов сущности. |
Параметр example
Применяется в конструкторе UI.
Заполняется значением нужного типа. Если строка, тогда строка. Если число или дата - тогда число. Для типа
Fileнельзя указать пример.Будет в таком же виде возвращено в конструктор.
AddAdditionalField (Data-model)
Операция добавления дополнительного поля к типу сущности. Для разных типов полей предусмотрены разные допустимые настройки.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
operation |
String |
Да | Должно быть AddAdditionalField. |
entityType |
String |
Да | Строковый код типа сущности, которому добавляется поле. |
fieldId |
String |
Да | Строковый код (название) добавляемого поля. |
fieldType |
String |
Да | Строковый код типа добавляемого поля. |
title |
String |
Да | Название добавляемого поля для вывода в UI. |
description |
String |
Нет | Развернутое описание добавляемого поля. |
example |
требуемый тип | Нет | Пример значения поля. Применяется в конструкторе UI. Заполняется значением нужного типа. Если строка, тогда строка. Если число или дата - тогда число. Будет в таком же виде возвращено в конструктор. |
settings |
JSON |
Нет | Произвольные настройки. |
DeleteField (Data-model)
Операция удаления поля у типа сущности. Поддерживает как простые, так и дополнительные поля.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
operation |
String |
Да | Должно быть DeleteField. |
entityType |
String |
Да | Строковый код типа сущности, у которой удаляется поле. |
fieldId |
String |
Да | Строковый код (название) удаляемого поля. |
UpdateField (Data-model)
Операция изменения поля у типа сущности.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
operation |
String |
Да | Должно быть UpdateField. |
entityType |
String |
Да | Строковый код типа сущности, которому добавляется поле. |
fieldId |
String |
Да | Строковый код (название) добавляемого поля. |
title |
String |
Да | Название добавляемого поля для вывода в UI. |
description |
String |
Нет | Развернутое описание добавляемого поля. |
example |
требуемый тип | Нет | Пример значения поля. Применяется в конструкторе UI. Заполняется значением нужного типа. Если строка, тогда строка. Если число или дата - тогда число. Будет в таком же виде возвращено в конструктор. |
nullable |
Boolean |
Нет | Необязательное или обязательное. Необязательное, когда указано true. |
settings |
JSON |
Нет | Произвольные настройки. |
fieldType |
String |
Нет | Строковый код нового типа поля. |
defaultValue |
требуемый тип | Если поле обязательное и уже есть объекты сущности | Значение поля, которое установится для уже имеющихся объектов сущности (если ранее отсутствовало). |
EntityTypeSettings (Data-model)
Типы сущностей могут содержать различные настройки, которые будут влиять на создаваемые объекты. Настройки задаются в виде JSON объекта, у которого название поля является названием опции, а значение поля используемым значением. Тип поля зависит от конкретной опции. Ниже представлена таблица с доступными настройками.
| Название | Тип | Описание | Пример |
|---|---|---|---|
titleRule |
String |
Правило указания наименования объекта, которое будет выводиться в UI. В качестве значения передается название поля, которое содержит наименование конкретного объекта. Если правило не задано, то наименование будет считаться как "{entityType} {objectId}". |
"titleRule": "title" |
revisionConfig |
String |
Настройки для Сущности-ревизии | {"parentFieldCode": "parent", "actualityFieldCode": "isActual"} |
FieldSettings (Data-model)
Создаваемые поля поддерживают различные настройки. Их набор и формат зависит от типа поля. Эти настройки в дальнейшем
влияют на обработку поля и отражаются в JSON схеме.
На текущий момент поддерживаются настройки для следующих типов полей:
- Строка
string-StringFieldSettings - Текст
text-TextFieldSettings - Элемент справочника
catalog-CatalogFieldSettings - Файл
file-FileFieldSettings
StringFieldSettings (Data-model)
Настройки для строкового поля.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
maxLength |
Int |
Нет | Максимальная длина для вводимой строки. Используется для валидации. Если значение не указано, используется 64 по умолчанию. |
multiple |
Boolean |
Да | Признак множественного выбора. |
TextFieldSettings (Data-model)
Настройки для текстового поля.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
multiple |
Boolean |
Да | Признак множественного выбора. |
CatalogFieldSettings (Data-model)
Настройки для поля с элементами справочника.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
code |
String |
Да | Код справочника, элементы которого можно сохранить в этом поле. |
multiple |
Boolean |
Да | Признак множественного выбора. Если выбрано true, тогда для поля будет использоваться multiselect, а также значение будет передаваться массивом id, а не просто одиночным значением. |
FileFieldSettings (Data-model)
Настройки для поля с файлами.
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
multiple |
Boolean |
Да | Признак множественного выбора. Если выбрано true, тогда в поле будет храниться несколько файлов. Как и в случае одиночного поля данные передаются массивом. | |
maxCount |
Int |
Нет | Признак максимального количества файлов, присваивается полю maxItems в JSON-схеме сущности. Используется только если multiple=true, иначе maxItems будет присвоено 1. По умолчанию 10. |
- Не может быть больше 100 - Не может быть меньше 1. |
RevisionConfig (Data-model)
Настройки для Сущности-ревизии
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
parentFieldCode |
String |
да | Поле сущности, ссылающееся на родительский объект, по отношению к которому он является ревизией. | Должно иметь тип many-to-one и ссылаться на entity1 (другими словами, many-to-one в сторону родительской сущности, а не в сторону ревизии). |
actualityFieldCode |
String |
да | Boolean - поле, обозначающее актуальность ревизии. |
Должно быть обязательным (not-null) boolean полем. |
AddRelation (Data-model)
Операция добавления отношения между типами сущностей. В дальнейшем отношение однозначно идентифицируется по комбинации entity1+entity2+entity1Field.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
operation |
String |
Да | Должно быть AddRelation. |
relationType |
String |
Да | Тип отношения между сущностями. |
entity1 |
String |
Да | Строковый код первого типа сущности. |
entity2 |
String |
Да | Строковый код второго типа сущности. |
title1 |
String |
Да | Название добавляемого отношения для вывода в UI (со стороны entity1). |
title2 |
String |
Нет | Название добавляемого отношения для вывода в UI (со стороны entity2). |
entity1Field |
String |
Да | Строковый код нового виртуального поля первой сущности. |
entity2Field |
String |
Нет | Строковый код нового виртуального поля второй сущности. |
entity1Settings |
JSON |
Нет | Произвольные настройки поля первой сущности. |
entity2Settings |
JSON |
Нет | Произвольные настройки поля второй сущности. |
UpdateRelationMigration (Data-model)
Операция изменения атрибутов (entity2Field, relationType, title1, title2) отношения между типами сущностей.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
operation |
String |
Да | Должно быть UpdateRelation. |
entity1 |
String |
Да | Строковый код первого типа сущности. |
entity2 |
String |
Да | Строковый код второго типа сущности. |
entity1Field |
String |
Да | Строковый код виртуального поля первой сущности. |
entity2Field |
String |
Нет | Новый строковый код виртуального поля второй сущности. |
relationType |
String |
Да | Новый тип отношения между сущностями. |
title1 |
String |
Да | Новое название добавляемого отношения для вывода в UI (со стороны entity1). |
title2 |
String |
Нет | Новое название добавляемого отношения для вывода в UI (со стороны entity2). |
entity1Settings |
JSON |
Нет | Произвольные настройки поля первой сущности. |
entity2Settings |
JSON |
Нет | Произвольные настройки поля второй сущности. |
RelationSettings (Data-model)
Создаваемые связи по сути определяют 2 поля. Для каждого из них можно задать настройки. Их набор и формат определяются
потребностями пользователя.
Эти настройки в дальнейшем влияют на обработку поля и отражаются в JSON схеме.
На текущий момент предполагается хранение в настройках связей (полях связи) информации о зависимостях между атрибутами
объекта.
Служебные атрибуты: при генерации JSON схемы настройки properties порождаемых
объектами Relation уже
были в схеме и генерировались автоматически.
Автоматически создавался атрибут "to" ссылающийся на EntityType сущности, на которую ссылалось property.
Следует избегать в своих настройках добавления в корень настроек этого ключа во избежание конфликтного затирания.
DeleteRelationMigration (Data-model)
Операция удаления отношения между типами сущностей.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
operation |
String |
Да | Должно быть DeleteRelation. |
entity1 |
String |
Да | Строковый код первого типа сущности. |
entity2 |
String |
Да | Строковый код второго типа сущности. |
entity1Field |
String |
Да | Строковый код виртуального поля первой сущности. |
PrefixMigration (Data-model)
Операция, применяемая для всех сущностей с указанным префиксом.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
entityPrefix |
String |
Да | Префикс сущностей. |
migration |
JSON |
Да | Сама миграция (см. ниже). |
Миграции, которые можно указывать в поле migration:
EntityType (Data-model)
Тип сущности в модели данных.
| Поле | Тип | Описание |
|---|---|---|
id |
String |
Строковый код типа сущности. |
title |
String |
Название типа сущности для вывода в UI. |
description |
String |
Развернутое описание типа сущности. |
settings |
JSON |
Настройки типа сущности. |
AddEntityObject (Data-model)
Создание объекта сущности.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
entityType |
String |
Да | Строковый код типа сущности. |
source |
String |
Да | Источник данных для объекта. Для введенных вручную - manual. |
attributes |
JSON |
Да | JSON с полями добавляемого объекта. |
createRelations |
Boolean |
Нет | Включение создания новых relation в рамках команды. |
AddEntityObjectBatch (Data-model)
Создание списка объектов сущности.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
entityType |
String |
Да | Строковый код типа сущности. |
source |
String |
Да | Источник данных для объекта. Для введенных вручную - manual. |
attributes |
List[JSON] |
Да | Список JSON с полями добавляемых объектов. |
createRelations |
Boolean |
Нет | Включение создания новых relation в рамках команды. |
AddEntityObjectForBatchV2 (Data-model)
Создание списка объектов сущностей.
| Поле | Тип | Обязательное | Значение по умолчанию | Описание |
|---|---|---|---|---|
objectId |
UUID |
Нет | UUID.randomUUID |
ID объекта (Если не указано - используется сгенерированное значение). |
entityType |
String |
Да | - | Строковый код типа сущности. |
source |
String |
Да | - | Источник данных для объекта. Для введенных вручную - manual. |
attributes |
JSON |
Да | - | Список JSON-ов с полями добавляемых объектов. |
metadata |
JSON |
Нет | {} |
JSON с метаданными. |
createRelations |
Boolean |
Нет | false |
Включение создания новых relation в рамках команды. |
AddExternalEntityObject (Data-model)
Создание объекта сущности, полученного из внешнего клиента.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
entityType |
String |
Да | Строковый код типа сущности. |
externalId |
String |
Да | Внешний ID объекта. |
source |
String |
Да | Источник данных. |
attributes |
JSON |
Да | JSON с полями добавляемого объекта. |
createRelations |
Boolean |
Нет | Включение создания новых relation в рамках команды. |
UpdateEntityObject (Data-model)
Изменение объекта сущности.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
entityType |
String |
Да | Строковый код типа сущности. |
objectId |
UUID |
Да | ID объекта. |
version |
Int |
Да | Версия объекта. Нужна для оптимистичных блокировок. |
attributes |
JSON |
Да | JSON с полями объекта. Должен содержать все поля объекта. |
createRelations |
Boolean |
Нет | Включение создания новых relation в рамках команды. |
UpdateEntityObjectFields (Data-model)
Изменение части полей объекта.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
entityType |
String |
Да | Строковый код типа сущности. |
objectId |
UUID |
Да | ID объекта. |
version |
Int |
Да | Версия объекта. Нужна для оптимистичных блокировок. |
updates |
JSON |
Да | JSON с изменяемыми полями объекта и их новыми значениями. |
createRelations |
Boolean |
Нет | Включение создания новых relation в рамках команды. |
UpdateEntityObjectFieldsList (Data-model)
Изменение части полей объектов (по поисковому запросу).
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
entityType |
String |
Да | Строковый код типа сущности. |
search |
Search |
Да | Параметры списочного запроса. |
updates |
JSON |
Да | JSON с изменяемыми полями объекта и их новыми значениями. |
createRelations |
Boolean |
Нет | Включение создания новых relation в рамках команды. |
UpdateEntityObjectFieldsBatch (Data-model)
Изменение части полей объектов (по ID).
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
entityType |
String |
Да | Строковый код типа сущности. |
objectIds |
List[UUID] |
Да | ID объектов. |
updates |
JSON |
Да | JSON с изменяемыми полями объекта и их новыми значениями. |
UpdateExternalEntityObject (Data-model)
Изменение объекта сущности.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
entityType |
String |
Да | Строковый код типа сущности. |
external |
String |
Да | Внешний ID объекта. |
attributes |
JSON |
Да | JSON с полями объекта. Должен содержать все поля объекта. |
createRelations |
Boolean |
Нет | Включение создания новых relation в рамках команды. |
EntityObjectIdentity (Data-model)
Полный идентификатор объекта сущности.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
entityType |
String |
Да | Строковый код типа сущности. |
objectId |
UUID |
Да | ID объекта. |
EntityObjectExternalIdentity (Data-model)
Полный идентификатор внешнего объекта сущности.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
entityType |
String |
Да | Строковый код типа сущности. |
externalId |
String |
Да | Внешний ID объекта. |
TitledEntityObjectIdentity (Data-model)
Полный идентификатор и наименование объекта сущности.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
entityType |
String |
Да | Строковый код типа сущности. |
objectId |
UUID |
Да | ID объекта. |
title |
String |
Да | Наименование объекта. |
EntityObjectFields (Data-model)
Идентификатор объекта сущности и список полей данного объекта.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
id |
EntityObjectIdentity |
Да | Идентификатор объекта сущности. |
fields |
List[String] |
Да | Список необходимых полей. |
fieldSearches |
JSON |
Нет | см. Фильтры для связанных сущностей. |
EntityObjectsBatchWithFields (Data-model)
Идентификаторы объектов сущности и список полей для данного набора объектов.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
entityType |
String |
Да | Строковый код типа сущности. |
ids |
List[UUID] |
Да | Идентификаторы объектов заданного типа сущности. |
fields |
List[String] |
Да | Список необходимых полей. |
fieldSearches |
JSON |
Нет | См. Фильтры для связанных сущностей. |
SaveObjectAdditionalInfo (Data-model)
Сохранение дополнительных атрибутов объекта сущности. Дополнительные атрибуты.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
entityType |
String |
Да | Строковый код типа сущности. |
objectId |
UUID |
Да | ID объекта. |
additionalData |
JSON |
Да | JSON с дополнительными полями. Поля добавляются к существующим. Не обязательно передавать все. |
SaveObjectMetadata (Data-model)
Сохранение метаданных объекта сущности.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
entityType |
String |
Да | Строковый код типа сущности. |
objectId |
UUID |
Да | ID объекта. |
metadata |
JSON |
Да | JSON с метаданными. |
SaveFilesAdditionalInfo (Data-model)
Сохранение дополнительных файлов для файловых полей объекта сущности.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
entityType |
String |
Да | Строковый код типа сущности. |
objectId |
UUID |
Да | ID объекта. |
data |
List[FileAdditionalInfo] |
Да | Информация по файловым полям. |
FileAdditionalInfo (Data-model)
Сохранение дополнительных файлов для отдельного файлового поля объекта сущности.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
field |
String |
Да | Строковый код файлового поля. |
key |
String |
Да | Код атрибута. |
data |
Map[UUID, File] |
Да | Существующие файлы ассоциированные с новыми дополнительными файлами. |
SaveFilesAdditionalInfoV2 (Data-model)
Сохранение дополнительных файлов для файловых полей объекта сущности.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
key |
String |
Да | Код атрибута. |
files |
Map[UUID, File] |
Да | Существующие файлы ассоциированные с новыми дополнительными файлами. |
EntityObjectMeta (Data-model)
Метаданные объекта сущности.
| Поле | Тип | Описание |
|---|---|---|
id |
UUID |
ID объекта. |
externalId |
String |
Внешний ID объекта. |
entityType |
String |
Тип сущности объекта. |
title |
String |
Название объекта. Может быть пустой строкой, если нет необходимых полей в data. |
source |
String |
Источник данных для объекта. |
created |
TimeStamp |
Дата и время создания объекта. |
modified |
TimeStamp |
Дата и время последнего изменения объекта. |
version |
Int |
Версия объекта для оптимистичных блокировок. Передается назад на бэкэнд при модификации данных. |
removed |
Boolean |
Признак того, считается ли объект удаленным. |
ListObjects (Data-model)
Получение списка объектов сущности.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
entityType |
String |
Да | Строковый код типа сущности. |
search |
Search |
Да | Параметры списочного запроса. |
RichListObjects (Data-model)
Получение списка объектов сущности только с указанными полями.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
entityType |
String |
Да | Строковый код типа сущности. |
fields |
List[String] |
Да | Список строк с названиями полей сущности. |
search |
Search |
Да | Параметры списочного запроса. |
fieldSearches |
JSON |
Нет | См. Фильтры для связанных сущностей. |
GetObjectPosition (Data-model)
Запрос позиции объекта в отфильтрованном и отсортированном списке.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
entityType |
String |
Да | Строковый код типа сущности. |
objectId |
UUID |
Да | ID искомого объекта. |
search |
Search |
Да | Параметры списочного запроса. |
GetEntityFieldAggregation (Data-model)
Параметры запроса на агрегацию значений полей.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
entityType |
String |
Да | Строковый код типа сущности. |
search |
Search |
Да | Параметры списочного запроса. Параметры sorting и paging не учитываются. |
fields |
List[String] |
Да | Перечень полей, для которых нужна агрегация. |
FieldAggregatedValue (Data-model)
Статистика значения поля.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
value |
произвольный | Да | Значение поля. |
count |
Number |
Да | Количество записей с таким значением поля. |
AddObjectRelation (Data-model)
Добавление отношения между объектами сущностей. Название отношения соответствует комбинации типов сущностей
${entity1Type}_to_${entity2Type}_on_${entity1Field}.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
entity1Type |
String |
Да | Тип первой сущности из отношения. |
entity2Type |
String |
Да | Тип второй сущности из отношения. |
entity1Field |
String |
Да | Виртуальное поле отношения из первой сущности. |
object1Id |
UUID |
Да | ID объекта первой сущности. |
object2Id |
UUID |
Да | ID объекта второй сущности. |
source |
String |
Да | Источник данных для отношений. Для введенных вручную - manual. |
Тип отношения и возможность сохранения проверяются на бэке в процессе вызова команды.
AddObjectRelationResult (Data-model)
Результат добавления отношения между объектами сущностей.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
relation |
AddObjectRelation |
Да | Описание запроса. |
result |
Boolean |
Да | Признак успешности. |
error |
String |
Нет | Описание ошибки, если произошла. |
ObjectProcessingResult (Data-model)
Результат обработки (например изменения) объекта.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
entityType |
String |
Да | Тип сущности обработанного объекта. |
objectId |
UUID |
Да | ID обработанного объекта. |
result |
Boolean |
Да | Признак успешности. |
error |
String |
Нет | Описание ошибки, если произошла. |
errorCode |
Int |
Нет | HTTP-код ошибки, если произошла. |
ObjectRelation (Data-model)
Описание сохраненного отношения между объектами сущностей.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
entity1Type |
String |
Да | Тип первой сущности из отношения. |
entity2Type |
String |
Да | Тип второй сущности из отношения. |
entity1Field |
String |
Да | Виртуальное поле отношения из первой сущности. |
entity2Field |
String |
Нет | Виртуальное поле отношения из первой сущности. |
object1Id |
UUID |
Да | ID объекта первой сущности. |
object2Id |
UUID |
Да | ID объекта второй сущности. |
source |
String |
Да | Источник данных для отношений. Для введенных вручную - manual. |
GetObjectRelation (Data-model)
Получение отношения между объектами сущностей.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
entity1Type |
String |
Да | Тип первой сущности из отношения. |
entity2Type |
String |
Да | Тип второй сущности из отношения. |
entity1Field |
String |
Да | Виртуальное поле отношения из первой сущности. |
entity2Field |
String |
Нет | Виртуальное поле отношения из второй сущности. |
object1Id |
UUID |
Да | ID объекта первой сущности. |
object2Id |
UUID |
Да | ID объекта второй сущности. |
ListObjectRelations (Data-model)
Получение списка всех отношений между объектов и указанной сущностью.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
entityType |
String |
Да | Тип сущности объекта. |
objectId |
UUID |
Да | ID объекта. |
relatedEntityType |
UUID |
Да | Тип связанной сущности. |
fieldName |
String |
Да | Поле, по которому построена связь. |
reversed |
Boolean |
Да | В каком направлении связь. |
paging |
Paging |
Нет | Параметры пейджинга. |
DeleteObjectRelation (Data-model)
Удаление отношения между объектами сущностей. Название отнощения соответствует комбинации типов сущностей
${entity1Type}_to_${entity2Type}_on_${entity1Field}.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
entity1Type |
String |
Да | Тип первой сущности из отношения. |
entity2Type |
String |
Да | Тип второй сущности из отношения. |
entity1Field |
String |
Да | Виртуальное поле отношения из первой сущности. |
object1Id |
UUID |
Да | ID объекта первой сущности. |
object2Id |
UUID |
Да | ID объекта второй сущности. |
DeleteObjectRelations (Data-model)
Удаление отношения между объектами сущностей.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
entityType |
String |
Да | Тип сущности. |
objectId |
UUID |
Да | ID объекта сущности. |
relatedEntityTypes |
List[UUID] |
Да | Перечень связанных типов сущностей. |
UpdateExternalObjectRelations (Data-model)
Обновление списка отношений объекта с сущностью.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
entity1Type |
String |
Да | Тип первой сущности из отношения. |
entity2Type |
String |
Да | Тип второй сущности из отношения. |
entity1Field |
String |
Да | Виртуальное поле отношения из первой сущности. |
reversed |
Boolean |
Нет (по умолчанию false) |
Направление отношения. Если false, то objectId - объект сущности entity1Type, иначе - entity2Type. |
objectId |
String |
Да | Внешний ID объекта, для которого обновляются отношения. |
relationObjectIds |
List[String] |
Да | Внешний ID объектов, связанных отношением с обновляемым объектом. |
source |
String |
Да | Источник данных для отношений. |
UpdateExternalObjectRelationResult (Data-model)
Результат добавления отношения между внешними объектами.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
relationObjectId |
String |
Да | ID связанного объекта. |
success |
Boolean |
Да | Признак успешности создания связи. |
error |
String |
Нет | Описание ошибки, если произошла. |
ObjectLink (Data-model)
Связь между двумя объектами сущностей. Связь устанавливается на основе интеллектуализации (содержательные пересечения, близкие по смыслу) или вручную.
| Поле | Тип | Описание |
|---|---|---|
id |
UUID |
ID связи. |
entityType1 |
String |
Тип сущности первого объекта из связи. |
object1Id |
UUID |
ID первого объекта из связи. |
entityType2 |
String |
Тип сущности второго объекта из связи. |
object2Id |
UUID |
ID второго объекта из связи. |
linkType |
String |
Тип связи, строковый код. |
source |
String |
Источник связи. Для введенных вручную - manual, для созданных в сервисах интеллектуализации - auto. |
owner |
String |
Создатель связи. Это может быть id пользователя, создавшего связь вручную, код или ID сервиса, создавшего связь автоматически. |
additional |
JSON |
Произвольный JSON объект с дополнительными данными, специфичными для конкретного типа связи. |
ObjectLinkWithObjects (Data-model)
Связь между двумя объектами сущностей. Включает информацию об объектах.
| Поле | Тип | Описание |
|---|---|---|
id |
UUID |
ID связи. |
entityType1 |
String |
Тип сущности первого объекта из связи. |
object1 |
EntityObject |
Первый объект. |
entityType2 |
String |
Тип сущности второго объекта из связи. |
object2 |
EntityObject |
Второй объект. |
linkType |
String |
Тип связи, строковый код. |
source |
String |
Источник связи. Для введенных вручную - manual, для созданных в сервисах интеллектуализации - auto. |
owner |
String |
Создатель связи. Это может быть id пользователя, создавшего связь вручную, код или ID сервиса, создавшего связь автоматически. |
additional |
JSON |
Произвольный JSON объект с дополнительными данными, специфичными для конкретного типа связи. |
GetObjectLinksList (Data-model)
Получение списка связей объекта.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
entityType |
String |
Да | Тип сущности объекта, для которого запрашиваются связи. |
objectId |
UUID |
Да | ID объекта, для которого запрашиваются связи. |
linkTypes |
List[String] |
Нет | Типы запрашиваемых связей. Может содержать несколько значений. Может быть пустым, тогда вернутся все доступные связи. |
forwardLinks |
Boolean |
Да | Признак получения прямых или обратных связей. Если true, тогда связи прямые, тогда искомый объект - это первый объект из связи (object1). Если false, тогда искомый объект - это второй объект из связи (object2). |
linkedEntityType |
String |
Нет | Тип сущности объектов на "другом конце" связи. Если связи прямые, то тип linkedEntityType должны иметь все вторые объекты из связи, а если обратные - то первый. |
GetObjectRelationsByType (Data-model)
Получение списка связей для типов объектов.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
entityFrom |
String |
Да | Тип сущности объекта, от которого идут запрашиваемые связи. |
entityTo |
String |
Да | Тип сущности объекта, к которому идут запрашиваемые связи. |
field |
String |
Да | Название поля, по которому идет связь. |
CreateObjectLink (Data-model)
Создание связи между объектами сущностей.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
entityType1 |
String |
Да | Тип сущности первого объекта из связи. |
object1Id |
UUID |
Да | ID первого объекта из связи. |
entityType2 |
String |
Да | Тип сущности второго объекта из связи. |
object2Id |
UUID |
Да | ID второго объекта из связи. |
linkType |
String |
Да | Тип связи, строковый код. Длина не более 64 символов. |
source |
String |
Да | Источник связи. Для введенных вручную - manual, для созданных в сервисах интеллектуализации - auto. Длина не более 64 символов. |
owner |
String |
Нет | Создатель связи. Это может быть id пользователя, создавшего связь вручную, код или ID сервиса, создавшего связь автоматически. Длина не более 64 символов. |
additional |
JSON |
Нет | Произвольный JSON объект с дополнительными данными, специфичными для конкретного типа связи. |
fileId1 |
UUID |
Нет | Идентификатор файла из первого объекта, если связь строится на основании файла. |
fileId2 |
UUID |
Нет | Идентификатор файла из второго объекта, если связь строится на основании файла. |
DeleteObjectLinks (Data-model)
Удаление связей объекта.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
entityType |
String |
Да | Тип сущности объекта, для которого удаляются связи. |
objectId |
UUID |
Да | ID объекта, для которого удаляются связи. |
linkType |
String |
Нет | Тип удаляемых связей. Может быть пустым, тогда удалятся все имеющиеся связи. |
forwardLinks |
Boolean |
Да | Признак удаления прямых или обратных связей. Если true, тогда связи прямые, тогда искомый объект - это первый объект из связи (object1). Если false, тогда искомый объект - это второй объект из связи (object2). |
ObjectFileWithTags (Data-model)
ID файла и список его тегов.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
fileId |
UUID |
Да | ID файла объекта. |
tags |
List[String] |
Да | Список тегов файла (кодов элемента справочника тегов). |
FileInfoWithTags (Data-model)
Информация о файле, включая его теги и ссылку на родительский объект.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
objectIdentity |
EntityObjectIdentity |
Да | ID объекта. |
entityTypeTitle |
String |
Да | Наименование типа объекта. |
objectTitle |
String |
Да | Наименование объекта. |
fileInfo |
ObjectFileMeta |
Да | Информация о файле. |
tags |
List[String] |
Да | Список тегов файла (кодов элемента справочника тегов). |
ObjectFileMeta (Data-model)
Полная информация о файле.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
fileId |
UUID |
Да | ID файла. |
name |
String |
Нет | Имя файла с расширением. |
extension |
String |
Нет | Расширение файла. |
size |
Long |
Нет | Размер файла в байтах. |
url |
String |
Нет | Ссылка на скачивание файла из файлового хранилища. |
additional |
JSON |
Нет | Объект с дополнительными параметрами. |
created |
TimeStamp |
Нет | Время загрузки файла. |
modified |
TimeStamp |
Нет | Время редактирования данной записи. |
md5 |
String |
Нет | Хеш файла. |
FileIdentity (Data-model)
Полный идентификатор файла.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
fileId |
String |
Да | ID файла. |
entityType |
String |
Да | Наименование типа объекта. |
objectId |
String |
Да | ID объекта. |
ObjectWithKeywordsDTO (Data-model)
Тип и ID объекта и список его ключевых слов.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
entityType |
String |
Да | Тип сущности объекта. |
objectId |
UUID |
Да | ID объекта. |
keywords |
List[KeywordDTO] |
Да | Список ключевых слов объекта. |
KeywordDTO (Data-model)
Информация о ключевом слове.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
keyword |
String |
Да | Ключевое слово. |
pos |
String |
Да | Часть речи. |
weight |
Double |
Нет | Вес ключевого слова по отношению к объекту. |
ObjectWithKeywords (Data-model)
Тип и ID объекта и список его ключевых слов.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
objectId |
UUID |
Да | ID объекта. |
keywords |
List[KeywordWithWeight] |
Да | Список ключевых слов объекта. |
KeywordWithWeight (Data-model)
Информация о ключевом слове совмещенная с весом ключевого слова в объекте.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
keywordId |
UUID |
Да | ID ключевого слова. |
keyword |
String |
Да | Ключевое слово. |
pos |
String |
Да | Часть речи. |
weight |
Double |
Нет | Вес ключевого слова по отношению к объекту. |
Keyword (Data-model)
Ключевое слово.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
id |
UUID |
Да | ID ключевого слова. |
title |
String |
Да | Ключевое слово. |
pos |
String |
Да | Часть речи. |
GetMaxNumericFieldValue (Data-model)
Изменение части полей объектов (по поисковому запросу).
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
entityType |
String |
Да | Строковый код типа сущности. |
search |
Search |
Да | Параметры списочного запроса. |
field |
String |
Да | Название поля для которого нужно найти максимум. |
ParentRelation (Data-model)
Родительская модель.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
entityType |
String |
Да | Наименование типа объекта. |
fieldId |
String |
Да | Строковый код (название) поля. |
nested |
List[ParentRelation] |
Да | Все вышележащие родители. |
ObjectStore (Data-model)
Объект сущности (модель базы данных).
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
id |
UUID |
Да | ID объекта. |
externalId |
String |
Нет | Внешний ID объекта. |
title |
String |
Да | Название объекта. |
source |
String |
Да | Источник данных для объекта. |
created |
TimeStamp |
Да | Дата и время создания объекта. |
modified |
TimeStamp |
Да | Дата и время последнего изменения объекта. |
data |
JSON |
Да | JSON с полями объекта. |
additionalData |
JSON |
Да | JSON с дополнительными полями объекта. |
metadata |
JSON |
Да | JSON с метаданными. |
version |
Int |
Да | Версия объекта для оптимистичных блокировок. |
removed |
Boolean |
Да | Признак того, считается ли объект удаленным. |
EntityObject (Data-model)
Объект сущности.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
id |
UUID |
Да | ID объекта. |
externalId |
String |
Нет | Внешний ID объекта. |
entityType |
String |
Да | Тип сущности объекта. |
title |
String |
Да | Название объекта. |
source |
String |
Да | Источник данных для объекта. |
created |
TimeStamp |
Да | Дата и время создания объекта. |
modified |
TimeStamp |
Да | Дата и время последнего изменения объекта. |
data |
JSON |
Да | JSON с полями объекта. |
additionalData |
JSON |
Да | JSON с дополнительными полями объекта. |
metadata |
JSON |
Да | JSON с метаданными. |
version |
Int |
Да | Версия объекта для оптимистичных блокировок. |
removed |
Boolean |
Да | Признак того, считается ли объект удаленным. |
EntityObjectEvent (Data-model)
Событие об изменении сущности.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
eventType |
String |
Да | Тип события (create, update, delete, reindex). |
payloadId |
UUID |
Да | ID объекта. |
payloadType |
String |
Да | Тип объекта (EntityTypeId). |
payload |
EntityObject |
Да | Сам объект. |
EntityTypeEvent (Data-model)
Событие об изменении модели.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
eventType |
String |
Да | Тип события (create, update, delete). |
payloadId |
String |
Да | Тип объекта (EntityTypeId). |
payloadType |
String |
Да | Константа, всегда равен EntityType. |
payload |
EntityTypeEventBody |
Да | Сам объект. |
EntityTypeEventBody (Data-model)
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
entityType |
EntityType |
Да | Информация о сущности. |
Работа с фильтрацией сервиса Data-model
Типы фильтров для полей сущности (Data-model)
Если поле для фильтрации имеет вид data.something или additionaldata.something,
то фильтрация идет по соответствующим полям в data или additionalData. Для этих фильтров
поддерживаются виды InSetQuery, LikeQuery, RangeQuery и AllInSetQuery (Только для вложенных полей-массивов.
Не будет работать для relation-полей.).
Каждый тип поля поддерживает свои типы фильтров. Таблица соответствия которых приведена ниже.
| Тип поля | Виды фильтров |
|---|---|
Int, Double, Long, Float, Number |
InSetQuery, RangeQuery |
TimeStamp |
InSetQuery, RangeQuery, LikeQuery |
String |
InSetQuery, LikeQuery |
UUID |
InSetQuery, LikeQuery |
Boolean |
InSetQuery |
Таблица демонстрирует допустимые фильтры по типам, однако некоторые поля могут поддерживать или не поддерживать те или иные виды фильтров в зависимости от специфики поля и его логической состовляющей.
Relation поля (Data-model)
Для указания фильтров или сортировки по определенному полю, можно использовать названия как полей конкретного типа
сущности EntityObject, так и relation-полей для данного типа сущности.
Для фильтра/сортировки указывается полное название поля, относительно
структуры EntityObject.
Также поддерживаются поля объектов, связанных через несколько relation с исходным, глубина не ограничена.
Примеры:
- Фильтр/сортировка по полю
numberобъектаEntityObjectс типом сущностиOrder
задается какdata.number, т.к. поля сущности лежат в JSON-объектеdata. - Фильтр по полю
author.name(author-relationполе типаPersonдля типаOrder)
объектаEntityObjectс типом сущностиOrderзадается какauthor.data.number,
т.к. relation объект также имеет структуруEntityObject - Можно фильтровать по глубоко вложенным связям. Если
Personсвязан сAddress, то цепочка до адреса будет выглядеть так:author.address.name. - Можно фильтровать (но не сортировать) по полям структуры
EntityObjectв рамках relation объекта.
Например, можно назвать фильтр какauthor.id. Данные поля называются "системными" (полный список в Методы Rich*), т.к. создаются для каждой сущности.
Фильтрация по разным значениям одного поля (Data-model)
Если есть необходимость фильтровать по сложному составному запросу, в котором имя одного поля появляется несколько раз, то можно воспользоваться тегами для полей. Например, можно составить такой запрос:
{
"search": {
"query": "(code:1 && title:1) || (code:2 && title:2)",
"context": {
"code:1": "10",
"title:1": "like документ%",
"code:2": "20",
"title:2": "like журнал%"
}
}
}
Благодаря тегам, которые указываются после двоеточия в конце, появляется возможность различать фильтры в
зависимости от их положения в query. Тегом может быть произвольная строка, содержащая в себе латинские символы,
цифры и знаки _ и - (т.е. регулярное выражение ^[a-zA-Z0-9_-]*$).
- Если поле содержит в себе символ
:(примерdata.name:myname), то для корректного декодирования поля - в конце обязательно нужно указать
:(примерdata.name:myname:), иначе он будет воспринят тегом.
Фильтрация по полям сущности (Data-model)
В рамках очередной доработки стали поддерживаться следующие варианты написания ключей кастомных полей
в Search.query.
- Без указания
data- Поле
my_fieldпринадлежит к текущей сущности, в Search.query можно указыватьmy_field - Поле
my_fieldпринадлежит к связанной сущности (полеrelation_obj1) целевого объекта, в Search.query можно указыватьrelation_obj.my_field - Поле
my_fieldпринадлежит к связанной сущности (полеrelation_obj2) для связанной сущности (полеrelation_obj1) целевого объекта, в Search.query можно указыватьrelation_obj1.relation_obj2.my_field
- Поле
- Указываем
dataиногда- Поле
my_fieldпринадлежит к связанной сущности (полеrelation_obj1) целевого объекта с одинаковым результатом, в Search.query можно указывать:data.relation_obj.my_fieldrelation_obj.data.my_field
- Поле
my_fieldпринадлежит к связанной сущности (полеrelation_obj2) для связанной сущности (полеrelation_obj1) целевого объекта с одинаковым результатом, в Search.query можно указывать:data.relation_obj1.relation_obj2.my_fieldrelation_obj1.data.relation_obj2.my_fieldrelation_obj1.relation_obj2.data.my_field
- Поле
- Указываем
dataвезде- Поле
my_fieldпринадлежит к текущей сущности, в Search.query можно указыватьdata.my_field - Поле
my_fieldпринадлежит к связанной сущности по полюrelation_obj, в Search.query можно указыватьdata.relation_obj.data.my_field - Поле
my_fieldпринадлежит к связанной сущности (полеrelation_obj2) для связанной сущности (полеrelation_obj1) целевого объекта, в Search.query можно указыватьdata.relation_obj1.data.relation_obj2.data.my_field
- Поле
Дополнительные уточнения по логике работы таких фильтров ниже.
Использование префикса data (Data-model)
Если поле содержится только среди системных полей объекта:
- указано значение без префикса
data- возвращаются только объекты со значениями системных полей, удовлетворяющих условию фильтрации; - указано значение c префиксом
data- возвращается пустой список, т.к. "кастомного" поля, указанного в фильтре, не существует.
Если поле содержится только среди кастомных полей объекта:
- указано значение без префикса
data- возвращаются все объекты со значениями кастомных полей, удовлетворяющих условию фильтрации; - указано значение c префиксом
data- возвращаются все объекты со значениями кастомных полей, удовлетворяющих условию фильтрации.
Если поля с одинаковым названием содержатся и в системных и в кастомных полях объекта:
- указано значение без префикса data - возвращаются все объекты со значениями системных полей, удовлетворяющих условию фильтрации;
- указано значение c префиксом data - возвращаются все объекты со значениями кастомных полей, удовлетворяющих условию фильтрации.
Методы Rich* (Data-model)
При получении объектов с помощью Rich* методов, помимо основных параметров, передаются требуемые поля объектов.
Поля могут быть из data или additionalData. Системные поля тоже можно указывать, но они в любом случае возвращаются
всегда.
Для каждого возвращенного объекта JSON будет содержать только указанные в запросе поля.
Если нужно запросить все поля, то можно использовать символ * вместо имени конкретного поля (relation поля не будут
возвращены).
Если никакое поле не указывать, то будут возвращены только системные поля. Это поведение сохраняется не только для
корневого объекта, но и для связанных объектов.
Для указания списка допустимых полей для корневого объекта (не relation), используются "короткие" варианты названия
полей (без указания поля data), т.к. все поля всегда находятся в JSON-объекте поля data.
При запросе полей relation-объекта, также происходит фильтрация его полей по списку "fields", но системные поля
добавляются всегда (с префиксом, указанным в DATA_MODEL_RELATION_SYSTEM_FIELDS_PREFIX).
Также можно запрашивать поля объектов, связанных через несколько relation с исходным, глубина не ограничена.
Запрашиваемые поля без данных или равных null не добавляются в результат.
Список системных полей из объекта EntityObject, которые добавляются всегда:
id, externalId, entityType, title, created, modified, version.
Для указания полей для relation-объектов, можно использовать все поля, которые есть
в EntityObject,
включая поля с файлами.
Примеры Rich-запросов (Data-model)
Для примеров используется следующая модель данных:
Order(number: String, name: String)
Person(name: String)
Address(text: String)
Order ссылается на Person через поле authors: Person[].
Person ссылается на Address через поле address: Option[Address].
Пример запроса RichGetObjects с указанием нужных полей
{
"id": {
"entityType": "Order",
"objectId": "18b1011b-9db3-4186-a53c-971016030068"
},
"fields": [
"name", // Order.name
"authors.data.name", // Полный путь к Person.name
"authors.name", // Короткая запись Person.name
"authors.id", // Системное поле EntityObject
"authors", // Запрос всех системных полей у всех связанных объектов (поле authors является списком)
"authors.*", // Wildcard для запроса всех существующих полей у связанного объекта (relation поля не возвращаются)
"authors.address.text", // Длинный путь до поля у глубоко вложенного объекта
"authors.address", // Запрос всех системных полей у глубоко вложенного объекта
"authors.address.*"
// Wildcard для запроса всех существующих полей у глубоко вложенного объекта (relation поля не возвращаются)
]
}
Результатом запроса будет объект
EntityObjectс полями связанных объектов вdata
{
"id": "18b1011b-9db3-4186-a53c-971016030068",
"externalId": "ExternalOrder",
"entityType": "Order",
"title": "Аренда лошади",
"source": "manual",
"created": 1630326492,
"modified": 1630326492,
"data": {
"name": "Test order",
"authors": [
{
"_id": "505e7939-94e4-4c1a-b175-b622258d00fc",
"_externalId": null,
"_entityType": "Person",
"_title": "First author",
"_source": "manual",
"_created": 1634553248859,
"_modified": 1634553248859,
"_version": 1,
"name": "First author",
"address": {
"_id": "478bf14a-b1f9-46d4-b7fb-3b7ff3d8ca79",
"_externalId": null,
"_entityType": "Address",
"_title": "Baker street",
"_source": "manual",
"_created": 1634553248859,
"_modified": 1634553248859,
"_version": 1,
"text": "Baker street"
}
},
{
"_id": "66806625-ea74-4c9e-8fca-ccf1e1366e8b",
"_externalId": null,
"_entityType": "Person",
"_title": "Second author",
"_source": "manual",
"_created": 1634553248859,
"_modified": 1634553248859,
"_version": 123,
"name": "Second author",
"address": null
}
]
},
"additionalData": {},
"version": 1
}
Фильтры для связанных сущностей (Data-model)
Обычные фильтры по связанным элементам влияют на корневой список элементов - в него попадают те объекты, для которых хотя бы один связанный объект удовлетворяет упомянутым фильтрам. На списки самих связанных объектов повлиять этими фильтрами нельзя - там все равно будут все элементы, которые связаны с корневыми.
Пример запроса RichGetObjects с указанием fieldSearches
{
"id": {
"entityType": "Order",
"objectId": "18b1011b-9db3-4186-a53c-971016030068"
},
"fields": [
"authors.data.name",
],
"fieldSearches": {
"authors": {
"query": "data.name",
"context": {
"data.name": "like Иванов%"
}
}
}
}
В rich запросах дополнительно можно указывать фильтры, которые будут применены только к связанным сущностям.
На корневой список элементов они не повлияют.
Например, в примере запроса RichGetObjects, с помощью можно поля fieldSearches мы отфильтровываем авторов заказов (
authors) по префиксу для поля data.name.
В fieldSearches можно указывать любое количество Search объектов. Каждый ключ в этом объекте должен
быть префиксом хотя бы одной цепочки в fields - иначе будет ошибка. Как и в случае с фильтрами,
поддерживается любая длина цепочек. Также поддерживается сортировка и пагинация.
{
"entityType": "documentAPI",
"search": {
"query": "UNKNOWN.data.source",
"context": {
"UNKNOWN.data.source": "manual"
},
"sorting": {
"fieldName": "created",
"order": "asc"
},
"paging": {
"page": 1,
"count": 10
}
}
}
Revisions (Data-model)
Существует механизм версионирования для сущностей, у которых указано поле revisionConfig
в settings. Такие сущности обладают двумя особенностями:
1) При создании новой актуальной ревизии (или выставлении этого признака у существующей) предыдущая становится неактуальной. 2) При изменении, создании или удалении актуальной ревизии посылается событие об изменении родительского объекта.
Поле revisionConfig имеет следующий вид:
{
"parentFieldCode": "parent",
"actualityFieldCode": "isActual"
}
parentFieldCode - поле, ссылающееся на родительскую сущность, по отношению к которой
эта сущность является версией.
actualityFieldCode - поле сущности, индикатор актуальности версии. Это должно быть
обязательное поле типа Boolean.
Использование AllInSet в запросах (Data-model)
Запрос для поиска книг с рыжими и темноволосыми авторами (на данный момент не работает)
Search(
query = "authors.data.hairColor",
context = Map(
"authors.data.hairColor" -> Json.arr(Json.fromString("black"), Json.fromString("red")),
"kind" -> Json.fromString("all")
)
)
Запрос для поиска книг с авторами, знающими русский и английский языки (на данный момент не работает)
Search(
query = "authors.data.languages",
context = Map(
"authors.data.languages" -> Json.arr(Json.fromString("ru"), Json.fromString("en")),
"kind" -> Json.fromString("all")
)
)
На данный момент AllInSetQuery не работает для relation-полей.
Если объект Book связан с объектом Person по полю authors,
то мы не сможем найти только книги у которых в массиве авторов, есть и рыжие, и черноволосые авторы, с помощью запроса
AllInSet.
Также если объект Book связан с объектом Person по полю authors,
а у Person есть поле-массив languages, то мы не сможем найти все книги,
в которых конкатенация языков авторов содержит и русский, и английский,
с помощью запроса AllInSet.
Публикуемые события (Data-model)
Сервис отправляет события об изменении модели и объектов в топик DATA_MODEL_KAFKA_ENTITY_OBJECT_EVENT_TOPIC.
События об изменении объектов (Data-model)
{
"eventType": "create",
"payloadId": "1627c316-6de9-4c16-b43a-4d293a7805ea",
"payloadType": "Company_0D33",
"payload": {
"additionalData": null,
"entityObject": {
"additionalData": {},
"created": 1739953317862,
"data": {
"title": "123435"
},
"entityType": "Company_0D33",
"externalId": null,
"id": "1627c316-6de9-4c16-b43a-4d293a7805ea",
"metadata": {},
"modified": 1750742233664,
"removed": false,
"source": "manual",
"title": "123435",
"version": 1
}
}
}
Тип данных - EntityObjectEvent
Примечание - при удалении сущности посылается события на удаление всех ее существующих объектов.
События об изменении модели (Data-model)
События посылаются только на миграции CreateEntity, UpdateEntity, DeleteEntity.
Изменение полей или relation сущности не посылают события.
{
"eventType": "create",
"payloadId": "Test2",
"payloadType": "EntityType",
"payload": {
"entityType": {
"description": "",
"id": "Test2",
"settings": {},
"title": "test"
}
}
}
Тип данных - EntityTypeEvent
Data-model-client: клиент для сервиса Data-model
client.saveObject(EntityTypeId("test"), TestClass("kek", 123), "manual")
client.getObject[TestClass](EntityTypeId("test"), objectId)
Предоставляет удобный способ общения с моделью данных и механизм для применения миграций к модели данных.
Регистрация в distage
case class ClientsModule[F[_]: Async: ContextShift: TagK]() extends ModuleDef {
make[DataModelClient[F]].from { (dispatcher: Dispatcher) =>
new DataModelClientImpl(dispatcher)
}
}
В distage сам клиент можно зарегистрировать следующим способом:
Использование мигратора
make[DataModelMigratorF[F]].from { (client: DataModelClient[F], migrations: Seq[Migration]) =>
new DataModelMigratorF(client, migrations)
}
Мигратор можно подключить следующим образом:
Далее, чтобы запустить миграции можно получить DataModelMigrator из контейнера и выполнить migrator.migrate.
Метод migrate вызывает комманду сервиса createDataModel(). В случае каких-то проблем из метода возвращается ошибка,
повторная отправка запросов не производится.
| Команда | Метод клиента |
|---|---|
| getFieldTypes | getFieldTypes |
| getRelationTypes | getRelationTypes |
| getDataModel | getDataModel |
| getAllDataModels | getAllDataModels |
| getEntityParents | getEntityParents |
| createDataModel | createDataModel |
| listDataModels | listDataModels |
| saveObject | saveObject |
| saveObjectBatch | saveObjectBatch |
| saveExternalObject | saveExternalObject |
| updateObject | updateObject |
| updateExternalObject | updateExternalObject |
| updateObjectFields | updateFields |
| internalUpdateObjectFields | internalUpdateFields |
| updateObjectFieldsList | updateFieldsList |
| updateObjectFieldsBatch | updateFieldsBatch |
| deleteObject | deleteObject |
| softDeleteObject | softDeleteObject |
| deleteObjectBatch | deleteObjectBatch |
| softDeleteObjectBatch | softDeleteObjectBatch |
| deleteObjectSearch | deleteObjectSearch |
| softDeleteObjectSearch | softDeleteObjectSearch |
| deleteExternalObject | deleteExternalObject |
| saveAdditionalInfo | saveObjectAdditionalInfo |
| saveObjectMetadata | saveObjectMetadata |
| saveObjectMetadataBatch | saveObjectMetadataBatch |
| saveFilesAdditionalInfo | saveFilesAdditionalInfo |
| getObject | getObject |
| internalGetObject | internalGetObject |
| getExternalObject | getExternalObject |
| getExampleObject | getExampleObject |
| listObjects | listObjects |
| listNonExistingFileId | listNonExistingFileId |
| getObjectsBatch | getObjectBatch |
| richGetObject | richGetObject |
| internalRichGetObject | internalRichGetObject |
| internalRichListObject | internalRichListObject |
| richListObjects | richListObjects |
| richGetObjectsBatch | richGetObjectsBatch |
| listObjectsMeta | listObjectsMeta |
| listObjectTitles | listObjectTitles |
| listObjectTitlesV2 | listObjectTitlesV2 |
| getObjectPosition | getObjectPosition |
| getEntityFieldAggregation | getEntityFieldAggregation |
| reindexObject | reindexObject |
| saveRelation | saveRelation |
| saveRelationBatch | saveRelationBatch |
| getRelation | getRelation |
| listRelations | listObjectRelations |
| listAllRelations | listAllRelations |
| listRelationsBatch | listRelationsBatch |
| listRelationsByType | listRelationsByType |
| deleteRelation | deleteRelation |
| deleteRelations | deleteRelations |
| deleteAllRelations | deleteAllRelations |
| updateExternalRelations | updateExternalRelations |
| getObjectLink | getLink |
| getObjectLinks | getLinks |
| createObjectLink | createLink |
| createObjectsLinks | createObjectLinks |
| deleteObjectLink | deleteObjectLink |
| deleteAllObjectLinks | deleteAllObjectLinks |
| listFilesInfoWithTags | listFilesInfoWithTags |
| listTagsWithFilesCount | listTagsWithFilesCount |
| listFileExtensions | listFileExtensions |
| writeFileTags | writeFileTags |
| removeFileTags | removeFileTags |
| removeAllFileTags | removeAllFileTags |
| getFile | getFile |
| updateKeywords | updateKeywords |
| listObjectKeywords | listObjectKeywords |
| listKeywords | listKeywords |
| internalGetMaxNumericFieldValue | internalGetMaxNumericFieldValue |
Erika: сервис печатных форм
В сервисе реализованы следующие команды:
- Создание отчета
- Создание отчета (асинхронная версия)
- Извлечение переменных
- Извлечение переменных (асинхронная версия)
- Конвертация в pdf
- Конвертация в pdf (асинхронная версия)
- Конвертация в pdf c контролем доступа к сгенерированному файлу
- Конвертация в pdf c контролем доступа к сгенерированному файлу (асинхронная версия)
Конфигурирование сервиса Erika
Список переменных окружения сервиса Erika
| Переменная | Тип | Обязательная | Значение по умолчанию | Описание |
|---|---|---|---|---|
SERVER_PORT |
int | нет | 8080 |
Порт, на котором слушает HTTP-сервер. |
SERVICE_TIMEOUTS_ENABLED |
bool | нет | false | Действуют ли переменные SERVER_IDLE_TIMEOUT и SERVER_RESPONSE_TIMEOUT. |
SERVER_IDLE_TIMEOUT |
duration string | нет | 2 hours | Period of Time a connection can remain idle before the connection is timed out and disconnected. Не рекомендован к использованию, так как не отменяет операцию обработки файла. По умолчанию отключен. Для аналогичных целей можно рассмотреть использование PROCESSING_TIMEOUT и query-параметра timeoutSeconds. |
SERVER_RESPONSE_TIMEOUT |
duration string | нет | 1 hour | Time from when the request is made until a response line is generated before a 503 response is returned and the HttpApp is canceled. Не рекомендован к использованию, так как не отменяет операцию обработки файла. По умолчанию отключен. Для аналогичных целей можно рассмотреть использование PROCESSING_TIMEOUT и query-параметра timeoutSeconds. |
PROCESSING_QUEUE_SIZE |
int | нет | 5 |
Размер очереди для всех задач, т.е. уровень буферизации. |
PROCESSING_WORKERS_COUNT |
int | нет | 2 |
Количество воркеров, т.е. уровень параллельности. |
PROCESSING_FILE_READ_CHUNK_SIZE |
int | нет | 16384 |
Размер буфера в байтах для результатов генерации отчетов. |
PROCESSING_TIMEOUT |
duration string | нет | 10 minutes | Таймаут на выполнение задачи воркером. Отменяет операцию обработки файла. |
PROCESSING_GROUP_MAX_PARALLELISM |
int | нет | 5 |
Параллелизм обработки групп отчетов. |
PROCESSING_IMAGES_DIR |
string | нет | /tmp |
Директория для скачивания изображений. |
PROCESSING_FIX_JUSTIFY |
bool | нет | false |
Костыль для корректного отображения на фронте сгенерированных pdf файлов. |
PROCESSING_FULLNESS_LIMIT |
int | нет | 10 |
Тоже отчасти костыль, который ограничивает время, в течении которого все воркеры могут быть заняты. Добавлен, т.к. spire.doc регулярно падает в бесконечный цикл, и свободные воркеры заканчиваются. |
PROCESSING_WATCHER_DURATION |
duration string | нет | 5 seconds |
Периодичность проверки на исчерпание воркеров. При достижении PROCESSING_FULLNESS_LIMIT следующая проверка завершит приложение. |
SPIRE_DOC_LICENSE_KEY |
string | нет | "" |
Лицензионный ключ библиотеки spire.doc Если оставить пустым то будет работать в режиме trial-версии. |
PROCESSING_PDF_BUCKET |
string | нет | pdf |
Название бакета в файловом хранилище для хранения pdf-файлов. Бакет с указанным именем автоматически создается при старте сервиса. Если эта переменная равна пустой строке, то бакет не создается при старте. |
PROCESSING_REPORT_BUCKET |
string | нет | report |
Название бакета в файловом хранилище для хранения сгенерированных отчетов. Бакет с указанным именем автоматически создается при старте сервиса. Если эта переменная равна пустой строке, то бакет не создается при старте. |
PROCESSING_GENERATION_VERSION |
int | нет | 1 |
Версия генерации отчёта. Подробнее: страница Confluence посвященная шаблонам. |
VERDI_CONSUL |
string | нет (если сервис используется без verdi) | http://localhost:8500 |
Адрес Consul. |
VERDI_CONSUL_AUTH_USER |
string | нет | "" |
Название учетной записи Сonsul. Если название не указано, то настройки авторизации не будут применены. |
VERDI_CONSUL_AUTH_PASSWORD |
string | нет | "" |
Пароль учетной записи Сonsul. |
VERDI_KAFKA_AUTH_PRINCIPAL |
string | нет | "" |
Principal учетной записи Kafka в Kerberos(в случае соединения с kafka через Kerberos). |
VERDI_KAFKA_AUTH_KEYTAB_PATH |
string | нет | "" |
Путь до keytab-файла (в случае соединения с kafka через Kerberos). |
VERDI_KAFKA_ADDRESS |
string | да | localhost:9092 |
Адрес брокера Kafka. |
VERDI_KAFKA_TOPIC |
string | нет | commandevents |
Название кафка-топика для отправки сообщений со статусами выполняемых команд. ОБЯЗАТЕЛЬНО должно соответствовать названию этого топика в сервисе статуса команд. |
VERDI_COMMANDS_TOPIC |
string | нет | erika |
Название топика для команд. |
VERDI_CONSUMER_GROUP |
string | нет | erika_consumer_group |
Название consumer-группы для чтения команд. |
VERDI_KAFKA_AUTH_USER |
string | нет | "" |
Название учетной записи Kafka. Если название не указано, то настройки авторизации не будут применены. |
VERDI_KAFKA_AUTH_PASSWORD |
string | нет | "" |
Пароль учетной записи Kafka. |
VERDI_KAFKA_AUTH_TRUSTSTORE_LOCATION |
string | нет | "" |
Путь до хранилища сертификатов (Java key store). Если путь не указан, то сертификат применяться не будет. |
VERDI_KAFKA_AUTH_TRUSTSTORE_PASSWORD |
string | нет | "" |
Пароль к хранилищу сертификатов. |
VERDI_KAFKA_AUTH_MODE |
string | нет | "" |
Режим аутентификации: static - одна учетная запись на все запросы, mapping - учетная запись зависит от запроса. |
VERDI_KAFKA_AUTH_CONFIG |
string | нет | "" |
Настройки для аутентификации: если AuthMode = mapping, то необходим JSON с List[KafkaAuthConfig]. Переменная соответствует полю authConfig из KafkaAuthSettings. |
VERDI_KAFKA_AUTH_CACHE_SIZE |
int | нет | Максимальный размер кеша для Kafka producer (количество активных соединений). | |
VERDI_KAFKA_CONNECTION_CHECK_TEST_MESSAGES_INTERVAL |
duration string | нет | 4 minutes |
Применяется только для producer-ов со способом аутентификации kerberos. Интервал отправки тестовых сообщений кафки в топик connectionCheck.testMessagesTopicName. Тестовые сообщения (null, service producer test) отправляются регулярно с этим интервалом. |
VERDI_KAFKA_CONNECTION_CHECK_INTERVAL |
duration string | нет | 60 seconds |
Применяется только для producer-ов со способом аутентификации kerberos. Интервал проверки того, сколько тестовых сообщений было отправлено за данный период. Если количество сообщений за этот период равно количеству сообщений за прошлый период, то начинается отсчет периода без сообщений. |
VERDI_KAFKA_CONNECTION_CHECK_FAILED_AFTER_INTERVAL |
duration string | нет | 5 minutes |
Применяется только для producer-ов со способом аутентификации kerberos. Максимальная продолжительность периода без успешно отправленных тестовых сообщений. По ее достижении сервис будет объявлен больным. |
VERDI_KAFKA_AUTH_CACHE_TTL |
duration string | нет | Время жизни Kafka producer в кеше. | |
VERDI_HOST |
string | нет (если сервис используется без verdi) | localhost |
Хост, публикуемый в ServiceDiscovery. По нему на данный сервис будут обращаться другие через HTTP. Указанный адрес должен быть виден другим сервисам. Пример: имя kubernetes/docker_swarm service. |
VERDI_TTL |
duration string | нет | 30 seconds |
Период после последней отправки health check, в течение которого ServiceDiscovery считает данный сервис живым. |
VERDI_HEALTH_CHECK |
duration string | нет | 10 seconds |
Периодичность отправки health check в ServiceDiscovery. |
VERDI_COMMAND_STORAGE_UPDATE_PERIOD |
duration string | нет | 1 minutes |
Время кэширования данных по командам из CommandDiscovery. |
VERDI_SERVICE_DISCOVERY_UPDATE_PERIOD |
duration string | нет | 30 seconds |
Время кэширования данных по сервисам из ServiceDiscovery. |
VERDI_ALLOW_INTERNAL_COMMANDS |
bool | нет | true |
Можно ли сервису отправлять внутрисистемные команды. |
VERDI_CONSIDER_ALL_COMMANDS_AS_INTERNAL |
boolean | Нет | false |
Флаг, определяющий будут ли все обращения в другие сервисы являться внутренними (т.е. не требовать авторизацию). Детальное описание механизма: Внутренние команды. |
VERDI_CONSUL_CONNECTION_MAX_RETRY |
int | нет | 5 |
Максимальное количество попыток подключений к Consul. |
VERDI_CONSUL_CONNECTION_RETRY_DELAY |
duration string | нет | 1 seconds |
Таймаут между неудачными попытками подключения к Consul. |
FS_URI |
url string | нет (если сервис используется без verdi) | http://localhost:9002 |
Адрес S3 файлового хранилища minio. |
FS_ACCESS_KEY_ID |
string | нет (если сервис используется без verdi) | admin |
Идентификатор доступа к minio. |
FS_SECRET_ACCESS_KEY |
string | нет (если сервис используется без verdi) | admin |
Секретный ключ доступа к minio. |
FS_UPLOAD_PARALLELISM |
int | нет | 4 |
Параллелизм загрузки файлов в minio. |
FS_AUTH_MODE |
string | нет | static |
Режим аутентификации: static - одна учетная запись на все запросы, mapping - учетная запись зависит от запроса. |
FS_AUTH_CONFIG |
string | нет | "" |
Настройки для аутентификации: если AuthMode = mapping, то необходим JSON с маппингом учетных записей. |
FS_CACHE_SIZE |
int | нет | 1 |
Максимальный размер кеша клиентов для хранилища файлов (количество активных соединений). |
FS_CACHE_TTL |
duration string | нет | Время жизни клиента в кеше. | |
FS_RETRY_ATTEMPTS |
int | нет | 5 |
Количество ретраев, которое будет произведено в случае Exception-а в операции FSClient-а и при вычитывании стрима в get операциях FSClient-а. |
FS_RETRY_DELAY |
duration string | нет | 10 millis |
Задержка между ретраями операций FSClient-а. |
FS_ZIO_SHORT_MESSAGE_MODE |
boolean | нет | false |
Флаг включения режима сохранения ошибок работы с файловым хранилищем в сервисе журналирования nestor. При включении режима ошибки в логах будут отображаться в сокращенном формате: Short zio message mode. ExceptionType: ТИП ОШИБКИ, Exception id: 'СГЕНЕРИРОВАННЫЙ UUID' added to journal. Указанный id будет фиксироваться в event записи nestor'а в поле data.id |
VERDI_ALLOWED |
bool | нет | true |
Интеграция сервиса с verdi. |
VERDI_COMMANDS_HTTP_RETRY_ATTEMPTS |
int | нет | 5 |
Поле attempts из RetrySettings. |
VERDI_COMMANDS_HTTP_RETRY_DELAY |
duration string | нет | 5 seconds |
Поле delay из RetrySettings. |
VERDI_COMMANDS_HTTP_RETRY_KIND |
string | нет | OnSomeExceptions(ConnectException) |
CommandResultRetryConditionKind. |
DISABLE_FONTS_DOWNLOAD |
bool | нет | false |
Определяет, будет ли отключено скачивание шрифтов. Если указать значение "true", то перед стартом сервиса будет выполняться загрузка шрифтов. Если загрузка завершиться с ошибкой, то сервис не будет запущен. |
S3_FONTS_STORE_DIR |
string | нет (если DISABLE_FONTS_DOWNLOAD != true) |
/usr/share/fonts/truetype/msttcorefonts/ |
Путь до папки куда будут скачены шрифты. |
S3_FONTS_URL |
string | нет (если DISABLE_FONTS_DOWNLOAD != true) |
Адрес S3, в котором хранятся шрифты. Например, https://storage.yandexcloud.net. |
|
S3_FONTS_PATH |
string | нет (если DISABLE_FONTS_DOWNLOAD != true) |
erika-fonts/fonts |
Путь до бакета, который содержит файлы со шрифтами (один файл = один шрифт). Например, erika-fonts/fonts. |
S3_FONTS_ACCESS_KEY |
string | нет (если DISABLE_FONTS_DOWNLOAD != true) |
Идентификатор доступа к S3-совместимому хранилищу. | |
S3_FONTS_SECRET_KEY |
string | нет (если DISABLE_FONTS_DOWNLOAD != true) |
Секретный ключ доступа к S3-совместимому хранилищу. | |
JOURNAL_MODE |
string | нет | WriteToJournal |
Режим журналирования Nestor. Допустимые значения: WriteToJournal (Отправка в сервис журналирования), WriteToTopic (Отправка события в очередь) |
JOURNAL_TOPIC |
string | да, если переменная JOURNAL_MODE = WriteToTopic |
"" | Название очереди журналирования. Для режима WriteToJournal значение игнорируется. |
Поддерживаемые форматы для конвертации сервиса Erika
- doc
- docm
- docx
- dot
- dotm
- dotx
- htm
- html
- odt
- rtf
- txt
- wps
- wpt
- xml
Модели сервиса Erika
Progress
Прогресс генерации группы отчетов
| Название поля | Тип | Описание |
|---|---|---|
| id | UUID | Идентификатор генерации |
| rowCount | Int | Общее кол-во групп |
| rowNumber | Int | Кол-во обработанных групп |
StampedDocumentForm
Форма для конвертации документа со штампом
| Название поля | Тип | Описание |
|---|---|---|
| file | File | Документ для конвертации |
| stamp | File | Штамп |
| stampHeight | Float | Высота штампа |
| stampWidth | Float | Ширина штампа |
MergeMode
Тип-сумма режимов объединения групп документов
AllInOne
Группа документов объединяется в один документ. Часть тип-суммы MergeMode
Zip
Группа документов объединяется в один архив. Часть тип-суммы MergeMode
GenerateMode
Тип-сумма режимов генерации отчетов
Single
Режим генерации единичного отчета. Часть тип-суммы GenerateMode
GroupGeneration
Режим генерации группы отчетов. Часть тип-суммы GenerateMode
| Название поля | Тип | Описание | ||
|---|---|---|---|---|
| mergeMode | MergeMode | Режим объединения групп документов | ||
| progressQueue | Option[zio.Queue[Progress]] | Опциональная очередь для отслеживания прогресса |
ReportCommand
Данные для генерации отчета
| Название поля | Тип | Обязательное | Описание |
|---|---|---|---|
| mode | GenerateMode | да | Режим генерации отчета |
| name | string | нет | Имя файла. Расширение (и имя, если не указано) подставляется от шаблона. |
| templateFile | com.embedika.verdi.fsClient.StoredFile | да | Ссылка на шаблон отчета |
| json | io.circe.JsonObject | да | Данные отчета |
| ownerUserId | UserId | нет | Идентификатор пользователя, которому будет предоставлен доступ к сгенерированному файлу через контроль доступа fsclient. |
ConvertToPdf2Command
Данные для конвертации файла в pdf
| Название поля | Тип | Обязательное | Описание |
|---|---|---|---|
| file | com.embedika.verdi.fsClient.StoredFile | да | Исходный файл |
| ownerUserId | UserId | да | Идентификатор пользователя, которому будет предоставлен доступ к сгенерированному файлу через контроль доступа fsclient. |
Команды сервиса Erika
createReport
На входе данные для генерации отчета
{
"mode": "single",
"name": "new_report",
"templateFile": "/tmp/55497df9-bf03-4364-bada-881bbd5531f8",
"json": {
"key": "value"
},
"ownerUserId": "32d96be5-2945-4605-8962-b4ff2797653e"
}
В результате ссылка на файл отчета
"/report/55497df9-bf03-4364-bada-881bbd5531f8"
Создание отчета. При указании в переданном ReportCommand значения в ownerUserId, полученный файл будет доступен для скачивания только пользователю с указанным идентификатором.
Имя вызова команды: createReport.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: ReportCommand
- На выходе: com.embedika.verdi.fsClient.StoredFile
createReportAsync
На входе данные для генерации отчета
{
"mode": "single",
"name": "new_report",
"templateFile": "/tmp/55497df9-bf03-4364-bada-881bbd5531f8",
"json": {
"key": "value"
},
"ownerUserId": "32d96be5-2945-4605-8962-b4ff2797653e"
}
В результате ссылка на файл отчета
"/report/55497df9-bf03-4364-bada-881bbd5531f8"
Создание отчета. При указании в переданном ReportCommand значения в ownerUserId, полученный файл будет доступен для скачивания только пользователю с указанным идентификатором.
Асинхронная версия команды createReport.
Имя вызова команды: createReportAsync.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: ReportCommand
- На выходе: com.embedika.verdi.fsClient.StoredFile
extractVars
На входе ссылка на шаблона отчета
"/tmp/55497df9-bf03-4364-bada-881bbd5531f8"
В результате возвращаются переменные из шаблона в виде строки с JSON массивом
"[ \"key1\", \"key2\" ]"
Извлечение переменных.
Имя вызова команды: extractVars.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: com.embedika.verdi.fsClient.StoredFile
- На выходе: String с сериализованным в Json List[String]
extractVarsAsync
На входе ссылка на шаблона отчета
"/tmp/55497df9-bf03-4364-bada-881bbd5531f8"
В результате возвращаются переменные из шаблона в виде строки с JSON массивом
"[ \"key1\", \"key2\" ]"
Извлечение переменных.
Асинхронная версия команды extractVars.
Имя вызова команды: extractVarsAsync.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: com.embedika.verdi.fsClient.StoredFile
- На выходе: String с сериализованным в Json List[String]
convertToPdf
На входе ссылка на файл для конвертации
"temp/55497df9-bf03-4364-bada-881bbd5531f8"
В результате ссылка на pdf версию
"pdf/55497df9-bf03-4364-bada-881bbd5531f8"
Конвертация в pdf без реализации контроля доступа к сгенерированному файлу. Поддерживаются файлы с расширениями. Исходный файл для конвертации поднимается из файлового хранилища без проверки на доступ для текущего пользователя.
Имя вызова команды: convertToPdf.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: String (URL файла для конвертации)
- На выходе: String (URL сконвертированного файла в бакете pdf)
convertToPdfAsync
На входе ссылка на файл для конвертации
"temp/55497df9-bf03-4364-bada-881bbd5531f8"
В результате ссылка на pdf версию
"pdf/55497df9-bf03-4364-bada-881bbd5531f8"
Конвертация в pdf без реализации контроля доступа к сгенерированному файлу. Поддерживаются файлы с расширениями. Исходный файл для конвертации поднимается из файлового хранилища без проверки на доступ для текущего пользователя.
Асинхронная версия команды convertToPdf.
Имя вызова команды: convertToPdfAsync.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: String (URL файла для конвертации)
- На выходе: String (URL сконвертированного файла в бакете pdf)
convertToPdf2
На входе данные для конвертации
{
"file": "temp/55497df9-bf03-4364-bada-881bbd5531f8",
"ownerUserId": "55497df9-bf03-4364-bada-881bbd5531f8"
}
В результате ссылка на pdf версию
"pdf/55497df9-bf03-4364-bada-881bbd5531f8"
Конвертация в pdf c контролем доступа к сгенерированному файлу. Поддерживаются файлы с расширениями. В отличии от ConvertToPdf исходный файл для конвертации поднимается из файлового хранилища с проверкой на доступ для текущего пользователя.
Имя вызова команды: convertToPdf2.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: ConvertToPdf2Command
- На выходе: String (URL сконвертированного файла в бакете pdf)
convertToPdf2Async
На входе данные для конвертации
{
"file": "temp/55497df9-bf03-4364-bada-881bbd5531f8",
"ownerUserId": "55497df9-bf03-4364-bada-881bbd5531f8"
}
В результате ссылка на pdf версию
"pdf/55497df9-bf03-4364-bada-881bbd5531f8"
Конвертация в pdf c контролем доступа к сгенерированному файлу (асинхронная версия). Поддерживаются файлы с расширениями. В отличии от ConvertToPdf исходный файл для конвертации поднимается из файлового хранилища с проверкой на доступ для текущего пользователя.
Асинхронная версия команды convertToPdf2.
Имя вызова команды: convertToPdf2Async.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: ConvertToPdf2Command
- На выходе: String (URL сконвертированного файла в бакете pdf)
Работа с сервисом erika без использования apigateway
К сервису erika можно обращаться напрямую, без использования apigateway. Для этого существуют следующие http-руты:
/report
Аналог команды createReport.
На входе(режим конвертации single)
curl --request POST \
--url http://myhost/report/single?timeoutSeconds=20 \
--header 'content-type: multipart/form-data' \
--form 'file=@myFile.docx' \
--form 'json=@one.json'
curl --request POST \
--url http://myhost/report/merge?timeoutSeconds=20 \
--header 'content-type: multipart/form-data' \
--form 'file=@myFile.docx' \
--form 'json=@mergeJson.json'
curl --request POST \
--url http://myhost/report/zip?timeoutSeconds=20 \
--header 'content-type: multipart/form-data' \
--form 'file=@myFile.docx' \
--form 'json=@mergeJson.json'
Query-параметр timeoutSeconds во всех случаях является опциональным и определяет то,
через сколько секунд после начала обработки файла воркером стоит отменить эту операцию.
В эту обработку входит как загрузка файла, так и создание отчета, но не входит время ожидания в очереди файлов на обработку.
Если параметр timeoutSeconds не был передан, то операция будет отменена только в том случае, если сработает таймаут PROCESSING_TIMEOUT.
При этом PROCESSING_TIMEOUT не сработает, если timeoutSeconds был передан.
Таймауты SERVER_IDLE_TIMEOUT и SERVER_RESPONSE_TIMEOUT продолжают действовать даже при наличии timeoutSeconds.
На выходе (режим конвертации single)
Бинарное содержимое файла с расширением .docx и header Content-Disposition.
В файл myFile.docx подставлены данные из one.json.
На выходе (режим конвертации merge)
Бинарное содержимое файла с расширением .docx и header Content-Disposition.
В файл myFile.docx поочередно подставлены данные из массива внутри mergeJson.json.
Получено несколько файлов .docx, которые склеены в один большой .docx файл, возвращенный в результате.
На выходе (режим конвертации zip)
Бинарное содержимое файла с расширением .zip и header Content-Disposition.
В файл myFile.docx поочередно подставлены данные из массива внутри mergeJson.json.
Получено несколько файлов .docx, которые упакованы в zip-архив, возвращенный в результате.
Подробнее про формирование header-а Content-Disposition можно прочитать в документации сервиса apigateway
/convert
Аналог команды convertToPdf.
На входе
curl --request POST \
--url 'http://myhost/convert?timeoutSeconds=20' \
--header 'content-type: multipart/form-data' \
--form 'file=@myFile.doc'
Query-параметр timeoutSeconds во всех случаях является опциональным и определяет то,
через сколько секунд после начала обработки файла воркером стоит отменить эту операцию.
В эту обработку входит как загрузка файла, так и создание отчета, но не входит время ожидания в очереди файлов на обработку.
Если параметр timeoutSeconds не был передан, то операция будет отменена только в том случае, если сработает таймаут PROCESSING_TIMEOUT.
При этом PROCESSING_TIMEOUT не сработает, если timeoutSeconds был передан.
Таймауты SERVER_IDLE_TIMEOUT и SERVER_RESPONSE_TIMEOUT продолжают действовать даже при наличии timeoutSeconds.
На выходе
Бинарное содержимое файла с расширением .pdf и header Content-Disposition.
Подробнее про формирование header-а можно прочитать в документации сервиса apigateway
Event-status: сервис информации о событиях
Сервис принимает запросы для работы со статусом обработки событий. На данный момент все состояние сервиса хранится в
памяти.
Команды могут приходить как по HTTP, так и через Kafka в топик event_status_commands.
В сервисе реализованно 2 команды:
Сервис разбит на несколько модулей, в виде sbt проектов:
domain, в котором содержатся все доменные модели и их различные представления.commands, в котором содержатся все? что связано с командами, их описанием и обработчиками.infrastructure, в котором содержится описание взаимодействия с другими сервисами.storage, содержит сервисы для сохранения и чтения их разных хранилищ доменных моделей.service, содержит сервисы бизнес логики, которые определяют правила взаимодействия компонентов между собой.boot, содержит зависимости и описание для сборки и запуска сервиса.
Информация по добавлению команд можно прочитать в описании шаблона
Локальный запуск сервиса Event Status
При запуске сервиса ожидается, что уже развернута необходимая инфраструктура:
- PostgreSQL база по адресу
localhost:5432/eventStatus_db - Kafka по адресу
localhost:9092 - Consul по адресу
localhost:8500 - Адрес Kafka будет указан в
application.conf - Добавлены необходимые переменные окружения:
- EVENT_STATUS_DB_HOST
- EVENT_STATUS_DB_PORT
- EVENT_STATUS_DB_NAME
- EVENT_STATUS_DB_USER
- EVENT_STATUS_DB_PASSWORD
Запуск из консоли с помощью SBT сервиса Event Status
EVENT_STATUS_DB_HOST=localhost EVENT_STATUS_DB_PORT=5432 EVENT_STATUS_DB_NAME=eventStatus_db EVENT_STATUS_DB_USER=$EVENT_STATUS_DB_USER EVENT_STATUS_DB_PASSWORD=$EVENT_STATUS_DB_PASSWORD sbt boot/run
Список переменных окружения сервиса Event Status
Все доступные переменные окружения для настройки сервиса.
| Переменная | Тип | Обязательная | Значение по умолчанию | Описание |
|---|---|---|---|---|
EVENT_STATUS_HTTP_HOST |
string | нет | "0.0.0.0" | Хост, на котором слушает HTTP-сервер |
EVENT_STATUS_HTTP_PORT |
int | нет | 8192 | Порт, на котором слушает HTTP-сервер |
EVENT_STATUS_KAFKA_SERVERS |
string | да | "localhost:9092" | Адрес Kafka |
EVENT_STATUS_KAFKA_TOPIC |
string | нет | "event_status_commands" | Название кафка-топика для получения команд. Сервис получает кафка-команды по нему, но и также сам публикует это название в CommandDiscovery. |
EVENT_STATUS_KAFKA_CONSUMER_GROUP |
string | нет | "event_status_consumer_group" | Имя consumer-группы для чтения из кафка-топика команд. Не должна меняться и не должна быть пустой, иначе сервис перечитает свои команды при перезапуске. |
EVENT_STATUS_KAFKA_PARTITIONS |
int | нет | 10 | Число читаемых партиций из кафка-топика команд. |
EVENT_STATUS_KAFKA_CONSUMER_RESTART_MIN_BACKOFF |
duration string | нет | 1 second | Изначальная задержка до рестарта консьюмера после падения (увеличивается в 2 раза после каждого рестарта) |
EVENT_STATUS_KAFKA_CONSUMER_RESTART_MAX_BACKOFF |
duration string | нет | 30 seconds | Максимальное задержка до рестарта консьюмера после падения |
EVENT_STATUS_KAFKA_CONSUMER_RESTART_RANDOM_FACTOR |
double | нет | 0.2 | Коэффициент величины дополнительной случайной задержки (jitter) относительно основной задержки (При значении 0.2 задержка может быть до 20% больше, чем при 0). Если после умножения задержки на EVENT_STATUS_KAFKA_CONSUMER_RESTART_RANDOM_FACTOR получится меньше 1 миллисекунды, то jitter будет приравнен к нулю. |
EVENT_STATUS_KAFKA_CONSUMER_RESTART_MAX_RESTARTS |
int | нет | 5 | Максимальное число рестартов консьюмера после падения (в пределах EVENT_STATUS_KAFKA_CONSUMER_RESTART_MAX_RESTARTS_WITHIN). После превышения этого числа сервис будет объявлен больным. Все рестарты для каждого отдельного сообщения увеличивают и общий счетчик рестартов консьюмера, поэтому при использовании EVENT_STATUS_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS нужно указывать EVENT_STATUS_KAFKA_CONSUMER_RESTART_MAX_RESTARTS > EVENT_STATUS_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS или не указывать EVENT_STATUS_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS совсем |
EVENT_STATUS_KAFKA_CONSUMER_RESTART_MAX_RESTARTS_WITHIN |
duration string | нет | 5 minutes | Временной отрезок, в который EVENT_STATUS_KAFKA_CONSUMER_RESTART_MAX_RESTARTS ограничивает число рестартов |
EVENT_STATUS_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS |
int | нет | 2 | Максимальное количество раз, которое консьюмер перезапустится с неизменной очередью сообщений (в пределах DATA_MODEL_KAFKA_CONSUMER_RESTART_MAX_RESTARTS_WITHIN), прежде чем проигнорировать сообщение, на котором происходит ошибка (Указано количество рестартов, а не прочтений. Если EVENT_STATUS_KAFKA_CONSUMER_RESTART_MAX_RESTARTS = 2, то ошибочное сообщение будет обработано 3 раза, после чего произойдет 3ий рестарт и оно будет проигнорировано). Если указать 0, то перезапуск произойдет, но сообщение будет обработано только в первый раз, когда произошла ошибка. Если указать значение меньше 0, то перезапуски все равно будут происходить, но игнорирование сообщений, вызывающих ошибку, будет отключено. |
EVENT_STATUS_KAFKA_CONSUMER_PER_MESSAGE_RESTART_CACHE_SIZE |
int | нет | 100 | Для каждого сообщения счетчик перепрочтений хранится в кэше. Максимальное количество значений в этом кэше. |
EVENT_STATUS_KAFKA_CONSUMER_PER_MESSAGE_RESTART_CACHE_TTL |
duration string | нет | 5 minutes | Для каждого сообщения счетчик перепрочтений хранится в кэше. Максимальное время жизни элемента в этом кэше. В случае отсутствия значения время жизни элемента не будет ограничено. |
EVENT_STATUS_KAFKA_CONSUMER_POLL_TIMEOUT |
duration string | нет | 10 milliseconds | timeout запроса poll для kafka consumer |
EVENT_STATUS_KAFKA_CONSUMER_POLL_INTERVAL |
duration string | нет | 100 milliseconds | интервал между запросами poll для kafka consumer |
EVENT_STATUS_KAFKA_CONSUMER_PROPS |
string | нет | "max.poll.records=500;max.partition.fetch.bytes=524288" | дополнительные параметры для kafka consumer в формате "key1=value1;key2=value2" |
EVENT_STATUS_KAFKA_COMMANDEVENT_TOPIC |
string | да | "commandevents" | Название кафка-топика для отправки сообщений со статусами выполняемых команд. ОБЯЗАТЕЛЬНО должно соответствовать названию этого топика в сервисе статуса команд. |
EVENT_STATUS_KAFKA_AUTH_USER |
string | нет | "" | Название учетной записи Kafka. Если название не указано, то настройки авторизации не будут применены. |
EVENT_STATUS_KAFKA_AUTH_PASSWORD |
string | нет | "" | Пароль учетной записи Kafka. |
EVENT_STATUS_KAFKA_AUTH_PRINCIPAL |
string | нет | "" | Principal учетной записи Kafka в Kerberos(в случае соединения с kafka через Kerberos). |
EVENT_STATUS_KAFKA_AUTH_KEYTAB_PATH |
string | нет | "" | Путь до keytab-файла (в случае соединения с kafka через Kerberos). |
EVENT_STATUS_KAFKA_AUTH_TRUSTSTORE_LOCATION |
string | нет | "" | Путь до хранилища сертификатов (Java key store). Если путь не указан, то сертификат применятся не будет. |
EVENT_STATUS_KAFKA_AUTH_TRUSTSTORE_PASSWORD |
string | нет | "" | Пароль к харнилищу сертификатов. |
EVENT_STATUS_KAFKA_AUTH_MODE |
string | нет | "" | Режим аутентификации: static - одна учетная запись на все запросы, mapping - учетная запись зависит от запроса |
EVENT_STATUS_KAFKA_AUTH_CONFIG |
string | нет | "" | Настройки для аутентификации: если AuthMode = mapping, то необходим JSON с List[KafkaAuthConfig] соответствует полю authConfig KafkaAuthSettings |
EVENT_STATUS_KAFKA_AUTH_CACHE_SIZE |
int | нет | Максимальный размер кэша для Kafka producer (количество активных соединений). | |
EVENT_STATUS_KAFKA_CONNECTION_CHECK_TEST_MESSAGES_INTERVAL |
duration string | нет | 4 minutes | Применяется только для producer-ов со способом аутентификации kerberos. Интервал отправки тестовых сообщений кафки в топик connectionCheck.testMessagesTopicName. Тестовые сообщения (null, service producer test) отправляются регулярно с этим интервалом. |
EVENT_STATUS_KAFKA_CONNECTION_CHECK_INTERVAL |
duration string | нет | 60 seconds | Применяется только для producer-ов со способом аутентификации kerberos. Интервал проверки того, сколько тестовых сообщений было отправлено за данный период. Если количество сообщений за этот период равно количеству сообщений за прошлый период, то начинается отсчет периода без сообщений. |
EVENT_STATUS_KAFKA_CONNECTION_CHECK_FAILED_AFTER_INTERVAL |
duration string | нет | 5 minutes | Применяется только для producer-ов со способом аутентификации kerberos. Максимальная продолжительность периода без успешно отправленных тестовых сообщений. По ее достижении сервис будет объявлен больным. |
EVENT_STATUS_KAFKA_AUTH_CACHE_TTL |
duration string | нет | Время жизни Kafka producer в кэше. | |
EVENT_STATUS_CONSUL_ADDR |
url string | нет | "http://localhost:8500" | Адрес Сonsul. |
EVENT_STATUS_CONSUL_AUTH_USER |
string | нет | "" | Название учетной записи Сonsul. Если название не указано, то настройки авторизации не будут применены. |
EVENT_STATUS_CONSUL_AUTH_PASSWORD |
string | нет | "" | Пароль учетной записи Сonsul. |
EVENT_STATUS_TRACE_DURATION |
boolean | нет | false | Признак необходимости трассировки выполнения команд |
EVENT_STATUS_DISCOVERABLE_ID |
string | нет | "another_EVENT_STATUS_service_instance" | ID сервиса в ServiceDiscovery |
EVENT_STATUS_DISCOVERABLE_NAME |
string | нет | "eventStatus" | Имя сервиса в ServiceDiscovery |
EVENT_STATUS_DISCOVERABLE_HOST |
string | да | "localhost" | Хост, публикуемый в ServiceDiscovery. По нему на данный сервис будут обращаться другие через HTTP. Указанный адрес должен быть виден другим сервисам. Пример: имя kubernetes/docker_swarm service |
EVENT_STATUS_DISCOVERABLE_PORT |
int | нет | Порт, публикуемый в ServiceDiscovery. По нему на данный сервис будут обращаться другие через HTTP. По умолчанию указывается порт, который слушает HTTP-сервер. | |
EVENT_STATUS_DISCOVERABLE_LIVETIME |
duration string | нет | 2 minutes | Период после последней отправки health check, в течение которого ServiceDiscovery считает данный сервис живым. |
EVENT_STATUS_DISCOVERABLE_HEALTHPASS |
string | нет | 1 minute | Периодичность отправки health check в ServiceDiscovery |
EVENT_STATUS_SERVICE_TITLE |
string | нет | "Event Status" | Название сервиса для отображения |
EVENT_STATUS_SERVICE_DESCRIPTION |
string | нет | "Service EVENT_STATUS" | Описание сервиса для отображения |
EVENT_STATUS_AKKA_HTTP_CLIENT_MAXCON |
int | нет | 512 | Максимальное число одновременных исходящих HTTP-соединений |
EVENT_STATUS_AKKA_HTTP_CLIENT_MAXREQ |
int | нет | 1024 | Максимальное число одновременных исходящих HTTP-запросов |
EVENT_STATUS_AKKA_HTTP_SERVER_MAXCON |
int | нет | 1024 | Максимальное число одновременных входящих HTTP-соединений |
EVENT_STATUS_INTERNALCMD_ALLOW |
bool | нет | false | Можно ли сервису отправлять внутрисистемные команды |
EVENT_STATUS_SENDERLIB_CONSIDER_ALL_COMMANDS_AS_INTERNAL |
boolean | Нет | false |
Флаг, определяющий будут ли все обращения в другие сервисы являться внутренними (т.е. не требовать авторизацию). Детальное описание механизма: Внутренние команды. |
EVENT_STATUS_SENDERLIB_COMMANDS_CACHE_UPDATEPERIOD |
duration string | нет | 10 minutes | Время кэширования данных по командам из CommandDiscovery |
EVENT_STATUS_SENDERLIB_SERVICES_CACHE_UPDATEPERIOD |
duration string | нет | 30 seconds | Время кэширования данных по сервисам из ServiceDiscovery |
EVENT_STATUS_SENDERLIB_CONSUL_CONNECTION_RETRY_MAX |
int | нет | 5 | Количество попыток переподключения к Consul |
EVENT_STATUS_SENDERLIB_CONSUL_CONNECTION_RETRY_DELAY |
duration string | нет | 1 second | Задержка при попытках переподключения к Consul |
EVENT_STATUS_DB_HOST |
string | да | Хост БД | |
EVENT_STATUS_DB_PORT |
int | да | Порт БД | |
EVENT_STATUS_DB_NAME |
string | да | Имя базы в БД | |
EVENT_STATUS_DB_URL |
jdbc url string | нет | JDBC-url для соединения с БД. По умолчанию собирается из других обязательных переменных. Можно указать только его, если не хочется отдельно указывать хост/порт/имя базы. | |
EVENT_STATUS_DB_USER |
string | да | Пользователь БД | |
EVENT_STATUS_DB_PASSWORD |
string | да | Пароль пользователя БД | |
EVENT_STATUS_DB_THREADS |
int | нет | 10 | Количество потоков в пуле потоков для соединения с БД |
EVENT_STATUS_DB_QUEUE_SIZE |
int | нет | 300 | Размер очереди для действий базы данных, которые не могут быть выполнены немедленно, когда все потоки заняты. За пределами этого значения новые действия немедленно завершаются неудачей |
EVENT_STATUS_DB_CONN_MAX |
int | нет | 10 | Максимальное количество одновременных подключений к БД |
EVENT_STATUS_DB_CONN_TIMEOUT |
duration string | нет | 20 second | Максимальное время ожидания ответа для соединения к БД. Если это время превышено, а соединение не становится доступным, будет брошено исключение SQLException. 1000 мс — минимальное значение. |
EVENT_STATUS_DB_ISOLATION |
string | нет | "READ_COMMITTED" | Уровень изоляции транзакций для новых подключений. Допустимые значения: NONE, READ_COMMITTED, READ_UNCOMMITTED, REPEATABLE_READ, SERIALIZABLE. |
EVENT_STATUS_DB_READONLY |
boolean | нет | false | Read-only SQL транзакция может изменять только временные таблицы. Этот параметр управляет статусом «только для чтения» по умолчанию для каждой новой транзакции. |
EVENT_STATUS_DB_CONN_MIN |
int | нет | = DB_THREADS | Минимальное количество одновременных подключений к БД |
EVENT_STATUS_DB_VALIDATION_TIMEOUT |
duration string | нет | 1 seconds | Максимальное время, в течение которого соединение будет проверяться на работоспособность. 1000 мс — минимальное значение. |
EVENT_STATUS_DB_IDLE_TIMEOUT |
duration string | нет | 10 minutes | Максимальное время, в течение которого соединению разрешено простаивать в пуле. Значение 0 означает, что простаивающие соединения никогда не удаляются из пула. |
EVENT_STATUS_DB_MAX_LIFETIME |
duration string | нет | 30 minutes | Максимальное время жизни соединения в пуле. Когда простаивающее соединение достигает этого времени ожидания, даже если оно недавно использовалось, оно будет удалено из пула. Значение 0 указывает на отсутствие максимального срока службы. |
EVENT_STATUS_DB_INITIALIZATION_FAIL_FAST |
string | нет | false | Deprecated, начиная с версии Slick 3.3.0. Определяет, будет ли пул «быстро выходить из строя», если пул не может быть успешно заполнен начальными соединениями. Если соединения не могут быть созданы во время запуска пула, будет выдано исключение RuntimeException. Это свойство не имеет никакого эффекта, если minConnections равно 0. |
EVENT_STATUS_DB_LEAK_DETECTION_THRESHOLD |
int | нет | 0 | Время, в течение которого соединение может находиться вне пула, прежде чем будет зарегистрировано сообщение, указывающее на возможную утечку соединения. Значение 0 означает, что обнаружение утечек отключено. Наименьшее приемлемое значение для включения обнаружения утечек составляет 10 с. |
EVENT_STATUS_DB_CONNECTION_TEST_QUERY |
string | нет | "SELECT 1" | Выражение, которое будет выполнено непосредственно перед получением соединения из пула для проверки того, что соединение с базой данных все еще активно. Оно зависит от базы данных и должно представлять собой запрос, требующий минимальной обработки базой данных (например, «VALUES 1»). Если этот параметр не установлен, вместо него используется метод JDBC4 Connection.isValid(). |
EVENT_STATUS_DB_AUTO_COMMIT |
boolean | нет | true | Это свойство определяет то, как будут вести себя по умолчанию возвращаемые соединения относительно autocommit-а. |
EVENT_STATUS_DB_SCHEMA |
string | нет | "public" | Устанавливает schema по умолчанию |
EVENT_STATUS_DB_ISOLATE_INTERNAL_QUERIES |
boolean | нет | false | Определяет то, изолируются ли с помощью транзакций внутренние запросы пула (например запрос connection alive test). Свойство применяется только если autoCommit выключен. |
EVENT_STATUS_DB_INITIALIZATION_FAIL_TIMEOUT |
int | нет | 1 | Работает, начиная с версии Slick 3.3.0. Определяет, будет ли пул «быстро выходить из строя», если пул не может быть успешно заполнен начальными соединениями. Любое положительное число считается числом миллисекунд для попытки получить начальное соединение;поток приложения будет заблокирован в течение этого периода. Если соединение не может быть получено до истечения этого времени, будет брошено исключение. Данный таймаут применяется после периода connectionTimeout. Если значение равно нулю (0),HikariCP попытается получить и проверить подключение. Если соединение получено, но проверка не пройдена, будет брошено исключение, и пул не будет запущен. Однако, если соединение не может быть получено, пул запустится, но последующие попытки получить соединение могут потерпеть неудачу. Значение меньше нуля пройдет любую первоначальную попытку подключения, и пул немедленно запустится, пытаясь получить соединения в фоновом режиме. Следовательно, последующие попытки получить соединение могут потерпеть неудачу. |
EVENT_STATUS_DB_REGISTER_MBEANS |
boolean | нет | false | Зарегистрированы ли JMX Management Beans («MBeans») |
EVENT_STATUS_AUTHZFORCE_ADDR |
string | нет | "http://localhost:8080/authzforce-ce" | Адрес AuthZforce server |
EVENT_STATUS_AUTHZFORCE_DOMAIN |
string | нет | "" | Доступный DomainID в AuthZforce server |
EVENT_STATUS_EVENT_CACHE_MAX_SIZE |
int | нет | 1000 | Максимальное количество событий в кэше |
EVENT_STATUS_EVENT_CACHE_EXPIRE_AFTER_WRITE_SECONDS |
int | нет | 60 | Время в секундах, после которого элементы убираются из кэша |
EVENT_STATUS_JOURNAL_MODE |
string | Нет | "WriteToJournal" | Режим журналирования Nestor. Допустимые значения: WriteToJournal (Отправка в сервис журналирования), WriteToTopic (Отправка события в очередь) |
EVENT_STATUS_JOURNAL_TOPIC |
string | Да, если переменная EVENT_STATUS_JOURNAL_MODE = WriteToTopic |
"" | Название очереди журналирования. Для режима WriteToJournal значение игнорируется. |
Список команд сервиса Event Status
Команды сервиса информации о событиях:
| Команда | EntityType | Actions |
|---|---|---|
| eventStatus_http_publishHandledEvent | - | - |
| eventStatus_longPool_waitForEvent | - | - |
| eventStatus_longPool_waitForMultipleEvents | - | - |
publishHandledEvent
На входе описание события
{
"eventType": "test",
"payloadType": "test",
"payloadId": "test",
"serviceName": "test",
"payloadVersion": 5
}
На выходе ничего
{
"status": "Completed",
"timestamp": 1683184345008,
"value": {}
}
Публикует информацию, что сервис завершил обработку события и разблокирует всех кто ждет данное событие.
Имя команды для вызова eventStatus_http_publishHandledEvent.
Поддерживает только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: HandledEventDto
- На выходе: Unit
waitForEvent
На входе описание события и таймаут
{
"timeoutSeconds": 30,
"eventToWait": {
"eventType": "test",
"payloadType": "test",
"payloadId": "test",
"serviceName": "test",
"payloadVersion": 5
}
}
На выходе true, если событие уже обработано
{
"status": "Completed",
"timestamp": 1683184345008,
"value": true
}
Дожидается публикации информации о событии в сервисе. Работает через механизм Long-Pool
Имя команды для вызова eventStatus_longPool_waitForEvent.
Поддерживает только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: WaitForEventDto
- На выходе: Boolean
waitForMultipleEvents
На входе описание событий и timeout
{
"timeoutSeconds": 5,
"eventsToWait": [
{
"eventType": "test",
"payloadType": "test",
"payloadId": "test",
"serviceName": "test",
"payloadVersion": 5
}
]
}
На выходе список Boolean, аналогично waitForEvent
{
"status": "Completed",
"timestamp": 1683184345008,
"value": [
true
]
}
Дожидается публикации информации о всех событиях в сервисе. По истечению timeout возвращает результат по каждому событию.
Имя команды для вызова eventStatus_longPool_waitForMultipleEvents.
Поддерживает только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: [WaitForEventsDto]
- На выходе: List[Boolean]
Объекты сервиса EventStatus
HandledEventDto
Модель для уведомления, что serviceName обработал событие. Хранится в verdi-models.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| eventType | String | да | Тип события |
| payloadType | String | да | Тип объекта в событии |
| payloadId | String | да | Id объекта в событии |
| serviceName | String | да | Имя сервиса, обработкал событие |
| payloadVersion | Long | нет | Версия объекта в событии |
WaitForEventDto
Модель для ожидания события. Хранится в verdi-models.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| timeoutSeconds | Int | да | Максимальное ожидание в секундах |
| eventToWait | HandledEventDto | да | Событие, которого нужно дождаться |
WaitForEventsDto
Модель для ожидания события. Хранится в verdi-models.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| timeoutSeconds | Int | да | Максимальное ожидание в секундах |
| eventsToWait | HandledEventDto | да | События, которых нужно дождаться |
Exporter: библиотека для экспорта данных в различные форматы
Библиотека содержит:
- Общие типы и интерфейс для универсального экспортера (CellData, Exporter).
- Реализацию, которая генерирует файлы в формате xlsx (XlsxExporter).
- Вспомогательный класс, который позволяет из типичных функций Search => Page делать экспорт в S3 (ExportHelper).
Экспорт в Excel
Экспорт в Excel генерирует xlsx таблицу с фильтрами и обводкой. Используется Apache POI.
Поддерживает режимы:
- XSSFWorkbook:
- Подходит для небольших объемов данных (10к строк без большого потребления памяти).
- Хранит все временные данные в оперативной памяти.
В будущем при необходимости можно добавить поддержку других форматов:
- SXSSFWorkbook:
- Стриминговый режим, который позволяет обрабатывать большие объемы данных.
- Некоторые клиенты неадекватно реагируют на файлы, сгенерированные в этом режиме.
- Сохраняет временные файлы на диск, что нежелательно в контейнерах.
- Все равно нужно подготовить данные целиком, а потом экспортировать.
- DeferredSXSSFWorkbook:
- Стриминговый режим, который позволяет обрабатывать большие объемы данных.
- Некоторые клиенты неадекватно реагируют на файлы, сгенерированные в этом режиме.
- Не сохраняет временные файлы на диск.
- При редактировании таблицы сразу сохраняет результат в целевой файл.
- Предположительно имеет существенно больший оверхэд на маленьких данных.
- Сложнее в реализации.
- Считается экспериментальным.
FS-client: библиотека для работы с файловым хранилищем
Предоставляемый функционал FSClient
Библиотека предоставляет интерфейс и реализацию клиента файлового хранилища.
Предоставляемые реализации клиента LiveFSClient, LiveFSClientCached обеспечивают логику ограничения прав доступа к
загруженным файлам через опциональный атрибут контроля, хранящий идентификатор пользователя в поле ownerUserId FileMeta.
При отсутствии в нем какого-либо значения файл будет считаться доступным всем. При отсутствии доступа будет возвращена
ошибка DownloadForbidden.
Фиксация атрибута контроля доступа происходит при использовании апи uploadPrivate(), copyAndUpdateAccessSettings().
Отключение механизма контроля происходит через передачу пустого параметра ownerUserId: Option[UserId] в методы апи:
get(), getMeta(), getManaged().
Управление бакетами
- createBucketIfNotExist
/**
* Создать бакет если он еще не создан
* @param bucket Бакет
* @return Существовал ли бакет до вызова метода
*/
def createBucketIfNotExist(bucket: String): ZIO[FSClient, FSError, Boolean]
Работа с файлами
/**
* Получить файл с опциональной проверкой на наличие доступа при переданном ownerUserId
* @param storedFile Описание хранимого файла
* @param ownerUserId Идентификатор пользователя
* @return Стрим из файла и метаданные файла
*/
def get(
storedFile: StoredFile,
ownerUserId: Option[UserId] = None
): ZIO[FSClient, FSError, (Stream[FSError, Byte], FSMetadata)]
/**
* Получить файл как ресурс с опциональной проверкой на наличие доступа при переданном ownerUserId
* @param storedFile Описание хранимого файла
* @param ownerUserId Идентификатор пользователя
* @return InputStream открытый только в рамках ресурс и метаданные файла
*/
def getManaged(storedFile: StoredFile, ownerUserId: Option[UserId] = None): ZManaged[FSClient, FSError, (InputStream, FSMetadata)]
/**
* Получить метаданные файла без самого файла с опциональной проверкой на наличие доступа при переданном ownerUserId
* @param storedFile Описание хранимого файла
* @param ownerUserId Идентификатор пользователя
* @return Метаданные файла
*/
def getMeta(storedFile: StoredFile, ownerUserId: Option[UserId] = None): ZIO[FSClient, FSError, FSMetadata]
/**
* Загрузка файла. Загруженный файл будет доступен всем.
* @param storedFile описание сохраняемого файла
* @param name имя
* @param body стрим из файла
* @param parallelism уровень параллелизма загрузки
* @return
*/
def upload(
storedFile: StoredFile,
name: String,
body: Stream[Throwable, Byte],
parallelism: Int,
contentType: Option[String] = None
): ZIO[FSClient, FSError, Unit]
/**
* Загрузка файла с установкой атрибута для последующего контроля доступа к файлу (загруженный файл будет доступен
* только пользователю с идентификатором ownerUserId).
* @param storedFile описание сохраняемого файла
* @param name имя
* @param body стрим из файла
* @param parallelism уровень параллелизма загрузки
* @param ownerUserId Идентификатор пользователя
* @return
*/
def uploadPrivate(
storedFile: StoredFile,
name: String,
body: Stream[Throwable, Byte],
parallelism: Int,
ownerUserId: UserId,
contentType: Option[String] = None
): ZIO[FSClient, FSError, Unit]
/**
* Перемещение файла. При изменении бакета у файла будут сброшены опциональные настройки доступа.
* @param source Описание исходного хранимого файла для перемещения
* @param destination Описание желаемого места, куда перемещается файл
* @return
*/
def move(source: StoredFile, destination: StoredFile): ZIO[FSClient, FSError, FSMetadata]
/**
* Перемещение файла с сохранением исходного опционального атрибута для контроля доступа к файлу
* @param source Описание исходного хранимого файла для перемещения
* @param destination Описание желаемого места, куда перемещается файл
* @return
*/
def moveWithAccessControl(source: StoredFile, destination: StoredFile): ZIO[FSClient, FSError, FSMetadata]
/**
* Копирование файла. При изменении бакета у копии будут сброшены опциональные настройки доступа.
* @param source Описание исходного хранимого файла для перемещения
* @param destination Описание желаемого места, куда копируется файл
* @return
*/
def copy(source: StoredFile, destination: StoredFile): ZIO[FSClient, FSError, FSMetadata]
/**
* Копирование файла с сохранением исходного опционального атрибута для контроля доступа к файлу
* @param source Описание исходного хранимого файла для перемещения
* @param destination Описание желаемого места, куда копируется файл
* @return
*/
def copyWithAccessControl(source: StoredFile, destination: StoredFile): ZIO[FSClient, FSError, FSMetadata]
/**
* Копирование файла с принудительной установкой атрибута для последующего контроля доступа к файлу-копии
* ВАЖНО: метод не реализует проверку наличия доступа к исходному файлу
* @param source Описание исходного хранимого файла для перемещения
* @param destination Описание желаемого места, куда копируется файл
* @param ownerUserId Идентификатор пользователя
* @return
*/
def copyAndUpdateAccessSettings(
source: StoredFile,
destination: StoredFile,
ownerUserId: UserId
): ZIO[FSClient, FSError, FSMetadata]
/**
* Получить список файлов
* @param bucket путь
* @return Список с описанием файлов бакетов
*/
def list(bucket: String, path: Path = Path.of("")): URIO[FSClient, Stream[FSError, FileListEntity]]
/**
* Удаление файла
* @param storedFile Описание хранимого файла
* @return
*/
def delete(storedFile: StoredFile): ZIO[FSClient, FSError, Unit]
- get
- getManaged
- getMeta
- upload
- uploadPrivate
- move
- moveWithAccessControl
- copy
- copyWithAccessControl
- copyAndUpdateAccessSettings
- list
- delete
Структуры FSClient
FSConfigRep (FSClient)
Отображение FSConfig в "плоской форме", как он выглядит в конфиге приложения application.conf.
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
| uri | String | Да | Адрес файлового хранилища для подключения. | Не пустое |
| uploadParallelism | Int | Да | Параллелизм загрузки файлов в файловое хранилище. | > 0 |
| accessKeyId | String | Да, если authMode=Static | ID для подключения (не зависит от бакета). | Не пустое |
| secretAccessKey | String | Да, если authMode=Static | Key для подключения (не зависит от бакета). | Не пустое |
| authMode | String | Нет | Режим аутентификации клиента: Static - данные для подключения не зависят от бакета, Mapping - данные зависят от бакета. По-умолчанию Static. | "Static", "Mapping" |
| authConfig | String | Да, если authMode=Mapping | Настройки для выбранного режима аутентификации. Если authMode=Mapping, то ожидается Seq[FSBucketConfig] в формате JSON. | |
| clientsCache | VerdiCacheConfig | Нет | Настройки кеша для клиентов файлового хранилища. | |
| retrySettings | RetrySettings | Нет | Настойки для повтороного вызова функций файлового хранилища. | |
| zioShortMessageMode | Boolean | Нет | Флаг включения режима сохранения ошибок работы с файловым хранилищем в сервисе журналирования nestor. При включении режима ошибки в логах клиентского приложения будут отображаться в сокращенном формате: Short zio message mode. ExceptionType: ТИП ОШИБКИ, Exception id: 'СГЕНЕРИРОВАННЫЙ UUID' added to journal. Указанный id будет фиксироваться в event записи nestor'а в поле data.id |
FSConfig (FSClient)
Конфигурация клиента файлового хранилища.
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
| uri | String | Да | Адрес файлового хранилища для подключения | Не пустое |
| uploadParallelism | Int | Да | Параллелизм загрузки файлов в файловое хранилище | > 0 |
| credentials | Seq[FSBucketConfig] | Да | Список данных для учетных записей для подключения к бакетам | |
| clientsCache | VerdiCacheConfig | Да | Настройки кеша для клиентов файлового хранилища | |
| retrySettings | RetrySettings | Нет | Настойки для повтороного вызова функций файлового хранилища. | |
| zioShortMessageMode | Boolean | Нет | Флаг включения режима сохранения ошибок работы с файловым хранилищем в сервисе журналирования nestor. При включении режима ошибки в логах клиентского приложения будут отображаться в сокращенном формате: Short zio message mode. ExceptionType: ТИП ОШИБКИ, Exception id: 'СГЕНЕРИРОВАННЫЙ UUID' added to journal. Указанный id будет фиксироваться в event записи nestor'а в поле data.id |
FSBucketConfig (FSClient)
Данные для аутентификации, которые привязаны к конкретному бакету.
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
| bucketName | String | Да | Название бакета. Если значение пустое, то данные подходят для любого бакета. | |
| bucketAlias | List[String] | Нет | Список альтернативных названий бакета. | Не пустое |
| credentials | FSCredentials | Да | Данные учетной записи для подключения к бакету. |
FSCredentials (FSClient)
Данные для аутентификации.
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
| accessKeyId | String | Да | ID для подключения | Не пустое |
| secretAccessKey | String | Да | Key для подключения | Не пустое |
StoredFile
Информация о файле. Становится строкой в формате "{bucket}/{path}/{id}" при конвертации в json.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | string | да | ID файла |
| path | string | да | Путь по папкам до файла внутри бакета |
| bucket | string | да | Бакет для хранения файла |
FileMeta
Метаинформация о файле
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| filename | string | да | Имя файла |
| checksum | string | да | Значение контрольной суммы |
| ownerUserId | UserId | нет | Идентификатор пользователя, у которого есть доступ к файлу. При отсутствии значения файл считается доступным всем |
FSMetadata
Метаинформация о файле, возвращаемая при запросах к файловому хранилищу.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| contentType | string | да | Тип содержимого файла |
| contentLength | Long | да | Длина содержимого файла в байтах |
| fileName | string | да | Имя файла |
| md5 | string | да | Контрольная сумма файла в формате MD5 |
| ownerUserId | UserId | нет | Идентификатор пользователя, у которого есть доступ к файлу. При отсутствии значения файл считается доступным всем |
FileMetadata
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| fileId | string | да | Идентификатор файла |
| name | string | да | Имя файла |
| size | long | да | Размер файла в байтах |
| url | string | да | url файла в S3 |
| md5 | string | да | MD5 хеш файла |
| contentType | string | да | Content-Type файла |
Indexation: сервис индексаций
В сервисе реализованы следующие команды
- Создание описания индексации
- Получение описания индексации по идентификатору
- Удаление описания индексации
- Обновление описания индексации
- Получение списка описаний индексаций
- Получение списка описаний индексаций по страницам
- Получение списка статусов шагов
- Перезапуск шага
- Запуск индексации
- Перезапуск индексации
- Принудительное завершение индексации
- Статистика по индексации
- Получение индексации
- Получение списка индексаций
Общее описание архитектуры сервиса индексаций
Сервис индексирует объекты из модели данных. Индексирование может изменять состояние объекта в сервисах верди, например обновлять объект в модели данных или делать объект доступным для полнотекстового поиска, возможно индексирование без изменения состояния - например наполнение индексов LAMP для последующего использования. Индексация определенного типа описывается как последовательность шагов Step. Шаги могут зависеть друг от друга. Зависимость может быть 2 типов: шаг Б использует результаты шага А для определенной сущности, шаг Б полагается на выполнение шага А для всех сущностей. Некоторые шаги (сейчас только Lamp) после выполнения работы над определенной сущностью возвращают словарь вида: имяполя->результатработы. Зависящие от них шаги, могут использовать эти результаты в свой работе. Если дочерний шаг должен дождаться завершения индексации всех сущностей на родительском шаге - то при описании дочернего шага нужно указывать флаг oneLevel = false.
Сервис индексаций содержит следующие таблицы:
- "indexation_description" Таблица с описанием индексации: тип целевой сущности и список шагов Step. Является основной таблицей.
- "indexation" Таблица со статусами процесса индексации (история запуска индексаций). Связана
с
indexation_descriptionчерез колонку "entity_type". - "indexation_row" Таблица со статусами отдельных шагов индексаций (история выполнения шагов). Связана
с
indexation_descriptionчерез колонку "entity_type", а сindexationчерез колонку "correlation_id".
Конфигурирование сервиса индексаций
Требования к запуску сервиса индексаций
Запуск сервиса осуществляется локально через sbt, на стенде в docker на jvm. Для корректной минимальной работы сервиса требуется обязательное подключение к PostgreSQL, Kafka, Consul, MinIO и Remote Lamp Client Для нормальной работы сервису дополнительно требуется окружение Verdi: CommandStatus и ApiGateway.
Список переменных окружения сервиса индексаций
| Переменная | Тип | Обязательная | Значение по умолчанию | Описание |
|---|---|---|---|---|
| SERVER_PORT | int | нет | 8080 | Порт, на котором слушает HTTP-сервер |
| SERVER_AUTHORIZER_KIND | string | нет | "authzforce" | Вид авторизатора, который используется в сервисе. Допустимые значения: "authzforce", "oberto". При указании неизвестного значения будет использовано значение по-умолчанию. |
| CONSUMER_TOPIC | string | нет | entityObjectEvents | Название кафка-топика для событий по объектам |
| CONSUMER_GROUP | string | нет | indexation | Имя группы-консьюмеров сервиса индексаций |
| FIXED_CONSUMER_GROUP | string | нет | indexationFixed | Имя группы-консьюмеров без перебалансировки |
| CONSUMER_STEP_TOPIC | string | нет | step | Название кафка-топика для шагов индексации |
| CONSUMER_PROGRESS_TOPIC | string | нет | progress | Название кафка-топика для прогресса по плагинам |
| CONSUMER_STEP_FINISH_TOPIC | string | нет | stepFinish | Название кафка-топика для отслеживания завершения выполнения всех шагов по определенной сущности. Топик должен иметь только 1 партицию. Топик для внутреннего использования |
| CONSUMER_INDEXATION_TOPIC | string | нет | indexationInner | Название кафка-топика для выполнения массовой индексации сущностей определенного типа. Топик должен иметь только 1 партицию |
| CONSUMER_INDEXATION_INTERRUPT_TOPIC | string | нет | indexationInterrupt | Название кафка-топика для принудительного прерывания индексации. Топик должен иметь только 1 партицию. Топик для внутреннего использования |
| CONSUMER_STEP_PARTITION_PARALLELISM | int | нет | 10 | Параллелизм чтения из step партиции. Значения > 1 нарушают at-most-once семантику, но значительно ускоряют массовую индексацию |
| CONSUMER_FILE_EVENTS_TOPIC | string | нет | fileEvents | Название кафка-топика для событий с файлами из dataModel |
| VERDI_CONSUL | url string | да | http://localhost:8500 | Адрес Consul |
| VERDI_CONSUL_AUTH_USER | string | нет | "" | Название учетной записи Сonsul. Если название не указано, то настройки авторизации не будут применены. |
| VERDI_CONSUL_AUTH_PASSWORD | string | нет | "" | Пароль учетной записи Сonsul. |
| VERDI_KAFKA_ADDRESS | string | да | localhost:9092 | Адрес брокера Kafka. |
| VERDI_KAFKA_TOPIC | string | нет | commandevents | Название кафка-топика для отправки сообщений со статусами выполняемых команд. ОБЯЗАТЕЛЬНО должно соответствовать названию этого топика в сервисе статуса команд. |
| VERDI_KAFKA_AUTH_USER | string | нет | "" | Название учетной записи Kafka. Если название не указано, то настройки авторизации не будут применены. |
| VERDI_KAFKA_AUTH_PASSWORD | string | нет | "" | Пароль учетной записи Kafka. |
| VERDI_KAFKA_AUTH_PRINCIPAL | string | нет | "" | Principal учетной записи Kafka в Kerberos(в случае соединения с kafka через Kerberos). |
| VERDI_KAFKA_AUTH_KEYTAB_PATH | string | нет | "" | Путь до keytab-файла(в случае соединения с kafka через Kerberos). |
| VERDI_KAFKA_AUTH_TRUSTSTORE_LOCATION | string | нет | "" | Путь до хранилища сертификатов (Java key store). Если путь не указан, то сертификат применяться не будет. |
| VERDI_KAFKA_AUTH_TRUSTSTORE_PASSWORD | string | нет | "" | Пароль к хранилищу сертификатов. |
| VERDI_KAFKA_AUTH_MODE | string | нет | "" | Режим аутентификации: static - одна учетная запись на все запросы, mapping - учетная запись зависит от запроса |
| VERDI_KAFKA_AUTH_CONFIG | string | нет | "" | Настройки для аутентификации: если AuthMode = mapping, то необходим JSON с List[KafkaAuthConfig]. Переменная соответствует полю authConfig из KafkaAuthSettings. |
| VERDI_KAFKA_AUTH_CACHE_SIZE | int | нет | Максимальный размер кеша для Kafka producer (количество активных соединений). | |
| VERDI_KAFKA_AUTH_CACHE_TTL | duration string | нет | Время жизни Kafka producer в кеше. | |
| VERDI_KAFKA_CONNECTION_CHECK_TEST_MESSAGES_INTERVAL | duration string | нет | 4 minutes | Применяется только для producer-ов со способом аутентификации kerberos. Интервал отправки тестовых сообщений кафки в топик connectionCheck.testMessagesTopicName. Тестовые сообщения (null, service producer test) отправляются регулярно с этим интервалом. |
| VERDI_KAFKA_CONNECTION_CHECK_INTERVAL | duration string | нет | 60 seconds | Применяется только для producer-ов со способом аутентификации kerberos. Интервал проверки того, сколько тестовых сообщений было отправлено за данный период. Если количество сообщений за этот период равно количеству сообщений за прошлый период, то начинается отсчет периода без сообщений. |
| VERDI_KAFKA_CONNECTION_CHECK_FAILED_AFTER_INTERVAL | duration string | нет | 5 minutes | Применяется только для producer-ов со способом аутентификации kerberos. Максимальная продолжительность периода без успешно отправленных тестовых сообщений. По ее достижении сервис будет объявлен больным. |
| VERDI_KAFKA_PRODUCER_PROPS | string | нет | "max.request.size=1048576" | Дополнительные параметры для Kafka producer. Заполняются по шаблону "key1=value1;key2=value2". |
| VERDI_HOST | string | да | localhost | Хост, публикуемый в ServiceDiscovery. По нему на данный сервис будут обращаться другие через HTTP. Указанный адрес должен быть виден другим сервисам. Пример: имя kubernetes/docker_swarm service |
| VERDI_TTL | duration string | нет | 30 seconds | Период после последней отправки health check, в течение которого ServiceDiscovery считает данный сервис живым. |
| VERDI_HEALTH_CHECK | duration string | нет | 10 seconds | Периодичность отправки health check в ServiceDiscovery |
| VERDI_COMMAND_STORAGE_UPDATE_PERIOD | duration string | нет | 1 minutes | Время кэширования данных по командам из CommandDiscovery |
| VERDI_SERVICE_DISCOVERY_UPDATE_PERIOD | duration string | нет | 30 seconds | Время кэширования данных по сервисам из ServiceDiscovery |
| VERDI_ALLOW_INTERNAL_COMMANDS | bool | нет | true | Можно ли сервису отправлять внутрисистемные команды |
| VERDI_CONSIDER_ALL_COMMANDS_AS_INTERNAL | boolean | Нет | false | Флаг, определяющий будут ли все обращения в другие сервисы являться внутренними (т.е. не требовать авторизацию). Детальное описание механизма: Внутренние команды. |
| VERDI_CONSUL_CONNECTION_MAX_RETRY | int | нет | 5 | Максимальное количество попыток подключений к Consul |
| VERDI_CONSUL_CONNECTION_RETRY_DELAY | duration string | нет | 1 seconds | Таймаут между неудачными попытками подключения к Consul |
| VERDI_KAFKA_SYNC_POLLING_PERIOD | duration string | нет | 1 seconds | Периодичность запроса статуса verdi команд в sender-lib |
| VERDI_KAFKA_SYNC_POLLING_TIMEOUT | duration string | нет | 10 seconds | Максимальное время ожидания выполнения verdi команды в sender-lib |
| DB_JDBC_URL | jdbc url string | да | jdbc:postgresql://127.0.0.1:5432/indexation | JDBC-url для соединения с БД |
| DB_USER | string | да | Пользователь БД | |
| DB_PASSWORD | string | да | Пароль пользователя БД | |
| DB_THREADS | int | нет | 10 | Количество потоков в пуле потоков для соединения с БД |
| DB_QUEUE_SIZE | int | нет | 300 | Размер очереди для действий базы данных, которые не могут быть выполнены немедленно, когда все потоки заняты. За пределами этого значения новые действия немедленно завершаются неудачей |
| DB_CONN_MAX | int | нет | 10 | Максимальное количество одновременных подключений к БД |
| DB_CONN_TIMEOUT | duration string | нет | 20 second | Максимальное время ожидания ответа для соединения к БД. Если это время превышено, а соединение не становится доступным, будет брошено исключение SQLException. 1000 мс — минимальное значение. |
| DB_ISOLATION | string | нет | "READ_COMMITTED" | Уровень изоляции транзакций для новых подключений. Допустимые значения: NONE, READ_COMMITTED, READ_UNCOMMITTED, REPEATABLE_READ, SERIALIZABLE. |
| DB_READONLY | boolean | нет | false | Read-only SQL транзакция может изменять только временные таблицы. Этот параметр управляет статусом «только для чтения» по умолчанию для каждой новой транзакции. |
| DB_CONN_MIN | int | нет | = DB_THREADS | Минимальное количество одновременных подключений к БД |
| DB_VALIDATION_TIMEOUT | duration string | нет | 1 seconds | Максимальное время, в течение которого соединение будет проверяться на работоспособность. 1000 мс — минимальное значение. |
| DB_IDLE_TIMEOUT | duration string | нет | 10 minutes | Максимальное время, в течение которого соединению разрешено простаивать в пуле. Значение 0 означает, что простаивающие соединения никогда не удаляются из пула. |
| DB_MAX_LIFETIME | duration string | нет | 30 minutes | Максимальное время жизни соединения в пуле. Когда простаивающее соединение достигает этого времени ожидания, даже если оно недавно использовалось, оно будет удалено из пула. Значение 0 указывает на отсутствие максимального срока службы. |
| DB_INITIALIZATION_FAIL_FAST | string | нет | false | Deprecated, начиная с версии Slick 3.3.0. Определяет, будет ли пул «быстро выходить из строя», если пул не может быть успешно заполнен начальными соединениями. Если соединения не могут быть созданы во время запуска пула, будет выдано исключение RuntimeException. Это свойство не имеет никакого эффекта, если minConnections равно 0. |
| DB_LEAK_DETECTION_THRESHOLD | int | нет | 0 | Время, в течение которого соединение может находиться вне пула, прежде чем будет зарегистрировано сообщение, указывающее на возможную утечку соединения. Значение 0 означает, что обнаружение утечек отключено. Наименьшее приемлемое значение для включения обнаружения утечек составляет 10 с. |
| DB_CONNECTION_TEST_QUERY | string | нет | "SELECT 1" | Выражение, которое будет выполнено непосредственно перед получением соединения из пула для проверки того, что соединение с базой данных все еще активно. Оно зависит от базы данных и должно представлять собой запрос, требующий минимальной обработки базой данных (например, «VALUES 1»). Если этот параметр не установлен, вместо него используется метод JDBC4 Connection.isValid(). |
| DB_REGISTER_MBEANS | boolean | нет | false | Зарегистрированы ли JMX Management Beans («MBeans») |
| DB_AUTO_COMMIT | boolean | нет | true | Это свойство определяет то, как будут вести себя по умолчанию возвращаемые соединения относительно autocommit-а. |
| DB_SCHEMA | string | нет | "public" | Устанавливает schema по умолчанию |
| DB_ISOLATE_INTERNAL_QUERIES | boolean | нет | false | Определяет то, изолируются ли с помощью транзакций внутренние запросы пула(например запрос connection alive test). Свойство применяется только если autoCommit выключен. |
| DB_INITIALIZATION_FAIL_TIMEOUT | int | нет | 1 | Работает, начиная с версии Slick 3.3.0. Определяет, будет ли пул «быстро выходить из строя», если пул не может быть успешно заполнен начальными соединениями. Любое положительное число считается числом миллисекунд для попытки получить начальное соединение;поток приложения будет заблокирован в течение этого периода. Если соединение не может быть получено до истечения этого времени,будет брошено исключение. Данный таймаут применяется после периода connectionTimeout. Если значение равно нулю (0),HikariCP попытается получить и проверить подключение. Если соединение получено,но проверка не пройдена, будет брошено исключение, и пул не будет запущен. Однако,если соединение не может быть получено, пул запустится,но последующие попытки получить соединение могут потерпеть неудачу.Значение меньше нуля пройдет любую первоначальную попытку подключения, и пул немедленно запустится,пытаясь получить соединения в фоновом режиме.Следовательно, последующие попытки получить соединение могут потерпеть неудачу. |
| FS_URI | url string | да | http://localhost:9002 | Адрес S3 файлового хранилища minio |
| FS_ACCESS_KEY_ID | string | да | admin | Идентификатор доступа к minio |
| FS_SECRET_ACCESS_KEY | string | да | admin | Секретный ключ доступа к minio |
| FS_UPLOAD_PARALLELISM | int | нет | 10 | Параллелизм загрузки файлов в minio |
| FS_AUTH_MODE | string | нет | static | Режим аутентификации: static - одна учетная запись на все запросы, mapping - учетная запись зависит от запроса |
| FS_AUTH_CONFIG | string | нет | "" | Настройки для аутентификации: если AuthMode = mapping, то необходим JSON с List[FSBucketConfig] соответствует полю authConfig FSConfigRep |
| FS_CACHE_SIZE | int | нет | 1 | Максимальный размер кеша клиентов для хранилища файлов (количество активных соединений). |
| FS_CACHE_TTL | duration string | нет | Время жизни клиента в кеше | |
| FS_RETRY_ATTEMPTS | int | нет | 5 | Количество ретраев, которое будет произведено в случае Exception-а в операции FSClient-а и при вычитывании стрима в get операциях FSClient-а. |
| FS_RETRY_DELAY | duration string | нет | 10 millis | Задержка между ретраями операций FSClient-а. |
| FS_ZIO_SHORT_MESSAGE_MODE | boolean | нет | false | Флаг включения режима сохранения ошибок работы с файловым хранилищем в сервисе журналирования nestor. При включении режима ошибки в логах будут отображаться в сокращенном формате: Short zio message mode. ExceptionType: ТИП ОШИБКИ, Exception id: 'СГЕНЕРИРОВАННЫЙ UUID' added to journal. Указанный id будет фиксироваться в event записи nestor'а в поле data.id |
| LAMP_ENABLE | bool | нет | true | Пытаться ли подключиться к lamp(true) или не устанавливать соединение с lamp(false) |
| LAMP_USE_VERSION_2 | bool | нет | false | Использовать ли LAMP2 (true) или LAMP1 (false). Аналогичная переменная есть и в сервисах плагинов индексации |
| LAMP_BUFFER_SIZE | int | нет | 10 | Буфер на отправку сообщений в клиент LAMP |
| LAMP_RECONNECT_SCHEDULE | schedule string | нет | I(2 seconds) | Стратегия переподключения клиента LAMP (формат см. lamp.transport.model.Schedule) |
| LAMP_HOST | url string | нет | lamp-dev.dev.embedika.ru | Адрес клиента LAMP(должен быть непустым, если LAMP_ENABLE=true) |
| LAMP_PORT | int | нет | 443 | Порт клиента LAMP(должен быть непустым, если LAMP_ENABLE=true) |
| LAMP_TLS | bool | нет | true | Признак защищенного подключения к LAMP |
| LAMP_TLS_CERTIFICATE | string | нет | "" | Путь файла с сертификатом для подключения к LAMP |
| LAMP_TLS_PRIVATE_KEY | string | нет | "" | Путь файла с приватным ключем для подключения к LAMP |
| LAMP_TLS_ROOT_TRUSTED_CERTS | string | нет | "" | Путь файла с центром сертификации (Certification Authority, CA) для подключения к LAMP |
| LAMP_TIMEOUT | duration string | нет | 1 minute | Таймаут отправки сообщения и получения результатов через клиент LAMP |
| LAMP_MAX_MESSAGE_SIZE | int | нет | 524288000 | Максимальный допустимый размер сообщений в LAMP |
| LAMP_QUERY_PARALLELISM | int | нет | 10 | Параллелизм обработки в LAMP файлов одного объекта |
| APP_FILE_BUCKET | string | нет | document | S3 bucket, в котором следует искать файлы объектов |
| APP_ROUTE_MAPPING | string | нет | Extraction:extraction_route;Keyword:cursor_v0.1_keyword;Plagiarism:cursor_v0.1_plagiarism;Similarity:cursor_v0.1_similarity | Маппинг сервисных имен LAMP роутов с реальными LAMP роутами. Формат indexation1:route1;indexation2:route2. Список сервисные роуты см. LampRoute |
| APP_CLEAN_ROUTE_MAPPING | string | нет | Plagiarism:cursor_v0.1_plagiarism_clean;Similarity:cursor_v0.1_similarity_clean | Маппинг имен LAMP индексаций с LAMP роутами для удаления документов |
| APP_COMMAND_COMPLETION_TIMEOUT | duration string | нет | 20 seconds | Максимальное время ожидания команд после выполнения шага индексации |
| APP_COMMAND_PROCESSING_PARALLELISM | int | нет | 5 | Параллелизм обработки событий verdi |
| APP_MAX_STEP_ATTEMPTS | int | нет | 10 | Максимальное кол-во попыток выполнения шага индексации |
| APP_ASYNC_COMMAND_POLL_INTERVAL | duration string | нет | 1 second | Периодичность запроса статуса verdi команд |
| APP_ASYNC_COMMAND_TIMEOUT | duration string | нет | 10 seconds | Максимальное время ожидания выполнения verdi команды |
| APP_INDEXATION_DATA_BATCH | int | нет | 100 | Размер данных, получаемых за 1 раз из сервиса МД для индексации. С увеличением параметра увеличится время ожидания для принудительного прерывания, с уменьшением - увеличится нагрузка на МД |
| APP_INDEXATION_ENTITY_TIMEOUT | duration string | нет | 5 minutes | Время ожидания завершения всех шагов по сущности TODO Возможно стоит скалировать это время пропорционально кол-ву шагов, ведь оно может быть сильно разным |
| APP_INDEXATION_PARALLELISM | int | нет | 4 | Параллелизм массового индексирования |
| APP_VERDI_PARALLELISM | int | нет | 4 | Размер пула потоков для sender-lib |
| APP_VERDI_MAX_RETRY | int | нет | 10 | Максимальное число ретраев для verdi команд |
| APP_VERDI_RETRY_DELAY | duration string | нет | 5 seconds | Таймаут между неудачными вызовами verdi команд |
| APP_DEFAULT_WHITE_LISTS | string | нет | Erika:doc,docx;PDFView:pdf | Дефолтные фильтры файлов по расширениям |
| APP_FILE_PARALLELISM | int | нет | 10 | Лимит на одновременное число запросов к minio |
| PDF_VIEW_HOST | string | нет | http://localhost:3333 | Адрес сервиса для извлечения json из pdf |
| PDF_VIEW_TIMEOUT | duration string | нет | 5 minutes | Таймаут для запроса в сервис извлечения json из pdf |
| PDF_VIEW_ADDITIONAL_FIELD_NAME | string | нет | pdfJson | Ключ, под которым сохраняются результаты извлечения json из pdf |
| PDF_VIEW_EXTRACT_PART_NAME | string | нет | file | Ключ, под которым нужно передавать pdf для извлечения json |
| INDEXATION_AUTHZFORCE_ADDR | url string | нет | http://localhost:8080/authzforce-ce | Адрес сервиса authzforce |
| INDEXATION_AUTHZFORCE_DOMAIN | string | нет | "" | Доступный DomainID в Authzforce server |
| INDEXATION_AUTHZFORCE_CONNECT_TIMEOUT | duration string | нет | 5 seconds | Максимальное время ожидания ответа от Authzforce |
| INDEXATION_READABLE_NAME | string | нет | "Сервис индексаций" | Читаемое название этого сервиса |
| INDEXATION_DESCRIPTION | string | нет | "Предназначен для индексации" | Читаемое описание этого сервиса |
| VERDI_COMMANDS_HTTP_RETRY_ATTEMPTS | int | нет | 5 | Поле attempts из RetrySettings |
| VERDI_COMMANDS_HTTP_RETRY_DELAY | duration string | нет | "5 seconds" | Поле delay из RetrySettings |
| VERDI_COMMANDS_HTTP_RETRY_KIND | string | нет | "OnSomeExceptions(ConnectException)" | CommandResultRetryConditionKind |
| APP_JOURNAL_REQUIRED_STEPS | string | нет | "Erika,FullTextSearch,FullTextCompletion,Lamp,PDFView,Keyword" | Строка с перечислением типов шагов через запятую, которые обязательно должны завершиться успешно для объекта, чтобы при журналировании завершения индексации этот объект попал в число успешно обработанных. При этом если ошибка возникнет в шаге, который не входит в этот список, обработка объекта все равно будет зажурналирована как успешная. Не влияет на команду indexationStatistics |
| INDEXATION_JOURNAL_MODE | string | нет | WriteToJournal |
Режим журналирования Nestor. Допустимые значения: WriteToJournal (Отправка в сервис журналирования), WriteToTopic (Отправка события в очередь) |
| INDEXATION_JOURNAL_TOPIC | string | да, если переменная INDEXATION_JOURNAL_MODE = WriteToTopic |
"" | Название очереди журналирования. Для режима WriteToJournal значение игнорируется. |
Команды для сервиса индексации
Список реализованных в сервисе команд, моделей EntityType и действий Actions, которые можно использовать при настройке авторизации.
| Название команды | EntityType | Actions |
|---|---|---|
| createIndexationDescription | indexationDescription | indexation_indexationDescription_CreateIndexationDescription |
| getIndexationDescription | indexationDescription | indexation_indexationDescription_GetIndexationDescription |
| deleteIndexationDescription | indexationDescription | indexation_indexationDescription_DeleteIndexationDescription |
| updateIndexationDescription | indexationDescription | indexation_indexationDescription_UpdateIndexationDescription |
| listIndexationDescription | indexationDescription | indexation_indexationDescription_ListIndexationDescription |
| listIndexationDescriptionPages | indexationDescription | indexation_indexationDescription_ListIndexationDescriptionPages |
| indexationRowsList | row | indexation_row_row |
| indexationRestartStep | row | indexation_row_row |
| startIndexation | indexation | indexation_indexation_StartIndexation |
| fixIndexation | indexation | indexation_indexation_FixIndexation |
| indexationStatistics | indexation | indexation_indexation_IndexationStatistics |
| getIndexation | indexation | indexation_indexation_GetIndexation |
| getIndexations | indexation | indexation_indexation_GetIndexations |
Команды сервиса индексаций
createIndexationDescription
Создание описания индексации.
Указываемый id должен совпадать с entityType индексируемой сущности в сервисе Модели данных.
На входе описание индексации
{
"id": "NewEntityType",
"steps": [
{
"children": [],
"payload": {
"type": "Erika",
"fields": [
"files"
]
},
"extensionFilter": {
"type": "WhiteList",
"allowed": [
"docx"
]
}
}
]
}
В результате возвращается идентификатор описания
Поддерживается только синхронный вызов.
Результат выполнения команды журналируется.
- На входе: IndexationDescriptionDTO
- На выходе: String
getIndexationDescription
Получение описания индексации по идентификатору (по сути по типу объекта)
На входе идентификатор описания
"Document"
В результате описание индексации
{
"id": "NewEntityType",
"steps": [
{
"children": [],
"payload": {
"fields": [
"files"
],
"type": "Erika"
},
"extensionFilter": {
"type": "WhiteList",
"allowed": [
"docx"
],
"default": false
}
}
],
"version": 1
}
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: String
- На выходе: IndexationDescription
deleteIndexationDescription
Удаление описания индексации и истории запусков данной индексации.
На входе идентификатор описания
"Document"
В результате количество удаленных записей
Поддерживается только синхронный вызов.
Результат выполнения команды журналируется.
- На входе: String
- На выходе: Integer
updateIndexationDescription
Обновление описания индексации
На входе описание индексации
{
"id": "NewEntityType",
"steps": [
{
"children": [],
"payload": {
"fields": [
"files"
],
"type": "Erika"
}
},
{
"children": [],
"payload": {
"filesRoutes": [
{
"field": "files",
"actions": [
{
"lampRoute": "Plagiarism"
}
]
}
],
"type": "Lamp"
}
}
],
"version": 1
}
В результате количество обновленных записей
Поддерживается только синхронный вызов.
Результат выполнения команды журналируется.
- На входе: IndexationDescription
- На выходе: Integer
listIndexationDescription
Получение списка описаний индексаций
Входных данных нет
В результате список описаний индексаций
[
{
"id": "Document",
"steps": [
{
"children": [
{
"step": {
"fields": [
"documentFileContent"
],
"type": "FullTextSearch"
},
"oneLevel": false
}
],
"payload": {
"filesRoutes": [
{
"field": "documentFile",
"saveContentTo": "documentFileContent",
"actions": [
{
"lampRoute": "Extraction"
}
]
}
],
"type": "Lamp"
},
"extensionFilter": null
},
{
"children": [],
"payload": {
"fields": [
"documentFile"
],
"type": "Erika"
},
"extensionFilter": null
}
],
"version": 1
},
{
"id": "agreement",
"steps": [
{
"children": [],
"payload": {
"filesRoutes": {
"field": "files",
"actions": [
{
"lampRoute": "Plagiarism"
}
]
},
"type": "Lamp"
},
"extensionFilter": null
}
],
"version": 1
}
]
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Команда не принимает параметров
- На выходе: List[IndexationDescription]
listIndexationDescriptionPages
Получение списка описаний индексаций с поддержкой пагинации.
Имя вызова команды: listIndexationDescriptionPages.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: Search
- На выходе: Page[IndexationDescription]
{
"query": "",
"paging": {
"page": 2,
"count": 2
},
"context": {}
}
На выходе список описаний индексаций обернутый в Page
{
"items": [
{
"id": "NewEntityType",
"steps": [
{
"children": [],
"payload": {
"fields": [
"files"
],
"type": "Erika"
}
}
],
"whiteList": [
"docx"
],
"version": 1
},
{
"id": "NewEntityType1",
"steps": [
{
"children": [],
"payload": {
"fields": [
"files"
],
"type": "Erika"
}
}
],
"whiteList": [
"docx"
],
"version": 1
}
],
"total": 5
}
indexationRowsList
Получение списка результатов выполнения шагов.
Имя вызова команды: indexationRowsList.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: Search
- На выходе: Page[IndexationRow]
По умолчанию сортировка производится по полю created.
На входе поисковый запрос
{
"query": "entityId",
"context": {
"entityId": "d81eed64-3449-4bf1-a668-13f69cbaefc4"
},
"paging": {
"page": 1,
"count": 2
},
"sorting": {
"fieldName": "created",
"order": "asc"
}
}
Запрос принимает параметры сортировки, фильтров и пейджинга в параметре Search.
Применяется к полям модели IndexationRow.
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров | Комментарии |
|---|---|---|
| entityId | InSetQuery | Фильтрация по объекту. UUID-ы, разделенные запятыми |
| status | InSetQuery | Фильтрация по статусу шага. |
| entityType | InSetQuery | Фильтрация по типу объекта. Строки, разделенные запятыми |
| correlationId | InSetQuery | Фильтрация по тэгу. Например чтобы получить все шаги определенной индексации. |
| stepType | InSetQuery | Фильтрация по типу шага. Строки, разделенные запятыми |
Команда вне зависимости от входных данных никогда не возвращает результаты выполнения шагов со статусом Ignored.
Доступные поля для сортировки:
| Поле |
|---|
| created |
По умолчанию сортировка производится по полю created.
В результате список статусов шагов с пагинацией
{
"items": [
{
"id": "be54b09d-c655-41f6-a87e-1c5b1ed021cd",
"entityId": "d81eed64-3449-4bf1-a668-13f69cbaefc4",
"entityType": "Document",
"status": "Success",
"eventType": "Create",
"created": "1629964032194",
"step": {
"children": [],
"payload": {
"fields": [
"files"
],
"type": "Erika"
},
"extensionFilter": {
"type": "WhiteList",
"allowed": [
"docx",
"doc"
],
"default": true
}
},
"message": null,
"stackTrace": null,
"additional": {
"skipped": {
"fileId": "be54b09d-c655-41f6-a87e-1c5b1ed021cd",
"additional": null,
"name": "file.txt",
"url": "temp/be54b09d-c655-41f6-a87e-1c5b1ed021cd"
}
}
},
{
"id": "a4be56be-b5f0-4ff7-8a8e-a514a68b546e",
"entityId": "d81eed64-3449-4bf1-a668-13f69cbaefc4",
"entityType": "Document",
"status": "Error",
"eventType": "Create",
"created": "1629964032194",
"step": {
"children": [],
"payload": {
"fields": [
"files"
],
"type": "Erika"
},
"extensionFilter": null
},
"message": "CommandService timeout",
"stackTrace": null,
"additional": null
}
],
"total": 3
}
indexationRestartStep
Перезапуск шага
На входе идентификатор статуса шага
"be54b09d-c655-41f6-a87e-1c5b1ed021cd"
В результате признак успешного перезапуска
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: String
- На выходе: Boolean
startIndexation
Запуск индексации всех сущностей определенного типа
На вход тип сущности
"RfbrDocument"
В результате идентификатор индексации
"be54b09d-c655-41f6-a87e-1c5b1ed021cd"
Поддерживает только синхронный вызов.
Результат выполнения команды журналируется.
- На входе: String
- На выходе: UUID
fixIndexation
Перезапуск индексации. Будут заново проиндексированы объекты, у которых имеется хотя-бы 1 провалившийся шаг по данной индексации, а так же будут проиндексированы новые, не индексировавшиеся до этого объекты
На вход идентификатор завершившейся индексации
"be54b09d-c655-41f6-a87e-1c5b1ed021cd"
Поддерживает только синхронный вызов.
Результат выполнения команды журналируется.
- На входе: String
- Команда возвращает пустую строку
interruptIndexation
Прерывание индексации. Индексация будет прервана только после завершения индексации текущей страницы данных (см. параметр INDEXATION_DATA_BATCH)
На вход идентификатор индексации
"be54b09d-c655-41f6-a87e-1c5b1ed021cd"
Поддерживает только асинхронный вызов.
Результат выполнения команды журналируется.
- На входе: UUID
- Команда не возвращает данных
indexationStatistics command
Получение статистики по индексации
На вход идентификатор индексации
"be54b09d-c655-41f6-a87e-1c5b1ed021cd"
В результате полная статистика о прохождении индексации
{
"completed": [
"be54b09d-c655-41f6-a87e-1c5b1ed021cd",
"d81eed64-3449-4bf1-a668-13f69cbaefc4"
],
"typesErrors": {
"Erika": 3
},
"entitiesErrors": {
"372c7c3d-21dd-4568-8cf7-6c31b36b771d": [
"Erika"
]
},
"status": "Done"
}
Поддерживает только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: UUID
- На выходе: IndexationStatistics
getIndexation
Получение индексации
На вход идентификатор индексации
"282484ae-3c53-4176-af0b-dba62e50e606"
В результате модель индексации
{
"id": "282484ae-3c53-4176-af0b-dba62e50e606",
"entityType": "RfbrDocument",
"status": "InProgress",
"created": "2022-02-04T12:37:28.997818",
"updated": "2022-02-04T12:37:28.997818",
"description": {
"id": "RfbrDocument",
"steps": [
{
"children": [],
"payload": {
"filesRoutes": [
{
"field": "file",
"saveContentTo": "fileContent",
"actions": []
}
],
"type": "Lamp"
},
"extensionFilter": null
}
],
"version": 1
}
}
Поддерживает только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: UUID
- На выходе: Indexation
getIndexations
Получение списка индексаций
Входных данных нет
В результате список индексаций
[
{
"id": "245d6b04-40aa-4139-8c4d-a25ae2f57a55",
"entityType": "RfbrDocument",
"status": "InProgress",
"created": "2022-01-31T14:49:06.834771",
"updated": "2022-01-31T14:49:06.834771",
"description": {
"id": "RfbrDocument",
"steps": [
{
"children": [],
"payload": {
"filesRoutes": [
{
"field": "file",
"saveContentTo": "fileContent",
"actions": []
}
],
"type": "Lamp"
},
"extensionFilter": null
}
],
"version": 1
}
},
{
"id": "5436a8e7-1ba2-40ca-93cd-96e318d76b3d",
"entityType": "RfbrDocument",
"status": "Interrupted",
"created": "2022-01-31T14:52:12.495104",
"updated": "2022-01-31T14:53:08.142893",
"description": {
"id": "RfbrDocument",
"steps": [
{
"children": [],
"payload": {
"filesRoutes": [
{
"field": "file",
"saveContentTo": "fileContent",
"actions": []
}
],
"type": "Lamp"
},
"extensionFilter": null
}
],
"version": 1
}
}
]
Поддерживает только синхронный вызов.
Результат выполнения команды не журналируется.
- Команда не принимает параметров
- На выходе: Seq[Indexation]
Модели сервиса индексаций
IndexationDescription
Описание индексации определенного типа объекта
| Название поля | Тип | Описание |
|---|---|---|
| id | String | Идентификатор описания, соответствует типу объекта |
| steps | Seq[Step] | Шаги индексации |
| version | Int | Версия описания. Используется для optimistic lock |
IndexationDescriptionDTO
Создание описания индексации определенного типа объекта
| Название поля | Тип | Описание |
|---|---|---|
| id | String | Идентификатор описания, соответствует типу объекта |
| steps | Seq[Step] | Шаги индексации |
Шаги индексации
Отдельный элемент индексации, описывающий взаимодействие с сервисами интеллектуализации, конвертации или полнотекстового поиска
ExtensionFilter
Фильтр файлов по расширениям для шагов
AllowedAll
Разрешены любые расширения
WhiteList
| Название поля | Тип | Описание |
|---|---|---|
| allowed | Seq[String] | Допустимые расширения |
| default | boolean | Флаг для дефолтных настроек |
StepChild
Описание дочернего шага
| Название поля | Тип | Описание |
|---|---|---|
| step | Step | Описание шага |
| oneLevel | boolean | Располагается ли дочерний шаг на одном уровне с родительским шагом |
Step
Описание шага. Шаг после своего выполнения может вернуть результаты в виде ключ:ссылканафайлсрезультатами. Эти результаты можно использовать в дочерних шагах. Шаг может фиксировать свои результаты в дополнительных полях файлов через сервис модели данных
| Название поля | Тип | Описание |
|---|---|---|
| children | Seq[StepChild] | Зависящие шаги |
| payload | StepPayload | Описание самого шага |
| extensionFilter | Option[ExtensionFilter] | Опциональный фильтр файлов по расширениям |
| label | String | Опциональный лейбл шага, может быть полезен при отладке |
StepPayload
Тип-сумма для описания шагов индексации. При десериализации нужно дополнительное поле type, где указывается имя типа-произведения. Аналогичное поле будет при сериализации.
Lamp (indexation)
Индексация в сервисах LAMP всех объектов индексируемой сущности. Часть типов-произведений StepPayload. Может иметь дочернии шаги. Может фиксировать отдельные результаты в сервисе модели данных.
Этот шаг для каждого объекта индексируемой сущности и каждого i-го элемента массива fileRoutes
извлекает из поля filesRoutes[i].field информацию о файле, с помощью этой информации достает файл из s3,
и отправляет запросы с содержимым этого файла к рутам Lamp, которые соответствуют переданным
fileRoutes.actions.lampRoute в маппинге APP_ROUTE_MAPPING.
Если эти запросы будут обращаться к сервисам Lamp из LAMP_CACHEABLE_SERVICES,
то результаты обработки файлов этими сервисами будут добавлены в кэш Lamp-а по id
Имя_Сущности_DM;Id_объекта_DM;Имя_поля_с_файлом;ID_файла.
Для сервиса extraction таким результатом будет само содержимое файла. Для каждого внутреннего сервиса Lamp
поддерживается свой отдельный кэш.
Краткая справка про Lamp:
Lamp состоит внутри себя из нескольких сервисов, которые по-разному обрабатывают входящие файлы.
К каким конкретно сервисам внутри себя обратится Lamp при вызове определенного рута можно посмотреть в переменной
ROUTER_ROUTES сервиса router20.
| Название поля | Тип | Описание |
|---|---|---|
| filesRoutes | Seq[FileRoutes] | Индексация отдельных файловых полей сущности |
FullTextSearch
Индексация в сервисе полнотекстового поиска. Часть типов-произведений StepPayload
| Название поля | Тип | Описание |
|---|---|---|
| fields | Seq[String] | Поля, значение которых нужно сохранить в поисковом индексе |
FullTextCompletion
Индексация автодополнений в сервисе полнотекстового поиска. Содержит список названий полей, которые сохраняются в индексе. Среди полей могут быть поля из исходного объекта модели данных, или же полученные с помощью Lamp через сервис ключевых слов. В таком случае нужно передать поле с результатом соответствующего шага. Часть типов-произведений StepPayload
| Название поля | Тип | Описание |
|---|---|---|
| fields | Seq[String] | Поля, значение которых нужно сохранить в индексе для автодополнений |
| saveKeywordsToDM | Option[String] | Поле в модели данных, внутри additionalData, в которое нужно сохранить ключевые слова, выделенные из файлов |
Erika
Индексация, конвертирующая файлы объекта в pdf-представление. Обновляет состояние в сервисе МД. Часть типов-произведений StepPayload. Может иметь дочернии шаги. Сохраняет результаты в сервисе модели данных в дополнительных полях файлов под ключем pdf
| Название поля | Тип | Описание |
|---|---|---|
| fields | Seq[String] | Список полей для конвертации. |
Plugin
Пример описания действия Plagiarism в шаге Lamp
{
"lampRoute": "Plagiarism",
"routeResult": null
}
Пример описания действия Similarity в шаге Lamp
{
"lampRoute": "Similarity",
"routeResult": null
}
Индексация в плагинах интеллектуализации. Часть типов-произведений StepPayload.
В поле topic указывается кафка-топик, по которому произойдет связь с конкретным плагином.
Является единственным типом шагов, которые не игнорируются в индексациях, вызванных событиями удаления entityObject. Подробнее это поведение описано здесь.
Доступные на данный момент плагины:
- plagiarismPlugin - построение ссылок между объектами на основе содержательных пересечений,
- similarityPlugin - построение ссылок между объектами близкими по смыслу,
- taggingPlugin - назначение тэгов файлам на основе их расширения.
Для plagiarismPlugin и similarityPlugin шаг должен быть запущен после обработки всех передаваемых fields
с помощью шага Lamp (в шаге Lamp обрабатываемое поле указывается в filesRoutes.field).
В шаге Lamp в filesRoutes.actions должны присутствовать действия Plagiarism и Similarity
соответственно.
| Название поля | Тип | Описание |
|---|---|---|
| topic | String | Кафка топик целевого плагина |
| fields | Seq[String] | Список файловых полей для индексации |
| needBacklinks | Boolean | Определяет, нужно ли запускать переиндексацию связанных объектов, если файлы этих объектов не найдены в кэше lamp (используется только для lamp2) |
| parameters | Json | Произвольные параметры, определяющие специфичные настройки индексации для обработки плагином. Плагины plagiarism, similarity и tagging не учитывют данные параметры. |
PDFView
Индексация для предварительного рендеринга pdf. Часть типов-произведений StepPayload. Сохраняет результаты в сервисе модели данных в дополнительных полях файлов под ключом из настройки PDF_VIEW_ADDITIONAL_FIELD_NAME
| Название поля | Тип | Описание |
|---|---|---|
| fields | Seq[String] | Список файловых полей для индексации |
Keyword
Пример описания действия Keyword в шаге Lamp
{
"lampRoute": "Keyword",
"routeResult": {
"resultName": "fileKeywords",
"saveToDM": false
}
}
Пример описания шага индексации Keyword
{
"children": [],
"payload": {
"fields": [
"fileKeywords"
],
"type": "Keyword"
},
"extensionFilter": null,
"label": ""
}
Шаг индексации, осуществляющий заполнение реестра ключевых слов и установку связей ключей и объектов на основе ключевых слов, полученных в шаге Lamp. Часть типов-произведений StepPayload.
- Считывает из entityObject-ов, обрабатываемых индексацией, содержимое полей, идентификаторы которых указаны в
fields. - Конвертирует полученное содержимое во входные данные команды updateKeywords.
- Асинхронно вызывает команду updateKeywords и успешно завершает свое выполнение, если асинхронный
вызов
updateKeywordsвозвращаетcommandId. Иначе падает с ошибкой.
Шаг должен быть запущен после обработки нужных файловых полей сущности
с помощью шага Lamp. В шаге Lamp в filesRoutes.actions должно присутствовать действие Keyword с
указанным routeResult.resultName.
Указанный в шаге Lamp routeResult.resultName затем должен быть передан в шаге Keywords в fields.
| Название поля | Тип | Обязательное | Значение по умолчанию | Описание | Ограничения |
|---|---|---|---|---|---|
| fields | Seq[FieldId] | Да | Нет | Поля, из которых происходит выгрузка ключей, полученных Lamp, для формирования входного потока команды UpdateKeywords | Все поля, указанные в fields должны быть полями, сгенерированными на предыдущих шагах индексации. |
FileRoutes
Индексация в сервисах LAMP отдельно взятого файлового поля сущности. Модель формирует ключи для сохранения результатов работы шага Lamp из saveContentTo и actions.
| Поле | Тип | Описание |
|---|---|---|
| field | String | Имя поля, где хранится файл, для которого будет запущена индексация |
| saveContentTo | Option[String] | Опциональный ключ для сохранения результата работы extraction в data-model в поле data.[значение field].additional.[значение saveContentTo] |
| actions | Seq[FileRoute] | Список конкретных индексаций в LAMP |
| fieldSearch | Search | Фильтр связанной сущности, подробнее в подразделе про Lamp и длинные пути |
FileRoute
Конкретная индексация в LAMP
| Название поля | Тип | Описание |
|---|---|---|
| lampRoute | LampRoute | Lamp роут |
| routeResult | Option[RouteResult] | Опциональная обработка результатов от LAMP |
RouteResult
Обработка результатов от LAMP
| Название поля | Тип | Описание |
|---|---|---|
| resultName | String | Ключ для результата, по которому следующие шаги могу получить этот результат |
| saveToDM | Boolean | Флаг, указывающий нужно ли сохранить результат в сервис модели данных. По умолчанию false |
LampRoute (indexation)
Имена сервисных LAMP роутов. Доступные на данный момент роуты: Extraction, Keyword, Plagiarism, Similarity, ExtractionPdfium
EventType
Типы событий объектов, которые принимает сервис индексаций: Create, Delete, Update, Reindex, IndexPlagiarismPluginBacklinks, IndexSimilarityPluginBacklinks
IndexationRow
Статус шага индексации
| Название поля | Тип | Описание |
|---|---|---|
| id | UUID | Идентификатор шага |
| entityId | UUID | Идентификатор объекта, который индексируется этим шагом |
| entityType | String | Тип объекта, который индексируется этим шагом |
| status | IndexationRowStatus | Статус шага |
| created | LocalDateTime | Дата создания статуса шага |
| step | Step | Шаг индексации |
| correlation_id | String | Тэг. Используется, в частности, для объединения статусов по одной индексации |
| level | Int | Уровень обработки индексации, который вызвал этот шаг |
| message | Option[String] | Опциональный текст ошибки выполнения шага |
| stackTrace | Option[String] | Опциональное подробное описание ошибки выполнения шага |
| additional | Option[Json] | Опицональная дополнительная информация о шаге |
| initial_event | Option[EventType] | Тип события, который вызвал индексацию, содержащую этот шаг |
IndexationRowStatus
Типы статусов шагов индексации: Success(успешная обработка шага), Error(ошибка обработки шага), Ignored(проигнорирован).
Подробнее это поведение описано здесь.
Page
Страница списка элементов (часть списка с примененным пейджингом) типа T
| Название поля | Тип | Описание |
|---|---|---|
| items | Seq[T] | Список элементов на запрошенной странице |
| total | Long | Общее количество объектов |
IndexationStatistics
Статистика результатов индексации
| Название поля | Тип | Описание |
|---|---|---|
| completed | Seq[UUID] | Список сущностей, по которым все шаги были успешно выполнены |
| typesErrors | Map[String, Int] | Сводная информация об ошибках, в формате "Тип шага:кол-во провалившихся шагов" |
| entitiesErrors | Map[UUID, Seq[String]] | Сводная информация об ошибках, в формате "идентификатор сущности:типы провалившихся шагов" |
| status | IndexationStatus | Статус индексации |
IndexationStatus
Типы статусов индексации: InProgress, Done, Interrupted
Indexation
Индексация определенного типа сущностей
| Название поля | Тип | Описание |
|---|---|---|
| id | UUID | Идентификатор, по которому можно получить модель, статистику, и сделаные шаги |
| entityType | String | Тип сущности |
| status | IndexationStatus | Статус индексации |
| created | LocalDateTime | Дата создания |
| updated | LocalDateTime | Дата обновления |
| description | IndexationDescription | Зафиксированное на момент запуска описание индексации |
Особенности журналирования сервиса индексации
При журналировании окончания и прерывания индексаций, которые содержат шаги с типом Plugin, шаги с типом Plugin не учитываются при подсчете количества успешно или неуспешно обработанных объектов. Успешными при этом считаются шаги со статусом IndexationRowStatus Success и Ignored.
Delete entityObject indexations
Если индексация была начата из-за события с eventType равным delete, то она осуществляется по особым правилам.
Все шаги этой индексации, которые не являются плагинами, не запускаются и записываются в таблицу indexation_row со статусом Ignored. Однако дети проигнорированных шагов продолжают выполняться.
Если индексация дойдет до шагов-плагинов, то они будут запущены и выполнены исходя из своей логики и после этого могут иметь статусы Ignored, Error и Success.
Шаги со статусом Ignored не возвращаются в команде indexationRowsList даже если запросить их в search.
Lamp и длинный путь к relation полям (indexation)
Пример использования длинного пути до поля с файлом с использованием фильтра
{
"filesRoutes": [
{
"field": "children/file",
"saveContentTo": "fileContent",
"actions": [],
"fieldSearch": {
"query": "name",
"context": {
"name": "fileName.txt"
}
}
}
],
"type": "Lamp"
}
В индексации Lamp в поле field есть возможность указывать длинный путь до поля с файлами через relation.
В качестве разделителя полей в пути должен использоваться символ /.
Пример:
Создана сущность Folder(name: String) с Relation-полем children
Она связана с другой сущностью File(name: String, file: StoredFile), которое имеет поле с файлом.
В этом случае, путь до файла можно указать следующим образом: children/file.
Глубина пути не ограничена. Если отношение имеет тип one-to-many или many-to-many,
то будут включены все связанные файлы.
Также можно указать фильтр связанной сущности в поле fieldSearch.
Этот фильтр будет применен к конечной сущности в цепочке, а не к исходной.
Для иллюстрации предположим, что в предыдущем примере relation между "Folder" и "File" имеет тип one-to-many и
мы хотим отфильтровать файлы по полю "name". В таком случае, указанный фильтр будет применен к массиву из объектов сущности "File".
{
"query": "name",
"context": {
"name": "file.txt"
}
}
Integration-external-api: внешний интерфейс сервиса интеграций
Внешний API сервиса интеграций позволяет импортировать данные в систему на основе Verdi (далее просто Verdi), получать описание и пример данных для импорта.
Доступен по HTTP.
Сервис оперирует понятием сущности (entity). Он позволяет загрузить любые объекты с любым набором полей. Для отделения таких объектов с разным набором атрибутов друг от друга вводится понятие сущности. Сущность - это описание группы объектов, имеющих общий набор полей (например: договор, сотрудник или патент). Каждая сущность идентифицируется определенным типом entityType. Все операции с ней должны сопровождаться передачей соответствующего entityType в строке запроса.
Между двумя объектами могут устанавливаться отношения (relation).
Понятием "Вид отношения" называется комбинация двух сущностей и "виртуального" поля первой сущности.
Например: отношение авторства может быть представлено комбинацией сущностей Book и Person, и полем author.
Виртуальные поля отношений фактически не являются частью объекта и не могут быть напрямую указаны при создании или обновлении объекта;
но при этом возвращаются при получении объекта из Verdi.
Например: если у книги указан автор, его id вернется в поле author при получении данных этой книги.
Отношение между двумя объектами может быть установлено только в рамках какого-либо вида отношений сущностей этих объектов.
Между двумя сущностями может быть установлено несколько видов отношений;
кроме того может быть установлено отношение сущности с самой собой (например: отношение родительства или отношение связи элементов графа).
Вид отношений считается доступным для текущего клиента, если ему доступны обе входящие в него сущности
(см. Список сущностей, доступных для текущего клиента).
Для работы с файлами нужно использовать отдельный вызов UploadFile. По нему в систему можно загрузить некоторый файл. На выходе метода - id файла. Этот id необходимо передать при сохранении или обновлении объекта в соответствующем поле типа file. Тип поля можно узнать с помощью вызова GetEntityTypeSchema.
Каждый запрос требует указать заголовок X-Client-Token: [token], где [token] - это токен зарегистрированного, незаблокированного клиента.
Если запрос связан с какой-либо сущностью, данный клиент также должен иметь доступ к ней.
Во внешнем API реализовано получение документации по доступным для клиента типам данных:
- Список сущностей, доступных для текущего клиента
- Схема сущности
- Пример объекта сущности
- Генерация OpenAPI
- Загрузка файла
- Получение элементов справочника
- Создание объектов в системе (импорт)
- Обновление объектов в системе
- Удаление объектов в системе
- Получение данных объектов
- Обновление списка отношений объектов
- Получение метаданных объектов
В свою очередь, OpenAPI-документация содержит описание команд для работы с указанным типом данных, а также вспомогательных команд (загрузка файла для последующего использования в объектах, выгрузка элементов используемых справочников и т.д.).
Получение документации внешнего интерфейса сервиса интеграций
ListEntityTypesForCurrent
На входе ничего
На выходе список доступных типов данных для текущего клиента
[
{
"id": "paper",
"title": "Научная статья",
"description": "Документ, представляющий научную статью"
}
]
Возвращает перечень доступных для клиента типов данных
Путь: HTTP GET /external/v1/help/entityType
- Input: -
- Output: List[AvailableEntityType]
GetEntityTypeSchema
На входе ничего
На выходе JSON-Schema сущности
{
"$schema": "https://json-schema.org/draft/2019-09/schema",
"definitions": {
"date": {
"type": "integer"
},
"relation": {
"type": "string"
},
"catalog": {
"type": "string"
},
"multi-catalog": {
"type": "array",
"items": {
"type": "string",
"format": "uuid"
}
},
"file": {
"type": "object",
"properties": {
"fileId": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"size": {
"type": "integer",
"minimum": 0
},
"url": {
"type": "string"
},
"additional": {
"type": "object"
},
"created": {
"type": "integer",
"minimum": 0
},
"modified": {
"type": "integer",
"minimum": 0
},
"md5": {
"type": "string",
"pattern": "^[0-9a-fA-F]{32}$"
}
},
"required": [
"fileId"
]
}
},
"type": "object",
"properties": {
"modified": {
"$ref": "#/definitions/date",
"title": "Дата обновления файла",
"additional": false,
"rawType": "dateTime",
"description": "Дата обновления файла",
"example": 1582966800,
"exampleType": "number"
},
"created": {
"$ref": "#/definitions/date",
"title": "Дата создания файла",
"additional": false,
"rawType": "dateTime",
"description": "Дата создания файла",
"example": 1582966800,
"exampleType": "number"
},
"path": {
"type": "string",
"maxLength": 5000,
"title": "Путь в папке до файла",
"additional": false,
"rawType": "string",
"settings": {
"maxLength": 5000
},
"example": "/docs/dogovor.docx",
"exampleType": "string"
},
"name": {
"type": "string",
"maxLength": 1000,
"title": "Название файла",
"additional": false,
"rawType": "string",
"settings": {
"maxLength": 1000
},
"example": "Договор",
"exampleType": "string"
},
"file": {
"type": "array",
"items": {
"$ref": "#/definitions/file"
},
"multiple": false,
"maxItems": 1,
"title": "ID файла",
"additional": false,
"rawType": "file"
},
"author": {
"title": "Автор документа",
"$ref": "#/definitions/relation",
"multiple": false,
"additional": false,
"readOnly": true,
"nullable": true,
"to": "Author",
"settings": {
"to": "Author"
}
}
},
"required": [
"created",
"path",
"name",
"file"
],
"relations": [
{
"name": "Document_To_Author",
"entity1": "Document",
"entity2": "Author",
"entity1Field": "author",
"entity2Field": "documents",
"relationType": "many-to-one"
}
]
}
Получение описания модели данных для конкретной сущности в виде JSON-Schema.
Путь: HTTP GET /external/v1/help/entityType/:entityTypeId/schema
- Input: -
- Output: JSON-Schema
GetObjectExample
На входе ничего
На выходе пример данных объекта
{
"id": "64f1e728-7fe7-4886-9d5c-e72452dbc3ce",
"internalId": "933d8db6-fddc-475e-8366-652c8d0a0f32",
"entityType": "FolderFile",
"source": "example",
"created": 1644839076580,
"modified": 1644839076580,
"data": {
"created": 1582966800,
"file": [
{
"fileId": "00000000-0000-0000-0000-000000000000",
"name": "Пример_файла.txt",
"extension": "txt",
"size": 1,
"url": "datamodel/00000000-0000-0000-0000-000000000000",
"additional": {},
"created": 0,
"modified": 0,
"md5": "D41D8CD98F00B204E9800998ECF8427E"
}
],
"modified": 1582966800,
"name": "Договор",
"path": "/docs/dogovor.docx",
"author": "author1Id"
},
"additionalData": {},
"version": 1
}
Получение примера объекта указанной сущности
Путь: HTTP GET /external/v1/help/entityType/:entityTypeId/example
- Input: -
- Output: EntityObject
GetOpenAPI
Генерирует описание внешнего API для указанной сущности (в формате OpenAPI v3.1.0)
Путь: HTTP GET /external/v1/help/entityType/:entityTypeId/openAPI
- Input: -
- Output: Json в формате OpenAPI v3.1.0
Работа с файлами (внешний интерфейс сервиса интеграций)
UploadFile
На входе POST-запрос с Content-Type: multipart/form-data и файлом в бинарном виде в поле file
На выходе ID загруженного файла
{
"fileId": "1c689788-9617-4c93-bcee-6eae8909a0ba"
}
Загрузить файл в систему.
Путь: HTTP POST /external/v1/file/upload
- Input: multipart/form-data с файлом в поле file
- Output: FileUploadResult
Работа со справочниками (внешний интерфейс сервиса интеграций)
ListCatalogItems
На входе номер и размер страницы, и, опционально, фильтр по названию элемента
{
"paging": {
"page": 1,
"count": 10
},
"titleLike": "%файл%"
}
На выходе искомый список элементов запрашиваемого справочника и их общее количество на всех страницах
{
"items": [
{
"id": "2247fbe6-1f78-47d3-af28-e71f75535a84",
"catalogId": "fbf859d2-30db-4789-9fdd-71add0832772",
"code": "FileTags-3",
"title": "Файл кода",
"archived": false,
"metadata": {},
"created": 1642749153188,
"modified": 1664290811956,
"version": 10
},
{
"id": "a4f1b0e5-0c47-4d82-bbd7-2c1f2164765a",
"catalogId": "fbf859d2-30db-4789-9fdd-71add0832772",
"code": "FileTags-5",
"title": "Музыкальный файл",
"archived": false,
"metadata": {},
"created": 1642749350176,
"modified": 1642758418413,
"version": 3
},
{
"id": "6d2aa5c7-b0b8-455f-82c2-da90ff074a95",
"catalogId": "fbf859d2-30db-4789-9fdd-71add0832772",
"code": "FileTags-6",
"title": "Видеофайл",
"archived": false,
"metadata": {},
"created": 1642757894740,
"modified": 1643197192686,
"version": 2
}
],
"total": 3
}
Получение данных справочника в системе.
Путь: HTTP POST /external/v1/catalog/:catalogCode/listItems
- Input: ListCatalogItemsDTO
- Output: Page[CatalogItem]
Работа с объектами (внешний интерфейс сервиса интеграций)
CreateEntity (Integration)
На входе список создаваемых объектов
{
"items": [
{
"id": "first",
"data": {
"number": 1,
"file": [
{
"fileId": "dfca1cac-0df2-454a-b57a-4a2c360b09db"
}
]
}
},
{
"id": "second",
"data": {
"number": 2,
"file": [
{
"fileId": "724d8b05-6992-4d3c-ac0b-501ef02cb74e"
}
]
}
}
]
}
На выходе данные по статусу создания каждого объекта и дополнительные данные о загрузке
{
"items": [
{
"id": "first",
"statusCode": 201,
"payload": null
},
{
"id": "second",
"statusCode": 409,
"payload": null
}
]
}
Создание объектов в системе (импорт).
Для каждого объекта передается id и его атрибуты в виде произвольного json. Набор атрибутов должен соответствовать json-схеме сущности, которую можно получить с помощью вызова GetEntityTypeSchema
Путь: HTTP POST /external/v1/entity/:entityTypeId
- Input: ObjectCrudDTO
- Output: ObjectCrudResponse
UpdateEntity (Integration)
На входе список обновляемых объектов
{
"items": [
{
"id": "first",
"data": {
"number": 101,
"file": [
{
"fileId": "0cae7ea7-a6eb-4492-b72f-7a3d8187a17c"
}
]
}
},
{
"id": "second",
"data": {
"number": 102,
"file": [
{
"fileId": "22b9e63e-c0b6-43a6-9ce3-6540d5731c2b"
}
]
}
}
]
}
На выходе данные по статусу обновления каждого объекта и дополнительные данные об обновлении
{
"items": [
{
"id": "first",
"statusCode": 200,
"payload": null
},
{
"id": "second",
"statusCode": 404,
"payload": {
"message": "Processing error: ERROR: Entity object not found",
"data": null
}
}
]
}
Обновление данных объектов в системе. Обновление данных происходит путем поиска подходящих объектов по переданному id. Переданные данные по объекту перезаписывают имеющиеся.
Для каждого объекта передается id и его атрибуты в виде произвольного json. Набор атрибутов должен соответствовать json-схеме сущности, которую можно получить с помощью вызова GetEntityTypeSchema
Путь: HTTP PUT /external/v1/entity/:entityTypeId
- Input: ObjectCrudDTO
- Output: ObjectCrudResponse
DeleteEntity (Integration)
На входе перечень ID удаляемых объектов
{
"items": [
{
"id": "second"
}
]
}
На выходе данные по статусу удаления каждого объекта и дополнительные данные об удалении
{
"items": [
{
"id": "second",
"statusCode": 200,
"payload": null
}
]
}
Удаление объектов в системе.
Путь: HTTP POST /external/v1/entity/:entityTypeId/deleteByIds
- Input: ObjectCrudDTO
- Output: ObjectCrudResponse
GetEntity (Integration)
На входе перечень ID объектов
{
"items": [
{
"id": "first"
}
]
}
На выходе данные по каждому запрошенному объекту
{
"items": [
{
"id": "first",
"statusCode": 200,
"payload": {
"id": "first",
"internalId": "21c30f14-6671-4c3d-b238-d7bb7f738ee5",
"entityType": "document",
"source": "IntegrationClient",
"created": 1651821345542,
"modified": 1651821345542,
"data": {
"number": 101,
"file": [
{
"fileId": "0cae7ea7-a6eb-4492-b72f-7a3d8187a17c",
"name": "Договор.pdf",
"extension": "pdf",
"size": 254873,
"url": "datamodel/document/0cae7ea7-a6eb-4492-b72f-7a3d8187a17c",
"additional": {},
"created": 1651821345718,
"modified": 1651821345718,
"md5": "C4BA149A18155BF6E74AA55AA79776D6"
}
]
},
"additionalData": {},
"version": 2
}
}
]
}
Получение данных объектов.
Путь: HTTP POST /external/v1/entity/:entityTypeId/getByIds
- Input: ObjectCrudDTO
- Output: ObjectCrudResponse
UpdateEntityRelations (Integration)
На входе перечень связываемых отношениями объектов с указанием виртуальных полей отношений
{
"items": [
{
"id": "firstArticle",
"relations": {
"fromBook": ["myFirstBook"],
"authors": ["me"]
}
},
{
"id": "secondArticle",
"relations": {
"fromBook": ["mySecondBook"],
"authors": ["me", "anotherGuy"]
}
}
]
}
На выходе статус сохранения каждого отношения
{
"items": [
{
"id": "firstArticle",
"relation": "fromBook",
"relatedId": "myFirstBook",
"error": null
},
{
"id": "firstArticle",
"relation": "authors",
"relatedId": "me",
"error": null
},
{
"id": "secondArticle",
"relation": "fromBook",
"relatedId": "mySecondBook",
"error": null
},
{
"id": "secondArticle",
"relation": "authors",
"relatedId": "me",
"error": null
},
{
"id": "secondArticle",
"relation": "authors",
"relatedId": "anotherGuy",
"error": null
}
]
}
Обновление списка отношений для объектов сущности entityTypeId.
Команда полностью обновляет список отношений каждого из объектов сущности;
таким образом, указанные в теле команды отношения будут созданы, а не указанные — удалены.
Например: если у объекта first были ранее созданы отношения с объектами A и B по полю field,
а при вызове команды в теле был указан элемент {"id": "first", "relations": {"field": ["A", "C"]}},
то отношение с объектом B удалится, а с объектом C — создастся.
Список доступных для обновления отношений для конкретной сущности можно узнать, получив OpenApi по этой сущности.
В схеме формата тела данной команды будут указаны все поля, которые можно использовать текущему клиенту;
а в описании конкретного поля будет указана сущность, с которой по этому полю устанавливается связь.
Если какие-то из указанных полей не будут переданы в теле команды, соответствующие отношения не будут обновлены.
Путь: HTTP POST /external/v1/entity/:entityTypeId/updateRelations
- Input: UpdateRelationsDTO
- Output: UpdateRelationsResponse
ListEntityMeta (Integration)
На входе данные для получения определенной страницы
{
"paging": {
"page": 2,
"count": 10
}
}
На выходе страница со списком объектов
{
"items": [
{
"id": "first",
"internalId": "21c30f14-6671-4c3d-b238-d7bb7f738ee5",
"entityType": "document",
"source": "IntegrationClient",
"created": 1651821345542,
"modified": 1651821345542,
"version": 2
}
],
"total": 11
}
Получение метаданных объектов в системе: идентификаторов и прочих служебных аттрибутов.
Путь: HTTP POST /external/v1/entity/:entityTypeId/listMeta
- Input: ListEntityMetaDTO
- Output: Page[EntityMeta]
Объекты документации внешнего интерфейса сервиса интеграций
AvailableEntityType
Описание доступной текущему клиенту сущности
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | string | Да | Код сущности |
| title | string | Да | Название сущности |
| description | string | Да | Описание сущности |
EntityObject (Integration)
Данные объекта сущности
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | string | Нет | Идентификатор объекта, с которым он был загружен. Будет пустым, если объект создан внутри системы |
| internalId | uuid | Да | Внутренний идентификатор объекта в формате UUID |
| entityType | string | Да | Тип сущности объекта |
| source | string | Да | Источник, откуда был получен объект (импорт, интерфейс, итп) |
| created | timestamp | Да | Дата и время создания объекта в виде timestamp |
| modified | timestamp | Да | Дата и время последнего изменения объекта в виде timestamp |
| data | json object | Да | Исходные данные объекта. Могут быть изменены пользователем |
| additionalData | json object | Да | Дополнительные данные по объекту, полученные системой из сервисов интеллектуализации |
| version | integer | Да | Версия изменений |
ListEntityMetaDTO (Integration)
Запрос списка метаданных объектов
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| paging | Paging | Да | Данные для получения определенной страницы |
EntityMeta (Integration)
Метаданные объекта сущности
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | string | Нет | Идентификатор объекта, с которым он был загружен. Будет пустым, если объект создан внутри системы |
| internalId | uuid | Да | Внутренний идентификатор объекта в формате UUID |
| entityType | string | Да | Тип сущности объекта |
| source | string | Да | Источник, откуда был получен объект (импорт, интерфейс, итп) |
| created | timestamp | Да | Дата и время создания объекта в виде timestamp |
| modified | timestamp | Да | Дата и время последнего изменения объекта в виде timestamp |
| version | integer | Да | Версия изменений |
FileUploadResult
Результат загрузки файла
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| fileId | string | Да | Идентификатор загруженного файла в формате UUID |
ListCatalogItemsDTO
Запрос элементов справочника
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| paging | Paging | Да | Данные для получения определенной страницы |
| titleLike | string | Нет | Поиск по названию элемента справочника. Если поле пустое, тогда возвращаются все элементы |
CatalogItem
Данные элемента справочника
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | uuid | Да | Идентификатор элемента справочника в формате UUID |
| catalogId | uuid | Да | Идентификатор справочника в формате UUID |
| code | string | Да | Код элемента справочника |
| title | string | Да | Название элемента справочника |
| archived | boolean | Да | Признак архивности элемента |
| metadata | json object | Да | Произвольные дополнительные данные в виде json-объекта |
| created | timestamp | Да | Дата и время создания элемента в виде timestamp |
| modified | timestamp | Да | Дата и время последнего изменения элемента в виде timestamp |
| version | integer | Да | Версия изменений |
ObjectCrudDTO
Список объектов для выполнения CRUD-операции с ними
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| items | List[ObjectCrudDTOItem] | Да | Список объектов для выполнения операции с ними |
ObjectCrudDTOItem
Данные объекта для выполнения CRUD-команды с ним
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | string | Да | Идентификатор объекта в исходной системе |
| data | json object | Нет | Опциональные данные объекта в произвольном json-формате ключ-значение. Актуально в командах Create и Update. |
ObjectCrudResponse
Ответ на CRUD-операцию (команду) со списком объектов
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| items | List[ObjectCrudResponseItem] | Да | Список результатов выполнения команд над объектами |
ObjectCrudResponseItem
Результат выполнения CRUD-команды над объектом
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | string | Да | Идентификатор объекта в исходной системе |
| statusCode | integer | Да | Код результата операции с объектом в формате кода HTTP-ответа |
| payload | json object | Нет | Данные ответа в произвольном json-формате |
UpdateRelationsDTO
Запрос на обновление списка отношений объектов
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| items | List[UpdateRelationsDTOItem] | Да | Список объектов для выполнения операции с ними |
UpdateRelationsDTOItem
Данные объектов для установления отношений между ними
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | string | Да | ID объекта, для которого обновляется список отношений |
| relations | json object | Да | Объект, где ключ - это название поля отношения, а значение — ID объектов, которые должны быть связаны отношением с объектом id |
UpdateRelationsResponse
Ответ на операцию (команду) обновления перечня отношений
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| items | List[UpdateRelationsResponseItem] | Да | Список результатов сохранения указанных отношений |
UpdateRelationsResponseItem
Результат сохранения отношения между объектами
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | string | Да | ID объекта, для которого обновлялся список отношений |
| relatedId | string | Да | ID объекта, связываемого отношением с объектом id |
| relation | string | Да | Название поля, по которому устанавливается отношение |
| error | string | Нет | Ошибка сохранения отношения, если сохранение прошло неуспешно; иначе null |
Integration: сервис интеграций
Сервис интеграций, он же сервис импорта, включает в себя внутренний и внешний API:
- Внутренний API - позволяет регулировать доступ клиентов к внешнему API. Является набором команд Verdi.
- Внешний API - позволяет импортировать данные в систему на основе Verdi, получать описание и пример данных для импорта. Доступен по HTTP.
В данной документации описан внутренний API. Во внутреннем API сервиса реализованы следующие команды:
- Регистрация клиента
- Список зарегистрированных клиентов
- Обновление клиента
- Обновление токена доступа для клиента
- Выдача права для клиента на действия с данными определенного типа
- Запрет для клиента на действия с данными определенного типа
- Список всех доступных типов данных
- Обновить список всех доступных типов данных из сервиса модели данных
- Список типов данных, доступных для указанного клиента
Локальный запуск сервиса интеграций
При запуске сервиса ожидается, что уже развернута необходимая инфраструктура:
- PostgreSQL база по адресу, указанному в конфиге (см. ниже)
- Kafka по адресу
localhost:9092 - Consul по адресу
localhost:8500 - Добавлены необходимые переменные окружения:
- INTEGRATION_DB_HOST
- INTEGRATION_DB_PORT
- INTEGRATION_DB_NAME
- INTEGRATION_DB_USER
- INTEGRATION_DB_PASSWORD
Кроме того, конфигурация стенда должна подразумевать доступ к внешней части API
(т.е. той части, путь которой начинается с /external) по HTTP, минуя apigateway.
Например, на сервере может быть настроено перенаправление с http://verdi-host.org/integration/api/external/path
на /external/path.
Запуск из консоли с помощью SBT
INTEGRATION_DB_HOST=localhost INTEGRATION_DB_PORT=5432 INTEGRATION_DB_NAME=integration_db INTEGRATION_DB_USER=postgres INTEGRATION_DB_PASSWORD=12345 sbt boot/run
Список переменных окружения для сервиса Integration
| Переменная | Тип | Обязательная | Значение по умолчанию | Описание |
|---|---|---|---|---|
INTEGRATION_HTTP_HOST |
string | нет | "0.0.0.0" | Хост для HttpListener. |
INTEGRATION_HTTP_PORT |
int | нет | 8192 | Порт для HttpListener. |
INTEGRATION_KAFKA_SERVERS |
string | нет | "localhost:9092" | Адрес Kafka. |
INTEGRATION_KAFKA_TOPIC |
string | нет | "integration_commands" | Название топика для команд. |
INTEGRATION_KAFKA_CONSUMER_GROUP |
string | нет | "integration_consumer_group" | Название consumer-группы для чтения команд. |
INTEGRATION_KAFKA_COMMANDEVENT_TOPIC |
string | нет | "commandevents" | Название топика для отправки сообщений со статусом команд. |
INTEGRATION_KAFKA_PARTITIONS |
int | нет | 10 | Количество партиций в топике команд. |
INTEGRATION_KAFKA_CONSUMER_RESTART_MIN_BACKOFF |
duration string | нет | 1 second | Минимальная задержка перед перезапуском. |
INTEGRATION_KAFKA_CONSUMER_RESTART_MAX_BACKOFF |
duration string | нет | 30 seconds | Максимально возможная задержка перед перезапуском. |
INTEGRATION_KAFKA_CONSUMER_RESTART_RANDOM_FACTOR |
float | нет | 0.2 | Коэффициент величины дополнительной случайной задержки(jitter) относительно основной задержки: 0.0 - без случайной задержки, 1.0 - до 100% задержки. Если после умножения задержки на INTEGRATION_KAFKA_CONSUMER_RESTART_RANDOM_FACTOR получится меньше 1 миллисекунды, то jitter будет приравнен к нулю. |
INTEGRATION_KAFKA_CONSUMER_RESTART_MAX_RESTARTS |
int | нет | 5 | Максимальное количество перезапусков в заданный период времени. После превышения этого числа сервис будет объявлен больным. Все рестарты для каждого отдельного сообщения увеличивают и общий счетчик рестартов консьюмера, поэтому при использовании INTEGRATION_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS нужно указывать INTEGRATION_KAFKA_CONSUMER_RESTART_MAX_RESTARTS > INTEGRATION_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS или не указывать INTEGRATION_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS совсем. |
INTEGRATION_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS |
int | нет | 2 | Максимальное количество раз, которое консьюмер перезапустится с неизменной очередью сообщений(в пределах DATA_MODEL_KAFKA_CONSUMER_RESTART_MAX_RESTARTS_WITHIN), прежде чем проигнорировать сообщение, на котором происходит ошибка (Указано количество рестартов, а не прочтений. Если INTEGRATION_KAFKA_CONSUMER_RESTART_MAX_RESTARTS = 2, то ошибочное сообщение будет обработано 3 раза, после чего произойдет 3ий рестарт и оно будет проигнорировано). Если указать 0, то перезапуск произойдет, но сообщение будет обработано только в первый раз, когда произошла ошибка. Если указать значение меньше 0, то перезапуски все равно будут происходить, но игнорирование сообщений, вызывающих ошибку, будет отключено. |
INTEGRATION_KAFKA_CONSUMER_PER_MESSAGE_RESTART_CACHE_SIZE |
int | нет | 100 | Для каждого сообщения счетчик перепрочтений хранится в кэше. Максимальное количество значений в этом кэше. |
INTEGRATION_KAFKA_CONSUMER_PER_MESSAGE_RESTART_CACHE_TTL |
duration string | нет | 5 minutes | Для каждого сообщения счетчик перепрочтений хранится в кэше.Максимальное время жизни элемента в этом кэше. В случае отсутствия значения время жизни элемента не будет ограничено. |
INTEGRATION_KAFKA_CONSUMER_RESTART_MAX_RESTARTS_WITHIN |
duration string | нет | 5 minutes | Период времени для ограничения перезапусков. |
INTEGRATION_KAFKA_CONSUMER_POLL_TIMEOUT |
duration string | нет | 10 milliseconds | timeout запроса poll для kafka consumer |
INTEGRATION_KAFKA_CONSUMER_POLL_INTERVAL |
duration string | нет | 100 milliseconds | интервал между запросами poll для kafka consumer |
INTEGRATION_KAFKA_CONSUMER_PROPS |
string | нет | "max.poll.records=500;max.partition.fetch.bytes=524288" | дополнительные параметры для kafka consumer в формате "key1=value1;key2=value2" |
INTEGRATION_KAFKA_PRODUCER_PROPS |
string | нет | "batch.size=524288;linger.ms=10;max.request.size=1048576" | дополнительные параметры для kafka producer в формате "key1=value1;key2=value2" |
INTEGRATION_KAFKA_AUTH_USER |
string | нет | "" | Название учетной записи Kafka. Если название не указано, то настройки авторизации не будут применены. |
INTEGRATION_KAFKA_AUTH_PASSWORD |
string | нет | "" | Пароль учетной записи Kafka. |
INTEGRATION_KAFKA_AUTH_PRINCIPAL |
string | нет | "" | Principal учетной записи Kafka в Kerberos(в случае соединения с kafka через Kerberos). |
INTEGRATION_KAFKA_AUTH_KEYTAB_PATH |
string | нет | "" | Путь до keytab-файла(в случае соединения с kafka через Kerberos). |
INTEGRATION_KAFKA_AUTH_TRUSTSTORE_LOCATION |
string | нет | "" | Путь до хранилища сертификатов (Java key store). Если путь не указан, то сертификат применяться не будет. |
INTEGRATION_KAFKA_AUTH_TRUSTSTORE_PASSWORD |
string | нет | "" | Пароль к хранилищу сертификатов. |
INTEGRATION_KAFKA_AUTH_MODE |
string | нет | "static" | Режим аутентификации: static - одна учетная запись на все запросы, mapping - учетная запись зависит от запроса |
INTEGRATION_KAFKA_AUTH_CONFIG |
string | нет | "" | Настройки для аутентификации: если AuthMode = mapping, то необходим JSON с List[KafkaAuthConfig]. Переменная соответствует полю authConfig из KafkaAuthSettings. |
INTEGRATION_KAFKA_AUTH_CACHE_SIZE |
int | нет | Максимальный размер кеша для Kafka producer (количество активных соединений). | |
INTEGRATION_KAFKA_AUTH_CACHE_TTL |
duration string | нет | Время жизни Kafka producer в кеше. | |
INTEGRATION_KAFKA_CONNECTION_CHECK_TEST_MESSAGES_INTERVAL |
duration string | нет | 4 minutes | Применяется только для producer-ов со способом аутентификации kerberos. Интервал отправки тестовых сообщений кафки в топик connectionCheck.testMessagesTopicName. Тестовые сообщения (null, service producer test) отправляются регулярно с этим интервалом. |
INTEGRATION_KAFKA_CONNECTION_CHECK_INTERVAL |
duration string | нет | 60 seconds | Применяется только для producer-ов со способом аутентификации kerberos. Интервал проверки того, сколько тестовых сообщений было отправлено за данный период. Если количество сообщений за этот период равно количеству сообщений за прошлый период, то начинается отсчет периода без сообщений. |
INTEGRATION_KAFKA_CONNECTION_CHECK_FAILED_AFTER_INTERVAL |
duration string | нет | 5 minutes | Применяется только для producer-ов со способом аутентификации kerberos. Максимальная продолжительность периода без успешно отправленных тестовых сообщений. По ее достижении сервис будет объявлен больным. |
INTEGRATION_CONSUL_ADDR |
string | нет | "http://localhost:8500" | Адрес Сonsul. |
INTEGRATION_CONSUL_AUTH_USER |
string | нет | "" | Название учетной записи Сonsul. Если название не указано, то настройки авторизации не будут применены. |
INTEGRATION_CONSUL_AUTH_PASSWORD |
string | нет | "" | Пароль учетной записи Сonsul. |
INTEGRATION_TRACE_DURATION |
bool | нет | false | Признак необходимости трассировки выполнения команд. |
INTEGRATION_DISCOVERABLE_ID |
string | нет | "another_integration_instance" | Id сервиса в ServiceDiscovery. |
INTEGRATION_DISCOVERABLE_NAME |
string | нет | "integration" | Имя сервиса в ServiceDiscovery. |
INTEGRATION_DISCOVERABLE_HOST |
string | нет | "localhost" | Хост, публикуемый в ServiceDiscovery. |
INTEGRATION_DISCOVERABLE_PORT |
int | нет | 8192 | Порт, публикуемый в ServiceDiscovery. |
INTEGRATION_DISCOVERABLE_LIVETIME |
duration string | нет | 2 minutes | Период после отправки health check, в течение которого ServiceDiscovery считает сервис живым. |
INTEGRATION_DISCOVERABLE_HEALTHPASS |
duration string | нет | 1 minute | Периодичность отправки health check в ServiceDiscovery. |
INTEGRATION_AKKA_HTTP_CLIENT_MAXCON |
int | нет | 512 | Максимальное число одновременных исходящих HTTP-соединений. |
INTEGRATION_AKKA_HTTP_CLIENT_MAXREQ |
int | нет | 1024 | Максимальное число одновременных исходящих HTTP-запросов. |
INTEGRATION_AKKA_HTTP_SERVER_MAXCON |
int | нет | 1024 | Максимальное число одновременных входящих HTTP-соединений. |
INTEGRATION_AKKA_HTTP_PARSING_MAX_BYTES |
size string | нет | 50m | Максимальный размер данных из http-запроса, который может быть принят и распаршен |
INTEGRATION_AKKA_HTTP_PARSING_MAX_CHUNK_SIZE |
size string | нет | 10m | Максимальный размер одной части http-запроса, который может быть принят и распаршен |
INTEGRATION_AKKA_HTTP_SERVER_REQUEST_TIMEOUT |
duration string | нет | 2 minutes | Таймаут запросов к сервису по умолчанию. |
INTEGRATION_AKKA_HTTP_SERVER_IDLE_TIMEOUT |
duration string | нет | 3 minutes | Таймаут, по истечению которого бездействующее соединение закрывается. |
INTEGRATION_INTERNALCMD_ALLOW |
bool | нет | true | Можно ли сервису отправлять внутрисистемные команды. |
INTEGRATION_SENDERLIB_CONSIDER_ALL_COMMANDS_AS_INTERNAL |
boolean | Нет | false | Флаг, определяющий будут ли все обращения в другие сервисы являться внутренними (т.е. не требовать авторизацию). Детальное описание механизма: Внутренние команды. |
INTEGRATION_SENDERLIB_COMMANDS_CACHE_UPDATEPERIOD |
duration string | нет | 10 minutes | Время кэширования данных по командам из CommandDiscovery. |
INTEGRATION_SENDERLIB_SERVICES_CACHE_UPDATEPERIOD |
duration string | нет | 30 seconds | Время кэширования данных по сервисам из ServiceDiscovery. |
INTEGRATION_DB_URL |
string | да | Адрес базы данных. Можно использовать вместо DB_HOST, DB_PORT и DB_NAME. | |
INTEGRATION_DB_HOST |
string | да | Хост сервера базы данных. | |
INTEGRATION_DB_PORT |
int | да | Порт сервера базы данных. | |
INTEGRATION_DB_NAME |
string | да | Название базы данных. | |
INTEGRATION_DB_USER |
string | да | Пользователь базы данных. | |
INTEGRATION_DB_PASSWORD |
string | да | Пароль для пользователя базы данных. | |
INTEGRATION_DB_THREADS |
int | нет | 10 | Количество потоков в пуле потоков для соединения с БД |
INTEGRATION_DB_QUEUE_SIZE |
int | нет | 300 | Размер очереди для действий базы данных, которые не могут быть выполнены немедленно, когда все потоки заняты. За пределами этого значения новые действия немедленно завершаются неудачей |
INTEGRATION_DB_CONN_MAX |
int | нет | 10 | Максимальное количество одновременных подключений к БД |
INTEGRATION_DB_CONN_TIMEOUT |
duration string | нет | 20 second | Максимальное время ожидания ответа для соединения к БД. Если это время превышено, а соединение не становится доступным, будет брошено исключение SQLException. 1000 мс — минимальное значение. |
INTEGRATION_DB_ISOLATION |
string | нет | "READ_COMMITTED" | Уровень изоляции транзакций для новых подключений. Допустимые значения: NONE, READ_COMMITTED, READ_UNCOMMITTED, REPEATABLE_READ, SERIALIZABLE. |
INTEGRATION_DB_READONLY |
boolean | нет | false | Read-only SQL транзакция может изменять только временные таблицы. Этот параметр управляет статусом «только для чтения» по умолчанию для каждой новой транзакции. |
INTEGRATION_DB_CONN_MIN |
int | нет | = DB_THREADS | Минимальное количество одновременных подключений к БД |
INTEGRATION_DB_VALIDATION_TIMEOUT |
duration string | нет | 1 seconds | Максимальное время, в течение которого соединение будет проверяться на работоспособность. 1000 мс — минимальное значение. |
INTEGRATION_DB_IDLE_TIMEOUT |
duration string | нет | 10 minutes | Максимальное время, в течение которого соединению разрешено простаивать в пуле. Значение 0 означает, что простаивающие соединения никогда не удаляются из пула. |
INTEGRATION_DB_MAX_LIFETIME |
duration string | нет | 30 minutes | Максимальное время жизни соединения в пуле. Когда простаивающее соединение достигает этого времени ожидания, даже если оно недавно использовалось, оно будет удалено из пула. Значение 0 указывает на отсутствие максимального срока службы. |
INTEGRATION_DB_INITIALIZATION_FAIL_FAST |
string | нет | false | Deprecated, начиная с версии Slick 3.3.0. Определяет, будет ли пул «быстро выходить из строя», если пул не может быть успешно заполнен начальными соединениями. Если соединения не могут быть созданы во время запуска пула, будет выдано исключение RuntimeException. Это свойство не имеет никакого эффекта, если minConnections равно 0. |
INTEGRATION_DB_LEAK_DETECTION_THRESHOLD |
int | нет | 0 | Время, в течение которого соединение может находиться вне пула, прежде чем будет зарегистрировано сообщение, указывающее на возможную утечку соединения. Значение 0 означает, что обнаружение утечек отключено. Наименьшее приемлемое значение для включения обнаружения утечек составляет 10 с. |
INTEGRATION_DB_CONNECTION_TEST_QUERY |
string | нет | "SELECT 1" | Выражение, которое будет выполнено непосредственно перед получением соединения из пула для проверки того, что соединение с базой данных все еще активно. Оно зависит от базы данных и должно представлять собой запрос, требующий минимальной обработки базой данных (например, «VALUES 1»). Если этот параметр не установлен, вместо него используется метод JDBC4 Connection.isValid(). |
INTEGRATION_DB_AUTO_COMMIT |
boolean | нет | true | Это свойство определяет то, как будут вести себя по умолчанию возвращаемые соединения относительно autocommit-а. |
INTEGRATION_DB_SCHEMA |
string | нет | "public" | Устанавливает schema по умолчанию |
INTEGRATION_DB_ISOLATE_INTERNAL_QUERIES |
boolean | нет | false | Определяет то, изолируются ли с помощью транзакций внутренние запросы пула(например запрос connection alive test). Свойство применяется только если autoCommit выключен. |
INTEGRATION_DB_INITIALIZATION_FAIL_TIMEOUT |
int | нет | 1 | Работает, начиная с версии Slick 3.3.0. Определяет, будет ли пул «быстро выходить из строя», если пул не может быть успешно заполнен начальными соединениями. Любое положительное число считается числом миллисекунд для попытки получить начальное соединение;поток приложения будет заблокирован в течение этого периода. Если соединение не может быть получено до истечения этого времени,будет брошено исключение. Данный таймаут применяется после периода connectionTimeout. Если значение равно нулю (0),HikariCP попытается получить и проверить подключение. Если соединение получено,но проверка не пройдена, будет брошено исключение, и пул не будет запущен. Однако,если соединение не может быть получено, пул запустится,но последующие попытки получить соединение могут потерпеть неудачу.Значение меньше нуля пройдет любую первоначальную попытку подключения, и пул немедленно запустится,пытаясь получить соединения в фоновом режиме.Следовательно, последующие попытки получить соединение могут потерпеть неудачу. |
INTEGRATION_DB_REGISTER_MBEANS |
boolean | нет | false | Зарегистрированы ли JMX Management Beans («MBeans») |
INTEGRATION_PROCESSING_MULTIPLE_COMMAND_TIMEOUT |
duration string | нет | 1 minute | Таймаут батч-команд (команд над несколькими объектами). |
INTEGRATION_PROCESSING_MAX_TOTAL_ENTITIES_IN_PROCESS |
int | нет | 1000 | Максимальный размер очереди выполняемых единичных команд (среди всех клиентов). |
INTEGRATION_PROCESSING_COMMAND_PROCESSING_PARALLELISM |
int | нет | 32 | Максимальное число одновременно выполняемых команд (среди всех клиентов). |
INTEGRATION_FS_URI |
string | нет | http://localhost:9000 | Адрес для подключения к Minio. |
INTEGRATION_FS_ACCESS_KEY_ID |
string | нет | "minioadmin" | Ключ доступа к хранилищу файлов Minio (aka пользователь). |
INTEGRATION_FS_SECRET_ACCESS_KEY |
string | нет | "minioadmin" | Секретный код доступа к хранилищу файлов Minio (aka пароль). |
INTEGRATION_FS_UPLOAD_PARALLELISM |
int | нет | 4 | Максимально возможный параллелизм при загрузке файлов в хранилище. |
INTEGRATION_FS_AUTH_MODE |
string | нет | static | Режим аутентификации: static - одна учетная запись на все запросы, mapping - учетная запись зависит от запроса |
INTEGRATION_FS_AUTH_CONFIG |
string | нет | "" | Настройки для аутентификации: если AuthMode = mapping, то необходим JSON с List[FSBucketConfig] соответствует полю authConfig FSConfigRep |
INTEGRATION_FS_CACHE_SIZE |
int | нет | 1 | Максимальный размер кеша клиентов для хранилища файлов (количество активных соединений). |
INTEGRATION_FS_CACHE_TTL |
duration string | нет | Время жизни клиента в кеше | |
INTEGRATION_FS_RETRY_ATTEMPTS |
int | нет | 5 | Количество ретраев, которое будет произведено в случае Exception-а в операции FSClient-а и при вычитывании стрима в get операциях FSClient-а. |
INTEGRATION_FS_RETRY_DELAY |
duration string | нет | 10 millis | Задержка между ретраями операций FSClient-а. |
INTEGRATION_FS_SIZE_LIMIT_KB |
int | нет | 102400 | Максимальный размер загружаемого файла в килобайтах. |
INTEGRATION_FS_BUCKETS_TEMP |
string | нет | temp | Временный бакет, куда сохраняются файлы для дальнейшей отправки в составе полей объекта. |
| INTEGRATION_FS_ZIO_SHORT_MESSAGE_MODE | boolean | нет | false | Флаг включения режима сохранения ошибок работы с файловым хранилищем в сервисе журналирования nestor. При включении режима ошибки в логах будут отображаться в сокращенном формате: Short zio message mode. ExceptionType: ТИП ОШИБКИ, Exception id: 'СГЕНЕРИРОВАННЫЙ UUID' added to journal. Указанный id будет фиксироваться в event записи nestor'а в поле data.id |
INTEGRATION_ENTITY_TYPES_REFRESH_RATE |
duration string | нет | 5 minutes | Периодичность обновления перечня доступных типов данных из модели данных. |
INTEGRATION_SENDERLIB_COMMANDS_HTTP_RETRY_ATTEMPTS |
int | нет | 5 | Поле attempts из RetrySettings |
INTEGRATION_SENDERLIB_COMMANDS_HTTP_RETRY_DELAY |
duration string | нет | "5 seconds" | Поле delay из RetrySettings |
INTEGRATION_SENDERLIB_COMMANDS_HTTP_RETRY_KIND |
string | нет | "OnSomeExceptions(ConnectException)" | CommandResultRetryConditionKind |
INTEGRATION_SENDERLIB_CONSUL_CONNECTION_RETRY_MAX |
int | нет | 5 | Количество попыток переподключения к Consul |
INTEGRATION_SENDERLIB_CONSUL_CONNECTION_RETRY_DELAY |
duration string | нет | "1 second" | Задержка при попытках переподключения к Consul |
INTEGRATION_JOURNAL_MODE |
string | нет | WriteToJournal |
Режим журналирования Nestor. Допустимые значения: WriteToJournal (Отправка в сервис журналирования), WriteToTopic (Отправка события в очередь) |
INTEGRATION_JOURNAL_TOPIC |
string | да, если переменная INTEGRATION_JOURNAL_MODE = WriteToTopic |
"" | Название очереди журналирования. Для режима WriteToJournal значение игнорируется. |
Команды сервиса Integration
CreateClient (Integration)
На входе свойства регистрируемого клиента
{
"id": "network-folder-papers",
"title": "Сетевая папка - научные статьи",
"allowFiles": true,
"data": null
}
На выходе Boolean (признак успешности исполнения)
true
Регистрирует новый клиент.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
- Input: CreateClientDTO
- Output: Boolean
| Команда | Путь |
|---|---|
| integration_CreateClient | Kafka Topic "integration_commands" |
ListClients (Integration)
Входные данные отсутствуют
На выходе перечень зарегистрированных клиентов
[
{
"id": "network-folder-papers",
"title": "Сетевая папка - научные статьи",
"token": "mK8XoAb3GwICWZ4inj00Ax?lO_ZFRzshyTKQyH8j?COulcQFLnzcj6RczsSvBUYn",
"allowFiles": true,
"data": null,
"blocked": false
}
]
Возвращает полный перечень зарегистрированных клиентов.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Input: -
- Output: List[Client]
| Команда | Путь |
|---|---|
| integration_ListClients | HTTP POST /v1/client/list |
UpdateClient (Integration)
На входе ID обновляемого клиента и новые свойства
{
"id": "network-folder-papers",
"title": "Сетевая папка (научные статьи)",
"allowFiles": true,
"data": null,
"blocked": false
}
На выходе Boolean (признак успешности исполнения)
true
Обновляет данные клиента.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
- Input: UpdateClientDTO
- Output: Boolean
| Команда | Путь |
|---|---|
| integration_UpdateClient | Kafka Topic "integration_commands" |
RefreshClientToken (Integration)
На входе ID клиента, для которого требуется перегенерировать токен
"network-folder-papers"
На выходе Boolean (признак успешности исполнения)
true
Повторно генерирует токен клиента.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
- Input: String
- Output: Boolean
| Команда | Путь |
|---|---|
| integration_RefreshClientToken | Kafka Topic "integration_commands" |
AllowEntityType (Integration)
На входе ID клиента и ID типа данных, которые требуется связать
{
"clientId": "network-folder-papers",
"entityTypeId": "paper"
}
На выходе Boolean (признак успешности исполнения)
true
Дает указанному клиенту право создавать, редактировать и удалять данные указанного типа.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
- Input: ClientToEntityTypeIds
- Output: Boolean
| Команда | Путь |
|---|---|
| integration_AllowEntityType | Kafka Topic "integration_commands" |
DisallowEntityType (Integration)
На входе ID клиента и ID типа данных, для которых требуется удалить связь
{
"clientId": "network-folder-papers",
"entityTypeId": "paper"
}
На выходе Boolean (признак успешности исполнения)
true
Запрещает указанному клиенту создавать, редактировать и удалять данные указанного типа.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
- Input: ClientToEntityTypeIds
- Output: Boolean
| Команда | Путь |
|---|---|
| integration_DisallowEntityType | Kafka Topic "integration_commands" |
ListEntityTypes (Integration)
Входные данные отсутствуют
На выходе список доступных типов данных
[
{
"id": "paper",
"title": "Бумага",
"description": ""
},
{
"id": "document",
"title": "Документ",
"description": ""
}
]
Возвращает полный перечень доступных типов данных.
Сервис запрашивает список типов данных из сервиса модели данных с определенной периодичностью, указанной в конфиге
INTEGRATION_ENTITY_TYPES_REFRESH_RATE,
поэтому при добавлении нового типа в сервис модели данных, в сервисе интеграций он может появиться не сразу.
В случае необходимости, список доступных типов данных можно обновить принудительно при
помощи соответствующей команды.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Input: -
- Output: List[EntityType]
| Команда | Путь |
|---|---|
| integration_ListEntityTypes | HTTP POST /v1/entityType/list |
RefreshEntityTypes (Integration)
Входные данные отсутствуют
На выходе Boolean (признак успешности исполнения)
true
Вызывает принудительное обновление списка доступных типов данных (обычно список обновляется по расписанию в указанные в INTEGRATION_ENTITY_TYPES_REFRESH_RATE промежутки времени).
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
- Input: -
- Output: Boolean
| Команда | Путь |
|---|---|
| integration_RefreshEntityTypes | Kafka Topic "integration_commands" |
ListEntityTypesForClient (Integration)
На входе ID клиента
"MarkerExternalClient"
На выходе список доступных типов данных для указанного клиента
[
{
"id": "DocForOwTkexzNTZeyY995aWgmAg",
"title": "Документ для проекта с ID 3b04e47b-1ccd-4d97-b263-df7969682602",
"description": ""
},
{
"id": "DocForv0xczPbGTPiWaP_U8P1uBg",
"title": "Документ для проекта с ID bf4c5ccc-f6c6-4cf8-9668-ffd4f0fd6e06",
"description": ""
}
]
Возвращает перечень доступных для клиента типов данных.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Input: String
- Output: List[EntityType]
| Команда | Путь |
|---|---|
| integration_ListEntityTypesForClient | HTTP POST /v1/entityType/listForClient |
Модели сервиса (Integration)
Client (Integration)
Описание зарегистрированного клиента
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | string | Да | Код клиента |
| title | string | Да | Наименование клиента |
| token | string | Да | Токен доступа для внешнего апи |
| allowFiles | boolean | Да | Разрешено ли клиенту загружать файлы |
| data | json | Нет | Дополнительные данные в свободном формате |
| blocked | boolean | Да | Признак полной блокировки клиента |
CreateClientDTO (Integration)
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | string | Да | Код клиента |
| title | string | Да | Наименование клиента |
| allowFiles | boolean | Да | Разрешено ли клиенту загружать файлы |
| data | json | Нет | Дополнительные данные в свободном формате |
UpdateClientDTO (Integration)
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | string | Да | Код клиента |
| title | string | Да | Наименование клиента |
| allowFiles | boolean | Да | Разрешено ли клиенту загружать файлы |
| data | json | Нет | Дополнительные данные в свободном формате |
| blocked | boolean | Да | Признак блокировки клиента |
EntityType (Integration)
Описание известного типа данных
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | string | Да | Код типа данных |
| title | string | Да | Название типа данных |
| description | string | Да | Описание типа данных |
ClientToEntityTypeIds (Integration)
Описание связи клиентов и типов данных для использования в командах
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| clientId | string | Да | Код клиента |
| entityTypeId | string | Да | Код типа данных |
Intelligent-plugin-core: хранилище общей логики плагинов
Intelligent Plugin Core это отдельный sbt-project, в который были вынесены логика и сущности, переиспользуемые отдельными плагинами.
Модели IntelligentPluginCore (models)
PluginConstantRegistrar (plugin)
Плагины регистрируются в сервисе TechConstants не как отдельные сервисы, а как константы, относящиеся к сервису Indexation. PluginConstantRegistrar содержит в себе логику, осуществляющую этот процесс регистрации плагинов в сервисе TechConstants.
BaseFlow (plugin)
Трейт, содержащий в себе API запуска обработки kafka-сообщений, поступающих плагину.
Трейт имеет две реализации: Flow и FlowLamp2, которые в процессе обработки обращаются к Lamp1 и Lamp2 соответственно.
Обе эти реализации выполняют следующие шаги обработки:
1. Плагин ожидает получать из топика consumerConfig.topic сообщения, содержащие json-представления модели StepProgress. Происходит конвертация этого json-а в инстанс StepProgress.
2. После этого для каждого идентификатора файла(progress.files), генерируется EntityFileSemanticId, включающий в себя привязку к конкретной сущности(progress.entityObject).
3. Затем плагин отправляет в Lamp запрос, содержащий сгенерированный EntityFileSemanticId, чтобы найти файлы, которые имеют пересечение с текущим.
4. LampResponseProcessor, определяемый в каждом плагине отдельно, преобразует ответ Lamp в список пар из EntityFileSemanticId и некоторой меры схожести файлов(measure). Мера определяет то, насколько файл, соответствующий полученному id, похож на файл соответствующий id, переданному в запросе. По полученному списку производится фильтрация - остаются идентификаторы только тех файлов, мера которых превышает linkConfig.measureThreshold. Так мы получаем все forwardLinks, которые нужно создать.
5. Если индексация, вызвавшая обращение к плагину, была порождена событием в data-model, то для каждого EntityFileSemanticId, возвращенного Lamp-ом на предыдущем шаге, выполняются действия шагов 3 и 4. Пересечения, найденные таким образом, называются backlinks.
6. Если при обращении к Lamp во время поиска backlinks на шаге 5, происходит ошибка, то после того, как количество ретраев превысит максимально возможное, то:
- FlowLamp2: будет совершена асинхронная попытка переиндексации файла сущности, отправка EntityFileSemanticId которого в Lamp вызывает ошибку. Плагин при этом продолжит дальнейшее исполнение алгоритма обработки, не дожидаясь этой переиндексации.
- Flow: будет выброшено исключение и обработка всего батча будет неуспешной и соответствующие ссылки не будут созданы.
7. Множество (forwardLinks ++ backLinks) делится на батчи, которые отправляются в data-model во входных данных команды createObjectsLinks для создания
соответствующей связи между объектами.
В поле additional при этом сохраняется json-object {linkConfig.measureName -> measure}.
8. В топик consumerConfig.progressTopic отправляется либо StepProgress (тот же, что и поступил на вход), либо FailedStepProgress в качестве маркера об окончании обработки шага plugin для данного stepProgress.
Backlinks reindexation (plugin)
- Происходит обращение к data-model, чтобы по EntityFileSemanticId файла сущности получить саму сущность для переиндексации.
- В топик consumerConfig.indexationEntityEventObjectTopic отправляется сообщение, содержащее TypedEvent[EntityObjectEvent] с PluginBackLinksAdditionalData, которое порождает искусственную индексацию файла сущности с шагами Lamp и Plugin. При этом обработка искусственного шага Plugin для такого файла исключает поиск собственных backlinks (чтобы не попасть в цикл).
TypedEvent[EntityObjectEvent] (plugin)
DTO для стандартных событий
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
| eventType | String | Да | Тип события (информация для более удобной фильтрации) | |
| payloadType | String | Да | Тип объекта, который передается | |
| payloadId | String | Да | Id объекта, который передается. Может содержать идентификатор объекта из сервиса, который отправляет события | |
| payload | EntityObjectEvent | Да | Передаваемый объект |
LampResponseProcessor (plugin)
Содержит в себе один метод processResponse, который принимает на вход сообщение из Lamp и возвращает
Option[Seq[LinkItem]]
LinkItem (plugin)
| Поле | Тип | Обязательное | Значение по умолчанию | Описание | Ограничения |
|---|---|---|---|---|---|
| id | EntityFileSemanticId | Да | Нет | Семантический идентификатор файла сущности | |
| measure | Float | Да | Нет | Мера |
ConsumerConfig (plugin)
| Поле | Тип | Обязательное | Значение по умолчанию | Описание | Ограничения |
|---|---|---|---|---|---|
| topic | String | Да | Нет | Топик, в который поступает StepProgress на обработку | |
| group | String | Да | Нет | Группа консьюмера | |
| progressTopic | String | Да | Нет | Топик, в который плагин пишет об окончании обработки |
LinkConfig (plugin)
| Поле | Тип | Обязательное | Значение по умолчанию | Описание | Ограничения |
|---|---|---|---|---|---|
| lampParametersOperation | String | Да | Нет | Название операции, которое в качестве параметра передается в Lamp | |
| lampRoute | String | Да | Нет | Рут Lamp, к которому обращается плагин с запросом поиска пересекающихся файлов | |
| linkType | String | Да | Нет | Тип ссылки, создаваемой плагином в data-model | |
| linkOwner | String | Да | Нет | Link owner ссылки, создаваемой плагином в data-model | |
| measureName | String | Да | Нет | measureName, которое будет использовано в объекте, лежащем в поле additionalData при создании ссылки в data-model | |
| measureThreshold | Float | Да | Нет | Пороговое значение measure. Ссылки создаются только между документами, мера схожести между которыми больше или равна этому значению | |
| linkItemsPerKafkaMessage | Int | Да | Нет | Размер батча для запроса к data-model c командой createObjectsLinks |
EntityFileSemanticId (plugin)
| Поле | Тип | Обязательное | Значение по умолчанию | Описание | Ограничения |
|---|---|---|---|---|---|
| entityType | EntityTypeId | Да | Нет | Тип сущности, к которой относится файл | |
| entityId | String | Да | Нет | Идентификатор сущности, к которой относится файл | |
| fieldId | String | Да | Нет | Идентификатор поля сущности, в котором хранится файл | |
| fileId | String | Да | Нет | Идентификатор файла |
FailedStepProgress (plugin)
| Поле | Тип | Обязательное | Значение по умолчанию | Описание | Ограничения |
|---|---|---|---|---|---|
| indexationProgress | StepProgress | Да | Нет | StepProgress, который завершился ошибкой | |
| message | String | Да | Нет | Message ошибки, произошедшей во время обработки StepProgress | |
| stackTrace | String | Нет | Нет | StackTrace ошибки, произошедшей во время обработки StepProgress |
StepProgress (plugin)
В плагинах поле stepProgress.step всегда будет содержать Step c payload Plugin, то есть шаг сервиса индексации, который описывает обращение к плагину (тип stepPayload = Plugin). В остальном аналогично любому другому StepProgress.
JWT: библиотека для работы с JWT
Библиотека предоставляет вспомогательные методы для создания и работы с JWT.
TODO: описать JwtAuthenticatorPac4j, JwtPac4j, JwtClaim и как их использовать
Structs (jwt)
JwtInvalidationId (jwt)
Идентификатор для правила инвалидации JwtInvalidation. Может быть либо "global" - для всех пользователей, либо UserId - для конкретного пользователя. Соответствует типу String.
JwtInvalidation (jwt)
Параметры для хранилища сертификатов (Java key store)
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
| id | JwtInvalidationId | Да | Идентификатор правила инвалидации JWT | Либо "global" - для всех пользователей, либо UserId - для конкретного пользователя |
| condition | string | Да | Правило инвалидации JWT | Формат должен совпадать с JwtInvalidationCondition |
JwtInvalidationCondition (jwt)
Формат правила для инвалидации
- всех JWT выданных до определенного времени: "1700544874", где 1700544874 - это Unix timestamp (milliseconds)
Lamp-client: cервис интеграции с LAMP
В сервисе реализованы следующие команды
Общее описание архитектуры сервиса клиента LAMP
Сервис позволяет общаться с LAMP через Verdi команду, ответы LAMP упаковываются в файлы, и в качестве результата выполнения команды создается ссылка на файл с ответом LAMP
Конфигурирование сервиса клиента LAMP
Требования к запуску сервиса клиента LAMP
Запуск сервиса осуществляется локально через sbt, на стенде в docker на jvm. Для корректной минимальной работы сервиса требуется обязательное подключение к Kafka, Consul, MinIO и Remote Lamp Client Для нормальной работы сервису дополнительно требуется окружение Verdi: CommandStatus и ApiGateway.
Список переменных окружения сервиса клиента LAMP
| Переменная | Тип | Обязательная | Значение по умолчанию | Описание |
|---|---|---|---|---|
| CONSUMER_TOPIC | string | нет | lampClient | Название кафка-топика для запросов в LAMP |
| CONSUMER_GROUP | string | нет | lampClient | Имя группы-консьюмеров сервиса клиента LAMP |
| VERDI_CONSUL | url string | да | http://localhost:8500 | Адрес Consul |
| VERDI_CONSUL_AUTH_USER | string | нет | "" | Название учетной записи Сonsul. Если название не указано, то настройки авторизации не будут применены. |
| VERDI_CONSUL_AUTH_PASSWORD | string | нет | "" | Пароль учетной записи Сonsul. |
| VERDI_KAFKA_AUTH_PRINCIPAL | string | нет | "" | Principal учетной записи Kafka в Kerberos(в случае соединения с kafka через Kerberos). |
| VERDI_KAFKA_AUTH_KEYTAB_PATH | string | нет | "" | Путь до keytab-файла(в случае соединения с kafka через Kerberos). |
| VERDI_KAFKA_ADDRESS | string | да | localhost:9092 | Адрес брокера Kafka. |
| VERDI_KAFKA_TOPIC | string | нет | commandevents | Название кафка-топика для отправки сообщений со статусами выполняемых команд. ОБЯЗАТЕЛЬНО должно соответствовать названию этого топика в сервисе статуса команд. |
| VERDI_KAFKA_AUTH_USER | string | нет | "" | Название учетной записи Kafka. Если название не указано, то настройки авторизации не будут применены. |
| VERDI_KAFKA_AUTH_PASSWORD | string | нет | "" | Пароль учетной записи Kafka. |
| VERDI_KAFKA_AUTH_TRUSTSTORE_LOCATION | string | нет | "" | Путь до хранилища сертификатов (Java key store). Если путь не указан, то сертификат применяться не будет. |
| VERDI_KAFKA_AUTH_TRUSTSTORE_PASSWORD | string | нет | "" | Пароль к хранилищу сертификатов. |
| VERDI_KAFKA_AUTH_MODE | string | нет | "" | Режим аутентификации: static - одна учетная запись на все запросы, mapping - учетная запись зависит от запроса |
| VERDI_KAFKA_AUTH_CONFIG | string | нет | "" | Настройки для аутентификации: если AuthMode = mapping, то необходим JSON с List[KafkaAuthConfig]. Переменная соответствует полю authConfig из KafkaAuthSettings. |
| VERDI_KAFKA_AUTH_CACHE_SIZE | int | нет | Максимальный размер кеша для Kafka producer (количество активных соединений). | |
| VERDI_KAFKA_AUTH_CACHE_TTL | duration string | нет | Время жизни Kafka producer в кеше. | |
| VERDI_KAFKA_CONNECTION_CHECK_TEST_MESSAGES_INTERVAL | duration string | нет | 4 minutes | Применяется только для producer-ов со способом аутентификации kerberos. Интервал отправки тестовых сообщений кафки в топик connectionCheck.testMessagesTopicName. Тестовые сообщения (null, service producer test) отправляются регулярно с этим интервалом. |
| VERDI_KAFKA_CONNECTION_CHECK_INTERVAL | duration string | нет | 60 seconds | Применяется только для producer-ов со способом аутентификации kerberos. Интервал проверки того, сколько тестовых сообщений было отправлено за данный период. Если количество сообщений за этот период равно количеству сообщений за прошлый период, то начинается отсчет периода без сообщений. |
| VERDI_KAFKA_CONNECTION_CHECK_FAILED_AFTER_INTERVAL | duration string | нет | 5 minutes | Применяется только для producer-ов со способом аутентификации kerberos. Максимальная продолжительность периода без успешно отправленных тестовых сообщений. По ее достижении сервис будет объявлен больным. |
| VERDI_HOST | string | да | localhost | Хост, публикуемый в ServiceDiscovery. По нему на данный сервис будут обращаться другие через HTTP. Указанный адрес должен быть виден другим сервисам. Пример: имя kubernetes/docker_swarm service |
| VERDI_TTL | duration string | нет | 30 seconds | Период после последней отправки health check, в течение которого ServiceDiscovery считает данный сервис живым. |
| VERDI_HEALTH_CHECK | duration string | нет | 10 seconds | Периодичность отправки health check в ServiceDiscovery |
| VERDI_COMMAND_STORAGE_UPDATE_PERIOD | duration string | нет | 1 minutes | Время кэширования данных по командам из CommandDiscovery |
| VERDI_SERVICE_DISCOVERY_UPDATE_PERIOD | duration string | нет | 30 seconds | Время кэширования данных по сервисам из ServiceDiscovery |
| VERDI_ALLOW_INTERNAL_COMMANDS | bool | нет | true | Можно ли сервису отправлять внутрисистемные команды |
| VERDI_CONSUL_CONNECTION_MAX_RETRY | int | нет | 5 | Максимальное количество попыток подключений к Consul |
| VERDI_CONSUL_CONNECTION_RETRY_DELAY | duration string | нет | 1 seconds | Таймаут между неудачными попытками подключения к Consul |
| FS_URI | url string | да | http://localhost:9002 | Адрес S3 файлового хранилища minio |
| FS_ACCESS_KEY_ID | string | да | admin | Идентификатор доступа к minio |
| FS_SECRET_ACCESS_KEY | string | да | admin | Секретный ключ доступа к minio |
| FS_UPLOAD_PARALLELISM | int | нет | 10 | Параллелизм загрузки файлов в minio |
| FS_AUTH_MODE | string | нет | static | Режим аутентификации: static - одна учетная запись на все запросы, mapping - учетная запись зависит от запроса |
| FS_AUTH_CONFIG | string | нет | "" | Настройки для аутентификации: если AuthMode = mapping, то необходим JSON с List[FSBucketConfig] соответствует полю authConfig FSConfigRep |
| FS_CACHE_SIZE | int | нет | 1 | Максимальный размер кеша клиентов для хранилища файлов (количество активных соединений). |
| FS_CACHE_TTL | duration string | нет | Время жизни клиента в кеше | |
| FS_RETRY_ATTEMPTS | int | нет | 5 | Количество ретраев, которое будет произведено в случае Exception-а в операции FSClient-а и при вычитывании стрима в get операциях FSClient-а. |
| FS_RETRY_DELAY | duration string | нет | 10 millis | Задержка между ретраями операций FSClient-а. |
| FS_ZIO_SHORT_MESSAGE_MODE | boolean | нет | false | Флаг включения режима сохранения ошибок работы с файловым хранилищем в сервисе журналирования nestor. При включении режима ошибки в логах будут отображаться в сокращенном формате: Short zio message mode. ExceptionType: ТИП ОШИБКИ, Exception id: 'СГЕНЕРИРОВАННЫЙ UUID' added to journal. Указанный id будет фиксироваться в event записи nestor'а в поле data.id |
| LAMP_USE_VERSION_2 | bool | нет | false | Использовать ли LAMP2 (true) или LAMP1 (false) |
| LAMP_BUFFER_SIZE | int | нет | 10 | Буфер на отправку сообщений в клиент LAMP |
| LAMP_RECONNECT_SCHEDULE | schedule string | нет | I(2 seconds) | Стратегия переподключения клиента LAMP (формат см. lamp.transport.model.Schedule) |
| LAMP_HOST | url string | да | lamp-dev.dev.embedika.ru | Адрес клиента LAMP |
| LAMP_PORT | int | да | 443 | Порт клиента LAMP |
| LAMP_TLS | bool | да | true | Признак защищенного подключения к LAMP |
| LAMP_TLS_CERTIFICATE | string | нет | "" | Путь файла с сертификатом для подключения к LAMP |
| LAMP_TLS_PRIVATE_KEY | string | нет | "" | Путь файла с приватным ключем для подключения к LAMP |
| LAMP_TLS_ROOT_TRUSTED_CERTS | string | нет | "" | Путь файла с центром сертификации (Certification Authority, CA) для подключения к LAMP |
| LAMP_TIMEOUT | duration string | нет | 150 second | Таймаут отправки сообщения и получения результатов через клиент LAMP |
| APP_RESULT_BUCKET | string | нет | processing | S3 bucket в который сохраняются ответы LAMP |
| APP_ROUTE_MAPPING | string | нет | Plagiarism:plagiarism_route;Similarity:faiss_route | Маппинг сервисных имен LAMP роутов с реальными LAMP роутами. Формат indexation1:route1;indexation2:route2. Список роутов см. LampRoute |
| VERDI_COMMANDS_HTTP_RETRY_ATTEMPTS | int | нет | 5 | Поле attempts из RetrySettings |
| VERDI_COMMANDS_HTTP_RETRY_DELAY | duration string | нет | "5 seconds" | Поле delay из RetrySettings |
| VERDI_COMMANDS_HTTP_RETRY_KIND | string | нет | "OnSomeExceptions(ConnectException)" | CommandResultRetryConditionKind |
| SERVER_PORT | int | да | 8080 | Порт для HttpListener |
| JOURNAL_MODE | string | нет | WriteToJournal |
Режим журналирования Nestor. Допустимые значения: WriteToJournal (Отправка в сервис журналирования), WriteToTopic (Отправка события в очередь) |
| JOURNAL_TOPIC | string | да, если переменная JOURNAL_MODE = WriteToTopic |
"" | Название очереди журналирования. Для режима WriteToJournal значение игнорируется. |
Модели сервиса клиента LAMP
LampQuery
Описание запроса к LAMP с файлами
| Название поля | Тип | Описание |
|---|---|---|
| data | Either[String, StoredFile] | Данные запроса - это либо ссылка на файл, либо строка |
| route | String | LAMP роут |
| parameters | Option[JsonObject] | Опциональные параметры для запроса |
LampQueryJson
Описание запроса к LAMP с json
| Название поля | Тип | Описание |
|---|---|---|
| data | String | Строковые данные запроса |
| route | String | LAMP роут |
| parameters | Option[JsonObject] | Опциональные параметры для запроса |
Имена сервисных LAMP роутов
Доступные на данный момент роуты: Plagiarism, Similarity, Extend
Команды сервиса клиента LAMP
lampQuery-command
Запрос в LAMP для больших данных
На входе ссылка на файл с данными и роут
{
"data": "temp/8df98571-bb81-4ca6-8fef-0776ea18da50",
"route": "Plagiarism"
}
В результате ссылка на файл с ответом от LAMP
"processing/8df98571-bb81-4ca6-8fef-0776ea18da50"
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: LampQuery
- На выходе: StoredFile
lampQueryJson-command
Запрос в LAMP
На входе строковые данные, роут и параметры запроса в Lamp
{
"data":"nacl",
"route":"Extend",
"parameters": {
"k_nearest": "100",
"pos_accept": "noun,adj,verb"
}
}
В результате json с ответом от Lamp
{"synonyms":[{"lemma":"толуол","pos":"NOUN","weight":0.6470648050308228},{"lemma":"mgcl","pos":"NOUN","weight":0.6426058411598206}]}
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: LampQueryJson
- На выходе: Json
License-models: модели данных для работы с лицензией
Библиотека предоставляет вспомогательные методы для чтения файла лицензии и структуру с данными лицензии.
Модели данных (license-model)
LicenseDTO (license-model)
Пример лицензии, предоставляющей доступ к разделу "Лицензии".
kind=Prod
expiredAt:LONG=8050167349000
globalSessionsLimit:INT=-1
sessionsLimitPerUser:INT=-1
sessionWatchSec:INT=300
allowedActions=UIStorage_ViewList,ViewLicense
activeUserLimit:INT=-1
description=Лицензия для доступа к разделу "Лицензии"
Данные выданной лицензии.
| Поле | Тип | Обязательное | Описание | Значение по умолчанию |
|---|---|---|---|---|
kind |
LicenseKind | Нет | Вид лицензии | "Prod" |
expiredAt |
TimeStamp | Нет | Время, когда лицензия истекает, в миллисекундах | 0 |
globalSessionsLimit |
Int | Нет | Глобальное ограничение на количество сессий: меньше 0 = "без ограничений" | -1 |
sessionsLimitPerUser |
Int | Нет | Ограничение на количество сессий для одного пользователя: меньше 0 = "без ограничений" | -1 |
sessionWatchSec |
Int | Нет | Время в секундах, в течении которого сессия учитывается в подсчете доступного лимита: должно быть >= 0, ноль будет обрабатываться также как и любое другое значение | 300 |
allowedActions |
String | Нет | Строка в формате: список действий (List[String]), которые разрешены для выполнения под лицензией (другие - автоматически запрещены) | [] |
privilegedEmails |
String | Нет | Строка в формате: список email-ов привилегированных пользователей через запятую (List[UserEmail]) | [] |
activeUserLimit |
Int | Нет | Глобальное ограничение на количество активированных пользователей: меньше 0 - "без ограничений" | -1 |
jwtLifeTime |
Option[Int] | Нет | Время действия токена JWT в секундах (если есть, то перекрывает значение переменной MON_JWT_LIFETIME): должно быть >= 0, ноль будет обрабатываться также как и любое другое значение | None |
description |
Option[String] | Нет | Описание лицензии в свободном формате | None |
Примеры формата:
allowedActions=action1,action2privilegedEmails=email1,email2
LicenseKind (license-model)
Вид лицензии. Соответствует типу String. Возможные значения: Prod, Dev.
Расширения liquibase plugin
PidLockDatabaseChangeLogGenerator
Расширение LockDatabaseChangeLogGenerator записывает допольнительные данные о pid сервиса в стоблец LOCKEDBY таблицы с liquibase lock.
Работает только с PostgreSQL, используется таблицу pg_stat_activity, и функцию pg_backend_pid().
ReleasingLockService
Расширение StandardLockService проверяет есть ли активное подключение к базе по pid из столбца LOCKEDBY, если нет, то снимает lock. Требует PidLockDatabaseChangeLogGenerator. Работает только с PostgreSQL, используется таблицу pg_stat_activity, и функцию pg_backend_pid().
Marsu: cервис для тестирования
Marsu, в переводе с финского, означает "морская свинка".
Сервис предназначен для тестирования работоспособности команд.
Команды могут приходить как по HTTP, так и через Kafka в топик marsu_commands.
Конфигурирование Marsu
Список переменных окружения для сервиса Marsu
| Переменная | Тип | Обязательная | Значение по умолчанию | Описание |
|---|---|---|---|---|
MARSU_HTTP_HOST |
string | Нет | 0.0.0.0 |
Хост для HttpListener. |
MARSU_HTTP_PORT |
int | Нет | 8192 |
Порт для HttpListener. |
MARSU_KAFKA_SERVERS |
string | Нет | localhost:9092 |
Адрес Kafka. |
MARSU_KAFKA_TOPIC |
string | Нет | marsu_commands |
Название топика для команд. |
MARSU_KAFKA_CONSUMER_GROUP |
string | Нет | marsu_consumer_group |
Название consumer-группы для чтения команд. |
MARSU_KAFKA_COMMANDEVENT_TOPIC |
string | Нет | commandevents |
Название топика для отправки сообщений со статусом команд. |
MARSU_KAFKA_PARTITIONS |
int | Нет | 10 |
Количество партиций в топике команд. |
MARSU_KAFKA_CONSUMER_RESTART_MIN_BACKOFF |
duration string | Нет | 1 second |
Минимальная задержка перед перезапуском. |
MARSU_KAFKA_CONSUMER_RESTART_MAX_BACKOFF |
duration string | Нет | 30 seconds |
Максимально возможная задержка перед перезапуском. |
MARSU_KAFKA_CONSUMER_RESTART_RANDOM_FACTOR |
float | Нет | 0.2 |
Коэффициент величины дополнительной случайной задержки (jitter) относительно основной задержки: 0.0 - без случайной задержки, 1.0 - до 100% задержки. Если после умножения задержки на MARSU_KAFKA_CONSUMER_RESTART_RANDOM_FACTOR получится меньше 1 миллисекунды, то jitter будет приравнен к нулю. |
MARSU_KAFKA_CONSUMER_RESTART_MAX_RESTARTS |
int | Нет | 5 |
Максимальное количество перезапусков в заданный период времени. После превышения этого числа сервис будет объявлен больным. Все рестарты для каждого отдельного сообщения увеличивают и общий счетчик рестартов консьюмера, поэтому при использовании MARSU_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS нужно указывать MARSU_KAFKA_CONSUMER_RESTART_MAX_RESTARTS > MARSU_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS или не указывать MARSU_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS совсем. |
MARSU_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS |
int | Нет | 2 |
Максимальное количество раз, которое консьюмер перезапустится с неизменной очередью сообщений (в пределах MARSU_KAFKA_CONSUMER_RESTART_MAX_RESTARTS_WITHIN), прежде чем проигнорировать сообщение, на котором происходит ошибка (Указано количество рестартов, а не прочтений. Если MARSU_KAFKA_CONSUMER_RESTART_MAX_RESTARTS = 2, то ошибочное сообщение будет обработано 3 раза, после чего произойдет 3ий рестарт и оно будет проигнорировано). Если указать 0, то перезапуск произойдет, но сообщение будет обработано только в первый раз, когда произошла ошибка. Если указать значение меньше 0, то перезапуски все равно будут происходить, но игнорирование сообщений, вызывающих ошибку, будет отключено. |
MARSU_KAFKA_CONSUMER_PER_MESSAGE_RESTART_CACHE_SIZE |
int | Нет | 100 |
Для каждого сообщения счетчик перепрочтений хранится в кэше. Максимальное количество значений в этом кэше. |
MARSU_KAFKA_CONSUMER_PER_MESSAGE_RESTART_CACHE_TTL |
duration string | Нет | 5 minutes |
Для каждого сообщения счетчик перепрочтений хранится в кэше. Максимальное время жизни элемента в этом кэше. В случае отсутствия значения время жизни элемента не будет ограничено. |
MARSU_KAFKA_CONSUMER_RESTART_MAX_RESTARTS_WITHIN |
duration string | Нет | 5 minutes |
Период времени для ограничения перезапусков. |
MARSU_KAFKA_CONSUMER_POLL_TIMEOUT |
duration string | нет | 10 milliseconds |
timeout запроса poll для kafka consumer |
MARSU_KAFKA_CONSUMER_POLL_INTERVAL |
duration string | нет | 50 milliseconds |
интервал между запросами poll для kafka consumer |
MARSU_KAFKA_CONSUMER_PROPS |
string | нет | "max.poll.records=2500;max.partition.fetch.bytes=3145728" | дополнительные параметры для kafka consumer в формате "key1=value1;key2=value2" |
MARSU_KAFKA_PRODUCER_PROPS |
string | нет | "batch.size=3145728;linger.ms=5;max.request.size=3145728" | дополнительные параметры для kafka producer в формате "key1=value1;key2=value2" |
MARSU_KAFKA_CONSUMER_PARALLELISM |
int | нет | 10 | параллелизм обработки сообщений в одной партиции |
MARSU_KAFKA_AUTH_USER |
string | Нет | "" | Название учетной записи Kafka. Если название не указано, то настройки авторизации не будут применены. |
MARSU_KAFKA_AUTH_PASSWORD |
string | Нет | "" | Пароль учетной записи Kafka. |
MARSU_KAFKA_AUTH_PRINCIPAL |
string | Нет | "" | Principal учетной записи Kafka в Kerberos(в случае соединения с kafka через Kerberos). |
MARSU_KAFKA_AUTH_KEYTAB_PATH |
string | Нет | "" | Путь до keytab-файла(в случае соединения с kafka через Kerberos). |
MARSU_KAFKA_AUTH_TRUSTSTORE_LOCATION |
string | Нет | "" | Путь до хранилища сертификатов (Java key store). Если путь не указан, то сертификат применяться не будет. |
MARSU_KAFKA_AUTH_TRUSTSTORE_PASSWORD |
string | Нет | "" | Пароль к хранилищу сертификатов. |
MARSU_KAFKA_AUTH_MODE |
string | Нет | static |
Режим аутентификации: static - одна учетная запись на все запросы, mapping - учетная запись зависит от запроса. |
MARSU_KAFKA_AUTH_CONFIG |
string | Нет | "" | Настройки для аутентификации: если AuthMode = mapping, то необходим JSON с List[KafkaAuthConfig]. Переменная соответствует полю authConfig из KafkaAuthSettings. |
MARSU_KAFKA_AUTH_CACHE_SIZE |
int | Нет | Максимальный размер кеша для Kafka producer (количество активных соединений). | |
MARSU_KAFKA_AUTH_CACHE_TTL |
duration string | Нет | Время жизни Kafka producer в кеше. | |
MARSU_KAFKA_CONNECTION_CHECK_TEST_MESSAGES_INTERVAL |
duration string | Нет | 4 minutes |
Применяется только для producer-ов со способом аутентификации kerberos. Интервал отправки тестовых сообщений кафки в топик connectionCheck.testMessagesTopicName. Тестовые сообщения (null, service producer test) отправляются регулярно с этим интервалом. |
MARSU_KAFKA_CONNECTION_CHECK_INTERVAL |
duration string | Нет | 60 seconds |
Применяется только для producer-ов со способом аутентификации kerberos. Интервал проверки того, сколько тестовых сообщений было отправлено за данный период. Если количество сообщений за этот период равно количеству сообщений за прошлый период, то начинается отсчет периода без сообщений. |
MARSU_KAFKA_CONNECTION_CHECK_FAILED_AFTER_INTERVAL |
duration string | Нет | 5 minutes |
Применяется только для producer-ов со способом аутентификации kerberos. Максимальная продолжительность периода без успешно отправленных тестовых сообщений. По ее достижении сервис будет объявлен больным. |
MARSU_CONSUL_ADDR |
string | Нет | http://localhost:8500 |
Адрес Consul. |
MARSU_DISCOVERABLE_ID |
string | Нет | marsu_instance |
Id сервиса в ServiceDiscovery. |
MARSU_DISCOVERABLE_NAME |
string | Нет | Marsu |
Имя сервиса в ServiceDiscovery. |
MARSU_DISCOVERABLE_HOST |
string | Нет | localhost |
Хост, публикуемый в ServiceDiscovery. |
MARSU_DISCOVERABLE_PORT |
int | Нет | Порт, публикуемый в ServiceDiscovery. | |
MARSU_DISCOVERABLE_LIVETIME |
duration string | Нет | 2 minutes |
Период после отправки health check, в течение которого ServiceDiscovery считает сервис живым. |
MARSU_DISCOVERABLE_HEALTHPASS |
duration string | Нет | 1 minute |
Периодичность отправки health check в ServiceDiscovery. |
MARSU_AKKA_HTTP_CLIENT_MAXCON |
int | Нет | 512 |
Максимальное число одновременных исходящих HTTP-соединений. |
MARSU_AKKA_HTTP_CLIENT_MAXREQ |
int | Нет | 1024 |
Максимальное число одновременных исходящих HTTP-запросов. |
MARSU_AKKA_HTTP_SERVER_MAXCON |
int | Нет | 1024 |
Максимальное число одновременных входящих HTTP-соединений. |
MARSU_INTERNALCMD_ALLOW |
bool | Нет | false |
Можно ли сервису отправлять внутрисистемные команды. |
MARSU_SENDERLIB_COMMANDS_CACHE_UPDATEPERIOD |
duration string | Нет | 10 minutes |
Время кэширования данных по командам из CommandDiscovery. |
MARSU_SENDERLIB_SERVICES_CACHE_UPDATEPERIOD |
duration string | Нет | 30 seconds |
Время кэширования данных по сервисам из ServiceDiscovery. |
MARSU_SENDERLIB_COMMANDS_HTTP_RETRY_ATTEMPTS |
int | Нет | 5 |
Поле attempts из RetrySettings. |
MARSU_SENDERLIB_COMMANDS_HTTP_RETRY_DELAY |
duration string | Нет | 5 seconds |
Поле delay из RetrySettings. |
MARSU_SENDERLIB_COMMANDS_HTTP_RETRY_KIND |
string | Нет | OnSomeExceptions(ConnectException) |
CommandResultRetryConditionKind. |
Команды сервиса Marsu
Список реализованных в сервисе команд.
| Назначение команды | Имя вызова команды |
|---|---|
| Отправка тестовой команды по HTTP | marsu_http_Delayable |
| Отправка тестовой команды по KAFKA | marsu_kafka_Delayable |
http_Delayble (Marsu)
Получаем запрос о длительности выполнения команды
{
"delayMs": 1000
}
Возвращаем полученный запрос
{
"delayMs": 1000
}
Команда для проверки длительности выполнения команд. Команда ничего не делает, только ожидает указанное временя в мс.
Имя команды для вызова: marsu_http_Delayable.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: DelayableCommand
- На выходе: DelayableCommand
kafka_Delayble (Marsu)
Получаем запрос о длительности выполнения команды
{
"delayMs": 1000
}
Возвращаем полученный запрос
{
"delayMs": 1000
}
Команда для проверки длительности выполнения команд. Команда ничего не делает, только ожидает указанное временя в мс.
Имя команды для вызова: marsu_kafka_Delayable.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: DelayableCommand
- На выходе: DelayableCommand
Модели сервиса Marsu
DelayableCommand (Marsu)
Модель для настроек задержек команд
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
delayMs |
long | Да | Длительность выполнения команды в мс |
Mon-client: библиотека для работы с сервисом Mon
Библиотека предоставляет интерфейс и реализацию клиента для сервиса Mon.
Публикуется вместе с подпроектом mon-core/domain, так как использует сущности из этого подпроекта.
Подключение (mon-client)
Для того чтобы использовать библиотеку mon-client, нужно добавить зависимость
"com.embedika.mon" %% "mon-client" % verdiVersion
Регистрация в distage
make[MonClient[IO]].from { (dispatcher: Dispatcher, ec: ExecutionContext @Id("ec-services")) =>
implicit val executionContext: ExecutionContext = ec
implicit val ff: FromFuture[IO] = FromFuture.make[IO](ec)
MonClient.make[IO](dispatcher)
}
В distage клиент можно зарегистрировать следующим способом:
Предоставляемые методы
Mon-client предоставляет методы вызова соответствующих команд сервиса Mon. Формат входных и выходных данных методов Mon-client аналогичен формату входных и выходных данных команд сервиса Mon.
Mon-core: базовая библиотека сервисов аутентификации
В библиотеку вынесен шаблон структуры и кода для сервисов аутентификации и реализации по умолчанию.
Сервис разбит на несколько модулей, в виде sbt проектов:
domain, в котором содержатся все доменные модели и их различные представления.infrastructure, в котором содержатся базовые компоненты для взаимодействия с инфраструктурой.store, содержит сервисы для сохранения и чтения из разных хранилищ доменных моделей.service, содержит сервисы бизнес логики, которые определяют правила взаимодействия компонентов между собой.route, содержит HTTP роуты.boot, содержит зависимости и описание для сборки и запуска сервиса.testkit, моки и настройки окружения для тестов
Публикуются эти проекты как одна библиотека mon-core.
Подключение (mon-core)
Для того чтобы использовать библиотеку mon-core, нужно добавить зависимость
"com.embedika.mon" %% "mon-core" % verdiVersion
Liquibase (mon-core)
Реализация mon, поставляемая в данной библиотеке, предполагает наличие определенных таблиц в базе данных, которая
указана в
application.conf по пути database.db.url. Эти таблицы mon-core создает с помощью
com.embedika.verdi.persistence.migration.LiquibasePlugin.
Для корректной работы плагина в сервисе, созданном на основе mon-core, по пути boot/src/main/resources/liquibase
должен лежать файл changelog.xml,
иначе при запуске упадет исключение
liquibase.exception.ChangeLogParseException: The file liquibase/changelog.xml was not found.
Для корректной работы всех команд в сервисе, созданном на основе mon-core, предоставленный файл changelog.xml должен
включать в себя все
stages, находящиеся в mon-core по пути /testkit/src/main/resources/liquibase/stages.
При необходимости после указанных stages можно добавить в changelog.xml свои кастомные stages.
Пример содержимого файла changelog.xml.
<?xml version="1.0" encoding="UTF-8"?>
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd">
<include file="stages/init.xml" relativeToChangelogFile="true"/>
<include file="stages/groups.xml" relativeToChangelogFile="true"/>
<include file="stages/2023.xml" relativeToChangelogFile="true"/>
<include file="stages/2024.xml" relativeToChangelogFile="true"/>
<include file="stages/MyCustomStage.xml" relativeToChangelogFile="true"/>
</databaseChangeLog>
Модули (mon-core)
Для инициализации сервиса mon используются модули izumi-distage.
В каждом модуле описывается создание сущностей, необходимых для работы сервиса.
Модуль можно определить двумя способами
object MyModule extends ModuleDef {}
case class MyModule[F[_] : TagK] extends ModuleDef {}
В модулях можно указывать то, какая реализация соответствует трейту и (при необходимости) как ее создать.
make[MyTrait].from(MyImpl)
Если же класс используется напрямую, то указывать его соответствие трейту нет необходимости. Но указать необходимость его создания нужно и сделать это можно так.
make[MyImpl]
Если для трейта существует несколько имплементаций, которые стоит использовать в разных местах программы, то их можно различить с помощью метода named.
//создание named-соответствия
make[Config]
.named("db-config")
.from { rootConfig: RootConfig =>
rootConfig.database
}
//другое named-соответствие
make[Config]
.named("senderlib-config")
.from { rootConfig: RootConfig =>
rootConfig.senderlib
}
//использование named-соответствия
make[ProfileComponent].from { config: Config @Id("db-config") =>
ProfileComponent.postgresProfileComponent(config)
}
Если при инициализации хочется создать Set значений, то можно воспользоваться директивой many.
например
many[TechConstant]
.addSet(Set(myConstant1, myConstant2))
.add(myConstant3)
Если вы переиспользуете модуль, в котором уже было определено соответствие с помощью many, то добавить в этот Set значение можно точно также.
object OldModule extends ModuleDef {
many[TechConstant]
.addSet(Set(myConstant1, myConstant2))
.add(myConstant3)
}
object NewModule extends ModuleDef {
include(OldModule)
many[TechConstant]
.add(myConstant4)
}
Однако, если вы хотите убрать значение из предопределенного Set, нужно использовать overriddenBy с новым соответствием many и с новым набором значений.
В boot/src/main/modules хранятся некоторые уже описанные заранее определения модулей izumi-distage для создания сервисов mon. Для того чтобы расширить существующий модуль, то есть добавить в него НОВОЕ соответствие реализации трейту или новый класс, который мы используем напрямую, нужно создать новый расширенный модуль и включить в него старый.
object MyOldModule extends ModuleDef {
make[MyOldTrait].from(MyOldImpl)
}
object MyNewModule extends ModuleDef {
inlude(MyOldModule)
make[MyNewTrait].from(MyNewImpl)
}
Для того чтобы переопределить соответствие реализации трейту в модуле, но использовать все остальное, нужно переопределить модуль.
object MyOldModule extends ModuleDef {
make[MyOldTrait].from(MyOldImpl)
}
object MyNewModule extends ModuleDef {
make[MyOldTrait].from(MyNewImpl)
}
object OverriddenModule extends ModuleDef {
include(MyOldModule overriddenBy MyNewModule)
}
MainAppModule (mon-core)
Точкой входа в программу является модуль MainAppModule, который содержит весь функционал сервиса mon и требует всех обязательных значений application.conf.
Запустить MainAppModule можно двумя способами:
object Main extends IOApp {
override def run(args: List[String]): IO[ExitCode] =
MainAppModule
.resource[IO]
.use(_.run())
.as(ExitCode.Success)
}
object Main extends IOApp {
override def run(args: List[String]): IO[ExitCode] =
MainAppModule
.resourceWithModule[IO](MainAppModule[IO]())
.use(_.run())
.as(ExitCode.Success)
}
Для тех, кому нет необходимости использовать полную версию Mon, существует модуль BaseMainAppModule, который реализует только базовую инициализацию сервиса Mon.
Запустить BaseMainAppModule можно так:
Этот модуль парсит урезанную версию конфига, не содержит в себе функционал связанный с
- лицензиями,
- ограничением срока действия аккаунтов,
- журналированием,
- авторизацией,
- публикацией команд в attila,
- интеграцией с внешними системами keycloak и kerberos.
Кроме того, эта версия mon не публикует технические константы для команд и не отвечает ни на какие команды. Http-сервер этой версии mon принимает только GET запрос /health.
Для некоторых из этих функций в BaseMainApp совсем не определены модули, а для некоторых из них определены модули-заглушки (dummy-модули) и соответствия-заглушки (dummy-соответствия). Кроме того в BaseAppModule определен эффект LiquidBase-плагина, создающий Unit.
Модули, содержащиеся в BaseMainApp:
- ActorSystemModule,
- ThreadPoolModule,
- VerdiModule,
- JwtModule,
- InfrastructureServiceModule,
- KafkaProducerModule,
- DatabaseModule,
- DatabaseServiceModule,
- BaseConfigModule,
- BaseHttpApiModule,
- BaseServiceModule,
- BaseCommandsModule.
Соответствия, содержащиеся в BaseMainApp напрямую, без модулей:
- FromDBIO,
- FromFuture.
Dummy-соответствия, содержащиеся в BaseMainApp напрямую, без модулей:
- LicenseRestrictions
- AccountRestrictions
- JournalingService
- Authorizer
- AttilaDependenciesPublisher,
- many[TechConstant](множественное соответствие)
Классы без соответствий, содержащиеся в BaseMainApp напрямую, без модулей:
- ConstantsRegistrar
- TerminationCoordinator
- ServicePreparer
- DataBasePreparer
- SettingUp
- MainApp.
Предполагаемый сценарий использования BaseMainAppModule это включение его через include в некоторый новый модуль, который дополнительно содержит модули необходимые пользователю. Например, так можно добавить к базовому функционалу руты для команд, относящихся к пользователям.
Замечание: Это пример, а не готовый вариант запуска, так как UserApiModule требует хэндлеры команд.
case class UserHttpApiModule[F[_] : TagK]() extends ModuleDef {
include(BaseHttpApiModule[F])
include(UserApiModule[F]())
}
case class MainAppModule[F[_] : TagK : Timer]()(implicit ce: ConcurrentEffect[F], cs: ContextShift[F]) extends ModuleDef {
include(
BaseMainAppModule[F]()
overriddenBy UserHttpApiModule[F]()
)
}
Замечание: При наличии соответствия (даже dummy-соответствия) одновременно в BaseMainAppModule и
нельзя сделать просто:
include(BaseMainAppModule[F]())
make[MyTrait].from(MyImpl)
Нужно делать
object NyModule extends ModuleDef {
make[MyTrait].from(MyImpl)
}
include(BaseMainAppModule[F]() overriddenBy MyModule)
Базовые модули (mon-core)
Существуют также базовые модули
- BaseConfigModule,
- BaseHttpApiModule,
- BaseServiceModule,
- BaseCommandsModule.
Скорее всего их также нужно будет переопределить и расширить в соответствии со своими нуждами во время использования библиотеки.
Ознакомиться с тем, какие модули и соответствия они содержат внутри себя можно в файлах scala
- ConfigModule,
- HttpApiModule,
- ServiceModule,
- CommandsModule соответственно.
Пример минимального конфига, необходимого для запуска BaseMainAppModule (mon-core)
app {
http {
host = "0.0.0.0"
host = ${?MON_HTTP_HOST}
port = 8192
port = ${?MON_HTTP_PORT}
}
kafka {
servers = "localhost:9092"
servers = ${?MON_KAFKA_SERVERS}
commandEvent {
topic = "commandevents"
topic = ${?MON_KAFKA_COMMANDEVENT_TOPIC}
}
connectionCheck {
testMessagesTopicName = ${app.kafka.commandEvent.topic}
testMessagesSendInterval = 4 minutes
testMessagesSendInterval = ${?MON_KAFKA_CONNECTION_CHECK_TEST_MESSAGES_INTERVAL}
checkInterval = 60 seconds
checkInterval = ${?MON_KAFKA_CONNECTION_CHECK_INTERVAL}
checkFailedAfterInterval = 5 minutes
checkFailedAfterInterval = ${?MON_KAFKA_CONNECTION_CHECK_FAILED_AFTER_INTERVAL}
}
userEvent {
topic = "userEvents"
topic = ${?MON_KAFKA_USEREVENT_TOPIC}
}
auth {
staticAuth {
passwordBased {
user = ""
user = ${?MON_KAFKA_AUTH_USER}
password = ""
password = ${?MON_KAFKA_AUTH_PASSWORD}
}
kerberosBased {
principal = ""
principal = ${?MON_KAFKA_AUTH_PRINCIPAL}
keytabPath = ""
keytabPath = ${?MON_KAFKA_AUTH_KEYTAB_PATH}
}
truststore {
location = ""
location = ${?MON_KAFKA_AUTH_TRUSTSTORE_LOCATION}
password = ""
password = ${?MON_KAFKA_AUTH_TRUSTSTORE_PASSWORD}
}
}
authMode = "static"
authMode = ${?MON_KAFKA_AUTH_MODE}
authConfig = ""
authConfig = ${?MON_KAFKA_AUTH_CONFIG}
clientsCache {
maxSize = ${?MON_KAFKA_AUTH_CACHE_SIZE}
elementTTL = ${?MON_KAFKA_AUTH_CACHE_TTL}
}
}
}
consul {
address = "http://localhost:8500"
address = ${?MON_CONSUL_ADDR}
auth {
user = ""
user = ${?MON_CONSUL_AUTH_USER}
password = ""
password = ${?MON_CONSUL_AUTH_PASSWORD}
}
}
defaultUserGroups = ""
defaultUserGroups = ${?MON_USERGROUP_DEFAULT}
authentication {
jwt {
signatureSecret = ""
signatureSecret = ${?MON_JWT_SIGNATURE}
lifetime = 12 hours
lifetime = ${?MON_JWT_LIFETIME}
cookieExpireOffset = 24 hours
cookieExpireOffset = ${?MON_JWT_COOKIE_EXPIRE_OFFSET}
}
}
}
discoverableService {
id = "another_mon_instance"
id = ${?MON_DISCOVERABLE_ID}
name = "mon"
name = ${?MON_DISCOVERABLE_NAME}
host = "localhost"
host = ${?MON_DISCOVERABLE_HOST}
port = ${app.http.port}
port = ${?MON_DISCOVERABLE_PORT}
livetime = 2 minutes
livetime = ${?MON_DISCOVERABLE_LIVETIME}
healthPassPeriod = 1 minute
healthPassPeriod = ${?MON_DISCOVERABLE_HEALTHPASS}
}
serviceInfo {
name = ${discoverableService.name}
readableName = "Сервис пользователей"
readableName = ${?MON_READABLE_NAME}
description = "Предназначен для определения схемы и хранения объектов"
description = ${?MON_DESCRIPTION}
}
akka {
http {
host-connection-pool {
max-connections = 512
max-connections = ${?MON_AKKA_HTTP_CLIENT_MAXCON}
max-open-requests = 1024
max-open-requests = ${?MON_AKKA_HTTP_CLIENT_MAXREQ}
}
server {
max-connections = 1024
max-connections = ${?MON_AKKA_HTTP_SERVER_MAXCON}
}
}
}
senderlib {
allowInternalCommands = true
allowInternalCommands = ${?MON_INTERNALCMD_ALLOW}
cache {
commandStorage {
updatePeriod = 10 minutes
updatePeriod = ${?MON_SENDERLIB_COMMANDS_CACHE_UPDATEPERIOD}
}
serviceDiscovery {
updatePeriod = 30 seconds
updatePeriod = ${?MON_SENDERLIB_SERVICES_CACHE_UPDATEPERIOD}
}
}
commands {
http {
retry {
attempts = 5
attempts = ${?MON_SENDERLIB_COMMANDS_HTTP_RETRY_ATTEMPTS}
delay = 5 seconds
delay = ${?MON_SENDERLIB_COMMANDS_HTTP_RETRY_DELAY}
kind = "OnSomeExceptions(ConnectException)"
kind = ${?MON_SENDERLIB_COMMANDS_HTTP_RETRY_KIND}
}
}
}
}
database {
profile = "com.embedika.verdi.persistence.profile.VerdiPostgresProfile$"
db {
driver = "org.postgresql.Driver"
url = "jdbc:postgresql://"${?MON_DB_HOST}":"${?MON_DB_PORT}"/"${?MON_DB_NAME}
url = ${?MON_DB_URL}
user = ${?MON_DB_USER}
password = ${?MON_DB_PASSWORD}
numThreads = 10
numThreads = ${?MON_DB_THREADS}
queueSize = 300
queueSize = ${?MON_DB_QUEUE_SIZE}
maxConnections = 10
maxConnections = ${?MON_DB_CONN_MAX}
connectionTimeout = 20 second
connectionTimeout = ${?MON_DB_CONN_TIMEOUT}
isolation = "READ_COMMITTED"
isolation = ${?MON_DB_ISOLATION}
readOnly = false
readOnly = ${?MON_DB_READONLY}
minConnections = ${database.db.numThreads}
minConnections = ${?MON_DB_CONN_MIN}
validationTimeout = 1 seconds
validationTimeout = ${?MON_DB_VALIDATION_TIMEOUT}
idleTimeout = 10 minutes
idleTimeout = ${?MON_DB_IDLE_TIMEOUT}
maxLifetime = 30 minutes
maxLifetime = ${?MON_DB_MAX_LIFETIME}
#Deprecated in slick 3.3.0
initializationFailFast = false
initializationFailFast = ${?MON_DB_INITIALIZATION_FAIL_FAST}
leakDetectionThreshold = 0
leakDetectionThreshold = ${?MON_DB_LEAK_DETECTION_THRESHOLD}
connectionTestQuery = "SELECT 1"
connectionTestQuery = ${?MON_DB_CONNECTION_TEST_QUERY}
registerMbeans = false
registerMbeans = ${?MON_DB_REGISTER_MBEANS}
autoCommit = true
autoCommit = ${?MON_DB_AUTO_COMMIT}
schema = "public"
schema = ${?MON_DB_SCHEMA}
isolateInternalQueries = false
isolateInternalQueries = ${?MON_DB_ISOLATE_INTERNAL_QUERIES}
initializationFailTimeout = 1
initializationFailTimeout = ${?MON_DB_INITIALIZATION_FAIL_TIMEOUT}
}
}
liquibase = ${database.db}
# Default changelog file name in the root of classpath
liquibase.changelog = "liquibase/changelog.xml"
# Allows disabling liquibase migration
liquibase.enable = true
include "custom.conf"
Особенности Kerberos authentication (mon-core)
После добавления Kerberos authentication, сервис стал зависеть от пакета com.sun.security.auth.module, которого
нет, например, в IBM JRE.
Поэтому рекомендуется использовать OpenJDK или Oracle.
Дополнительно: "the browser URL must match the fully-qualified-domain-name as specified in ServicePrincipal".
Список команд библиотеки Mon-core (commands list)
Список реализованных в сервисе команд, моделей EntityType и действий Actions, которые можно использовать при настройке
авторизации.
Не все поля EntityType доступны для использования в настройке авторизации.
Если указан прочерк "-", то данное значение не влияет на авторизацию:
- если не указан Action, то никакой Action не проверяется (= без авторизации)
- если не указан EntityType, то на авторизацию влияет только Action
| Назначение команды | Имя вызова команды | EntityType | Actions |
|---|---|---|---|
| Регистрация нового пользователя | mon_http_RegisterUser | - | - |
| Подтверждение регистрации пользователя | mon_http_VerifyUserRegistration | - | - |
| Вход пользователя в систему (Логин-пароль) | mon_http_LoginByCredentials | - | - |
| Вход пользователя в систему (Kerberos) | mon_http_LoginByKerberos | - | - |
| Генерация ссылки на форму входа Keycloak | mon_http_GetKeycloakAuthUrl | - | - |
| Вход пользователя в систему (Keycloak) | mon_http_LoginByKeycloak | - | - |
| Выход пользователя из системы | mon_http_Logout | - | - |
| Изменение статуса пользователя | mon_http_ChangeUserStatus | User |
ChangeUserStatus |
| Изменение данных пользователя | mon_http_UpdateUserInfo | User |
UpdateUserInfo |
| Изменение пароля пользователя | mon_http_ChangeUserPassword | User |
ChangeUserPassword |
| Изменение срока действия аккаунта | mon_http_UpdateDeactivationTime | User |
UpdateDeactivationTime |
| Запрос восстановления пароля пользователя] | mon_http_PasswordRecoverRequest | - | - |
| Проверить токен пользователя | mon_http_CheckToken | - | - |
| Восстановить пароль по токену | mon_http_RecoverPasswordByToken | - | - |
| Список всех пользователей | mon_http_ListUsers | User |
ReadUsers |
| Список всех пользователей(внутренняя) | mon_http_ListUsersInternal | - | - |
| Список пользователей которые состоят в группе | mon_http_ListUsersByGroupId | User |
ReadUsers |
| Получение текущей лицензии | mon_http_ListUsersWithGroupsCount | User |
ReadUsers |
| Список пользователей с информацией о группах | mon_http_ListUsersWithGroups | User |
ListUsersWithGroups |
| Данные текущего пользователя | mon_http_MyData | - | - |
| Данные пользователя для контекста команды по JWT | mon_http_UserCommandContextData | - | - |
| Данные пользователя для контекста команды по OAuth access token | mon_http_UserCommandContextData_OauthAccessToken | - | - |
| Завершить все сессии (выданные JWT) для 1 пользователя | mon_http_CloseAllUserSessions | User |
InvalidateSession |
| Удалить правило инвалидации JWT | mon_http_DeleteJwtInvalidation | User |
InvalidateSession |
| Создать группу пользователей | mon_http_CreateGroup | Group |
CreateGroup |
| Получить группу пользователей по ID | mon_http_GetGroup | Group |
ReadGroup |
| Отредактировать группу пользователей | mon_http_UpdateGroup | Group |
UpdateGroup |
| Удалить группу пользователей | mon_http_DeleteGroup | Group |
DeleteGroup |
| Список всех групп пользователей | mon_http_ListGroups | Group |
ReadGroups |
| Список групп в которых состоит пользователь | mon_http_ListGroupsByUserId | Group |
ReadGroups |
| Получить список групп по списку идентификаторов пользователей | mon_http_ListGroupsByUserIds | Group |
ReadGroups |
| Добавить пользователей в группу | mon_http_AddUsersToGroup | Group |
ManageUsers |
| Удалить пользователей из группы | mon_http_RemoveUsersFromGroup | Group |
ManageUsers |
| Получение текущей лицензии | mon_http_GetLicenseInfo | - | ViewLicense |
| Получить список идентификаторов пользователей по списку идентификаторов групп(внутренняя) | mon_http_ListUserIdsByGroupIds | - | - |
| Выгрузить список пользователей согласно шаблону | mon_http_ExportUsers | User |
ExportUsers |
RegisterUser (mon-core)
Payload для команды
{
"email": "emailname@mail.io",
"password": "strongpassword",
"info": {
"firstName": "John",
"lastName": "Week",
"middleName": "Jovonovich",
"data": {
"myField": {
"myInnerField": "value"
}
}
},
"notificationUrl": "http://localhost:8080/verify-user?token=[[token]]"
}
Результат выполнения команды
{
"userId": "a133f0c8-a516-4537-8f3f-915acb335e2c",
"verificationRequested": true
}
Добавляет нового пользователя. Статус зависит от настроек сервиса. Если включена проверка email, то отправляется письмо для проверки email, а статус пользователя назначается в Pending. Если проверка email выключена, то статус пользователя назначается в Activated. Уникальность пользователя определяется по полю Email. Отправляет событие о регистрации нового пользователя.
Имя вызова команды:mon_http_RegisterUser.
Поддерживается только синхронный вызов.
Результат выполнения команды журналируется.
- На входе: UserRegistrationDto
- На выходе: UserRegistrationResult
VerifyUserRegistration (mon-core)
Payload для команды
"e5cdd1e3-84ef-4d85-98d4-b56bac91093d"
Результат выполнения команды
"user has been verified"
Подтверждает регистрацию нового пользователя и изменяет его статус "Pending" => "Activated". Отправляет событие о подтверждении нового пользователя.
Имя вызова команды:mon_http_VerifyUserRegistration.
Поддерживается только синхронный вызов.
Результат выполнения команды журналируется.
- На входе: ActionTokenId
- На выходе: "user has been verified"
LoginByCredentials (mon-core)
Payload для команды
{
"email": "emailname@mail.io",
"password": "strongpassword"
}
Результат выполнения команды (Header ответа)
Set-Cookie: jwt_token=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJTb21lKDRiZTgxOGFlLTUwNTMtNDM2Zi1hZTEzLWE3NDY5MDgwMDhkYykiLCJleHAiOjE2MjkzMDIyMzUsInVzZXJJZCI6IjRiZTgxOGFlLTUwNTMtNDM2Zi1hZTEzLWE3NDY5MDgwMDhkYyJ9.XxPMZUtIez9pG2zfwrIxBofQN5b2dQ2p3Q4XPPCLB-E; Expires=Wed, 18 Aug 2021 15:57:15 GMT; Path=/; HttpOnly
Осуществляет вход пользователя в систему по логину и паролю, а также деактивацию в соответствии с ограничениями лицензий и сроков действия аккаунта.
Имя вызова команды:mon_http_LoginByCredentials.
Поддерживается только синхронный вызов.
Результат выполнения команды журналируется.
- На входе: LoginCredentials
- На выходе: HTTP Header "Set-Cookie:jwt_token=???; Expires=???; Path=/; HttpOnly"
LoginByKerberos (mon-core)
Payload для команды (Header запроса, base64)
Authorization: Negotiate YIIB1wYJKoZIhvcSAQICAQBuggHGMIIBwqADAgEFoQMCAQ6iBwMFAAAAAACjge5hgeswge
Результат выполнения команды (Header ответа, base64)
WWW-Authenticate: Negotiate ???, где ??? может быть или токен в base64 или пустая строка (т.е. значение Header будет просто "Negotiate")
Set-Cookie: jwt_token=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJTb21lKDRiZTgxOGFlLTUwNTMtNDM2Zi1hZTEzLWE3NDY5MDgwMDhkYykiLCJleHAiOjE2MjkzMDIyMzUsInVzZXJJZCI6IjRiZTgxOGFlLTUwNTMtNDM2Zi1hZTEzLWE3NDY5MDgwMDhkYyJ9.XxPMZUtIez9pG2zfwrIxBofQN5b2dQ2p3Q4XPPCLB-E; Expires=Wed, 18 Aug 2021 15:57:15 GMT; Path=/; HttpOnly
Осуществляет вход пользователя в систему на основе профиля пользователя из Active Directory. Если пользователь с указанным профилем не зарегистрирован, то происходит процесс регистрации БЕЗ верификации (статус пользователя будет сразу Activated).
Имя вызова команды:mon_http_LoginByKerberos.
Поддерживается только синхронный вызов.
Результат выполнения команды журналируется.
- На входе: HTTP Header "Authorization: Negotiate ???"
- На выходе: HTTP Header "Set-Cookie: jwt_token=???; Expires=???; Path=/; HttpOnly"
GetKeycloakAuthUrl (mon-core)
Результат выполнения команды (тело ответа) (URL на форму входа)
"http://keycloak.url/realms/verdi/protocol/openid-connect/auth?scope=openid+profile+email&response_type=code&redirect_uri=http%3A%2F%2Fverdi.dev%2Fkeycloak-callback"
Результат выполнения команды (Header ответа)
Set-Cookie: external_session_id=802bf1d6-366c-420e-9196-5645ce9953bb; Max-Age=600; Path=/; HttpOnly
Генерирует и возвращает ссылку на форму входа в Keycloak, а также устанавливает коротко живущую Cookie, необходимую для последующей аутентификации в Keycloak.
Имя вызова команды:mon_http_GetKeycloakAuthUrl.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: -
- На выходе: String
LoginByKeycloak (mon-core)
Payload для команды
{
"queryParameters": {
"client_name": "KeycloakOidcClient",
"session_state": "914b01b8-19ca-42f4-af11-96fa49da0caa",
"code": "b164638b-05a8-413d-aa86-1442a7f10252.35216f68-c210-447e-ade4-d0a7035254d6.0974025f-9aa6-4daf-b755-80ba35c64576",
"state": "ce901f20522"
}
}
Результат выполнения команды (Header ответа)
Set-Cookie: jwt_token=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJTb21lKDRiZTgxOGFlLTUwNTMtNDM2Zi1hZTEzLWE3NDY5MDgwMDhkYykiLCJleHAiOjE2MjkzMDIyMzUsInVzZXJJZCI6IjRiZTgxOGFlLTUwNTMtNDM2Zi1hZTEzLWE3NDY5MDgwMDhkYyJ9.XxPMZUtIez9pG2zfwrIxBofQN5b2dQ2p3Q4XPPCLB-E; Expires=Wed, 18 Aug 2021 15:57:15 GMT; Path=/; HttpOnly
Осуществляет вход пользователя в систему на основе профиля в Keycloak. Если пользователь с указанным профилем не зарегистрирован, то происходит процесс регистрации БЕЗ верификации (статус пользователя будет сразу Activated).
Имя вызова команды:mon_http_LoginByKeycloak.
Поддерживается только синхронный вызов.
Результат выполнения команды журналируется.
- На входе: HTTP Header "Cookie: external_session_id=???"
- На входе: QueryParameters
- На выходе: HTTP Header "Set-Cookie: jwt_token=???; Expires=???; Path=/; HttpOnly"
Logout (mon-core)
Результат выполнения команды (Header ответа)
Set-Cookie:jwt_token=deleted; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Path=/; HttpOnly
Осуществляет выход текущего пользователя из системы.
Имя вызова команды:mon_http_Logout.
Поддерживается только синхронный вызов.
Результат выполнения команды журналируется.
- На входе: HTTP Header "Cookie: jwt_token=???"
- На выходе: HTTP Header "Set-Cookie:jwt_token=deleted; Expires=Thu, 01 Jan 1970 00:00:00 GMT; Path=/; HttpOnly"
ChangeUserStatus (mon-core)
Payload для команды
{
"userId": "a133f0c8-a516-4537-8f3f-915acb335e2c",
"status": "Deactivated"
}
Результат выполнения команды
{
"id": "a133f0c8-a516-4537-8f3f-915acb335e2c",
"email": "emailname@mail.io",
"status": "Deactivated",
"info": {
"firstName": "John",
"lastName": "Week",
"middleName": "Jovonovich",
"data": {}
},
"modified": 1715940083060,
"modifiedBy": "00000000-0000-0000-0000-000000000000",
"reason": null,
"deactivateAt": 1715940083770
}
Изменяет статус пользователя на тот, что указан во входных данных. Возможны любые переходы.
Имя вызова команды:mon_http_ChangeUserStatus.
Поддерживается только синхронный вызов.
Результат выполнения команды журналируется.
- На входе: UserIdWithStatus
- На выходе: User
UpdateUserInfo (mon-core)
Payload для команды
{
"id": "9a67afa9-1a21-4a6d-9e97-334e9d95a7f2",
"info": {
"firstName": "newFirstName",
"lastName": "newLastName",
"middleName": "newMiddleName",
"data": {
"myField": {
"myInnerField": "value"
}
}
}
}
Результат выполнения команды
{
"id": "9a67afa9-1a21-4a6d-9e97-334e9d95a7f2",
"email": "email3name@mail.io",
"status": "Pending",
"info": {
"firstName": "newFirstName",
"lastName": "newLastName",
"middleName": "newMiddleName",
"data": {
"myField": {
"myInnerField": "value"
},
"myOldField": "oldValue"
}
},
"modified": 1715940083060,
"modifiedBy": "00000000-0000-0000-0000-000000000000",
"reason": null,
"deactivateAt": 1715940083770
}
Обновляет данные пользователя относительно тех, которые указаны во входных данных. При этом поля firstName, lastName, middleName перезаписываются на новые значения (если соответствующее поле присутствует во входных данных), а в поле data производится merge: при наличии поля в json оно перезаписывается на новое значение, а при отсутствии добавляется. Старые поля json внутри data, которых не было во входящем json, не меняются.
Имя вызова команды:mon_http_UpdateUserInfo.
Поддерживается только синхронный вызов.
Результат выполнения команды журналируется.
- На входе: UserIdWithInfo
- На выходе: User
UpdateDeactivationTime (mon-core)
Payload для команды
{
"userIds": [
"9a67afa9-1a21-4a6d-9e97-334e9d95a7f2",
"d81f3bb4-46bc-475f-af21-3277989e1371"
],
"newDeactivateAt": 1715940083060,
"reason": "Изменение срока деактивации"
}
Результат выполнения команды
{
"updated": 2
}
Изменяет на переданное время деактивации(или удаляет при отсутствии поля newDeactivateAt) время деактивации аккаунта всех пользователей,
id которых входит в переданный список.
При выполнении этой команды также обновятся значения полей modified, modifiedBy и reason
на текущий timestamp, id пользователя, который вызывал команду, и переданный в команду reason соответственно.
Имя вызова команды:mon_http_UpdateDeactivationTime.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: UpdateDeactivationTimeInput
- На выходе: UpdateResponse
ChangeUserPassword (mon-core)
Payload для команды
{
"oldPassword": "pass123",
"newPassword": "new_Pa$$w0rd"
}
Результат выполнения команды (признак успешности исполнения)
true
Изменяет пароль пользователя со "старого" на "новый", что указан во входных данных. "Старый" пароль должен совпадать с текущим паролем пользователя. В ином случае, вовращается ошибка неверного пользователя/пароля.
Имя вызова команды:mon_http_ChangeUserPassword.
Поддерживается только синхронный вызов.
Результат выполнения команды журналируется.
- На входе: ChangePasswordDto
- На выходе: Boolean
PasswordRecoverRequest (mon-core)
Payload для команды
{
"email": "emailname@mail.io",
"notificationUrl": "http://localhost:8080/change-password?token=[[token]]"
}
Сгенерировать для пользователя токен c типом "ChangePassword"
Шаблон формируемой ссылки находится в переменной MON_PASSWORD_RECOVERY_URL
Имя вызова команды:mon_http_PasswordRecoverRequest.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: PasswordRecoverRequestDto
- На выходе: -
CheckToken (mon-core)
Payload для команды
{
"actionTokenId": "b133f0c8-a516-4537-8f3f-915acb335e2b"
}
Результат выполнения команды
"token is valid"
Проверить статус токена восстановления пароля
Имя вызова команды:mon_http_CheckToken.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: CheckTokenDto
- На выходе:
"token is valid"
RecoverPasswordByToken (mon-core)
Payload для команды
{
"token": "e5cdd1e3-84ef-4d85-98d4-b56bac91093d",
"newPassword": "new_Pa$$w0rd"
}
Результат выполнения команды
"password has been changed"
Команда используется для установки нового пароля, который пользователь введет на форме восстановления
Имя вызова команды:mon_http_RecoverPasswordByToken.
Поддерживается только синхронный вызов.
Результат выполнения команды журналируется.
- На входе: RecoverPasswordByTokenDto
- На выходе:
"password has been changed"
ListUsers (mon-core)
Payload для команды
{
"sorting": {
"fieldName": "lastname",
"order": "asc"
},
"paging": {
"page": 1,
"count": 20
},
"query": "firstname",
"context": {
"firstname": "John"
}
}
Результат выполнения команды
{
"total": 1,
"items": [
{
"id": "a133f0c8-a516-4537-8f3f-915acb335e2c",
"email": "emailname@mail.io",
"status": "Activated",
"info": {
"firstName": "John",
"lastName": "Week",
"middleName": "Jovonovich",
"data": {}
},
"modified": 1715940083060,
"modifiedBy": "00000000-0000-0000-0000-000000000000",
"reason": null,
"deactivateAt": 1715940083770
}
]
}
Возвращает список всех существующих пользователей.
Имя вызова команды:mon_http_ListUsers.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
По умолчанию сортировка производится по полю email модели User.
Запрос принимает параметры сортировки, фильтров и пейджинга в параметре Search.
Применяется к полям моделей User и UserInfo.
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров | Комментарии |
|---|---|---|
| userId | InSetQuery | |
| status | InSetQuery | |
| InSetQuery, LikeQuery | ||
| modified | InSetQuery, RangeQuery | |
| lastName | InSetQuery, LikeQuery | |
| firstName | InSetQuery, LikeQuery | |
| middleName | InSetQuery, LikeQuery | |
| fio | TsQuery | Поле содержит конкатенацию нескольких полей модели UserInfo: lastName + " " + firstName + " " + middleName. |
| data | LikeQuery |
Доступные поля для сортировки:
| Поле |
|---|
| userId |
| status |
| lastName |
| firstName |
| middleName |
| modified |
ListUsersInternal (mon-core)
Payload для команды
[
"45682a6e-fb74-4ea9-b344-f24b2d3afd0a",
"3c94e169-f9b3-4c50-b497-21ee544d6fae"
]
Результат выполнения команды
[
{
"userId": "45682a6e-fb74-4ea9-b344-f24b2d3afd0a",
"email": "email5name@mail.io"
},
{
"userId": "3c94e169-f9b3-4c50-b497-21ee544d6fae",
"email": "email6name@mail.io"
}
]
Возвращает список userId и соответствующих им email, где userId - это id пользователей, переданные во входящем списке.
Имя вызова команды:mon_http_ListUsersInternal.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway), не требует аутентификации.
- На входе: Set[UserId]
- На выходе: List[UserIdWithEmail]
ListUsersByGroupId (mon-core)
Payload для команды
{
"groupId": "id_of_my_first_group",
"options": {
"sorting": {
"fieldName": "name",
"order": "asc"
},
"paging": {
"page": 1,
"count": 20
},
"query": "status",
"context": {
"status": "Activated"
}
}
}
Результат выполнения команды
{
"total": 2,
"items": [
{
"user": {
"id": "a133f0c8-a516-4537-8f3f-915acb335e2c",
"email": "emailname@mail.io",
"status": "Activated",
"info": {
"firstName": "John",
"lastName": "Week",
"middleName": "Jovonovich",
"data": {}
},
"modified": 1715940083060,
"modifiedBy": "00000000-0000-0000-0000-000000000000",
"reason": null,
"deactivateAt": 1715940083770
},
"groupsCount": 1
},
{
"user": {
"id": "2595becc-e4a2-4507-88bf-e0114ab6d677",
"email": "abc@gmail.ru",
"status": "Activated",
"info": {
"firstName": "Ivan",
"lastName": "Petrov",
"middleName": "Vasilyevich",
"data": {}
},
"modified": 1715940083060,
"modifiedBy": "00000000-0000-0000-0000-000000000000",
"reason": null,
"deactivateAt": 1715940083770
},
"groupsCount": 10
}
]
}
Возвращает список всех пользователей, которые состоят в указанной группе.
Имя вызова команды:mon_http_ListUsersByGroupId.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: GroupIdWithOptions
- На выходе: List[UserWithGroupCount]
По умолчанию сортировка производится по полю email модели User.
Запрос принимает параметры сортировки, фильтров и пейджинга в параметре Search в поле options входных данных.
Применяется к полям моделей User и UserInfo, а также отдельно к полям:
count- количество групп, в которых состоит пользователь;groupId- идентификатор группы, в которой состоит пользователь.
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров | Комментарии |
|---|---|---|
| userId | InSetQuery | |
| status | InSetQuery | |
| InSetQuery, LikeQuery | ||
| modified | InSetQuery, RangeQuery | |
| lastName | InSetQuery, LikeQuery | |
| firstName | InSetQuery, LikeQuery | |
| middleName | InSetQuery, LikeQuery | |
| fio | TsQuery | Поле содержит конкатенацию нескольких полей модели UserInfo: lastName + " " + firstName + " " + middleName. |
| data | LikeQuery | |
| count | InSetQuery, LikeQuery, RangeQuery | |
| groupId | InSetQuery, AllInSetQuery |
Доступные поля для сортировки:
| Поле |
|---|
| userId |
| status |
| lastName |
| firstName |
| middleName |
| count |
ListUsersWithGroupsCount (mon-core)
Payload для команды
{
"sorting": {
"fieldName": "name",
"order": "asc"
},
"paging": {
"page": 1,
"count": 20
},
"query": "status",
"context": {
"status": "Activated"
}
}
Результат выполнения команды
{
"total": 2,
"items": [
{
"user": {
"id": "a133f0c8-a516-4537-8f3f-915acb335e2c",
"email": "emailname@mail.io",
"status": "Activated",
"info": {
"firstName": "John",
"lastName": "Week",
"middleName": "Jovonovich",
"data": {}
},
"modified": 1715940083060,
"modifiedBy": "00000000-0000-0000-0000-000000000000",
"reason": null,
"deactivateAt": 1715940083770
},
"groupsCount": 1
},
{
"user": {
"id": "2595becc-e4a2-4507-88bf-e0114ab6d677",
"email": "abc@gmail.ru",
"status": "Activated",
"info": {
"firstName": "Ivan",
"lastName": "Petrov",
"middleName": "Vasilyevich",
"data": {}
},
"modified": 1715940083060,
"modifiedBy": "00000000-0000-0000-0000-000000000000",
"reason": null,
"deactivateAt": 1715940083770
},
"groupsCount": 10
}
]
}
Возвращает список всех пользователей и кол-во групп, в которых они состоят.
Имя вызова команды:mon_http_ListUsersWithGroupsCount.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: Search
- На выходе: List[UserWithGroupCount]
По умолчанию сортировка производится по полю email модели User.
Запрос принимает параметры сортировки, фильтров и пейджинга в параметре Search.
Применяется к полям моделей User и UserInfo, а также отдельно к полям:
count- количество групп, в которых состоит пользователь;groupId- идентификатор группы, в которой состоит пользователь.
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров | Комментарии |
|---|---|---|
| userId | InSetQuery | |
| status | InSetQuery | |
| InSetQuery, LikeQuery | ||
| modified | InSetQuery, RangeQuery | |
| lastName | InSetQuery, LikeQuery | |
| firstName | InSetQuery, LikeQuery | |
| middleName | InSetQuery, LikeQuery | |
| fio | TsQuery | Поле содержит конкатенацию нескольких полей модели UserInfo: lastName + " " + firstName + " " + middleName. |
| data | LikeQuery | |
| count | InSetQuery, LikeQuery, RangeQuery | |
| groupId | InSetQuery, AllInSetQuery |
Доступные поля для сортировки:
| Поле |
|---|
| userId |
| status |
| lastName |
| firstName |
| middleName |
| count |
ListUsersWithGroups (mon-core)
Payload для команды
{
"sorting": {
"fieldName": "name",
"order": "asc"
},
"paging": {
"page": 1,
"count": 20
},
"query": "status",
"context": {
"status": "Activated"
}
}
Результат выполнения команды
{
"total": 2,
"items": [
{
"user": {
"id": "a133f0c8-a516-4537-8f3f-915acb335e2c",
"email": "emailname@mail.io",
"status": "Activated",
"info": {
"firstName": "John",
"lastName": "Week",
"middleName": "Jovonovich",
"data": {}
},
"modified": 1715940083060,
"modifiedBy": "00000000-0000-0000-0000-000000000000",
"reason": null,
"deactivateAt": 1715940083770
},
"groups": [
{
"groupId": "id_of_my_first_group",
"title": "моя первая группа"
}
]
},
{
"user": {
"id": "2595becc-e4a2-4507-88bf-e0114ab6d677",
"email": "abc@gmail.ru",
"status": "Activated",
"info": {
"firstName": "Ivan",
"lastName": "Petrov",
"middleName": "Vasilyevich",
"data": {}
},
"modified": 1715940083060,
"modifiedBy": "00000000-0000-0000-0000-000000000000",
"reason": null,
"deactivateAt": 1715940083770
},
"groups": [
{
"groupId": "id_of_my_first_group",
"title": "моя первая группа"
},
{
"groupId": "id_of_my_second_group",
"title": "моя вторая группа"
}
]
}
]
}
Возвращает список всех пользователей и id и title групп, в которых они состоят.
Имя вызова команды:mon_http_ListUsersWithGroups.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: Search
- На выходе: List[UserWithGroups]
По умолчанию сортировка производится по полю email модели User.
Запрос принимает параметры сортировки, фильтров и пейджинга в параметре Search.
Применяется к полям моделей User и UserInfo, а также отдельно к полям:
count- количество групп, в которых состоит пользователь;groupId- идентификатор группы, в которой состоит пользователь.
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров | Комментарии |
|---|---|---|
| userId | InSetQuery | |
| status | InSetQuery | |
| InSetQuery, LikeQuery | ||
| modified | InSetQuery, RangeQuery | |
| lastName | InSetQuery, LikeQuery | |
| firstName | InSetQuery, LikeQuery | |
| middleName | InSetQuery, LikeQuery | |
| fio | TsQuery | Поле содержит конкатенацию нескольких полей модели UserInfo: lastName + " " + firstName + " " + middleName. |
| data | LikeQuery | |
| count | InSetQuery, LikeQuery, RangeQuery | |
| groupId | InSetQuery, AllInSetQuery |
Доступные поля для сортировки:
| Поле |
|---|
| userId |
| status |
| lastName |
| firstName |
| middleName |
| count |
ExportUsers (mon-core)
Payload для команды
{
"sorting": {
"fieldName": "name",
"order": "asc"
},
"query": "status",
"context": {
"status": "Activated"
}
}
Результат выполнения команды
"temp/478eec63-4b8e-4cd2-9514-ae91b712b82a"
Выгружает список пользователей согласно шаблону, переданному в конфигурации.
Имя вызова команды:mon_http_ExportUsers.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: Option[Search]
- На выходе: StoredFile
Доступные поля для фильтрации и сортировки совпадают с ListUsersWithGroups.
MyData (mon-core)
Результат выполнения команды
{
"id": "a133f0c8-a516-4537-8f3f-915acb335e2c",
"email": "emailname@mail.io",
"status": "Activated",
"info": {
"firstName": "John",
"lastName": "Week",
"middleName": "Jovonovich",
"data": {}
},
"modified": 1715940083060,
"modifiedBy": "00000000-0000-0000-0000-000000000000",
"reason": null,
"deactivateAt": 1715940083770
}
Возвращает данные пользователя согласно указанному JWT.
Имя вызова команды:mon_http_MyData.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: HTTP Header "Cookie: jwt_token=???"
- На выходе: User
UserCommandContextData (mon-core)
Результат выполнения команды
{
"userContext": {
"id": "a133f0c8-a516-4537-8f3f-915acb335e2c",
"emailOpt": "emailname@mail.io",
"groupIds": [
"first_group_id",
"second_group_id",
"third_group_id"
],
"passwordExpirationDateOpt": 1715940083770
},
"userStatus": "Activated",
"jwtInvalidation": [
{
"id": "d07c0cbc-93ee-4d5c-b9af-21b1aaf92a40",
"condition": "1700545830"
}
]
}
Возвращает основную информацию о пользователе, которая необходима при выполнении команд пользователем, согласно указанному JWT.
Данная команда используется в ApiGateway при создании контекста запроса входящих команд (context в CommandRequest).
Имя вызова команды:mon_http_UserCommandContextData.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: HTTP Header "Cookie: jwt_token=???"
- На выходе: UserContextWithInvalidations
UserCommandContextData_OauthAccessToken (mon-core)
Payload для команды
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJ3ZnB4U3puQmw0UXRJNW83d2FZZFNWQzNRTm10NzEzUlB3bktMRzJDZk1nIn0.eyJleHAiOjE3MTkyOTMwOD...
Результат выполнения команды
{
"userContext": {
"id": "a133f0c8-a516-4537-8f3f-915acb335e2c",
"emailOpt": "emailname@mail.io",
"groupIds": [
"first_group_id",
"second_group_id",
"third_group_id"
],
"passwordExpirationDateOpt": null
},
"userStatus": "Activated",
"jwtInvalidation": []
}
Возвращает информацию о пользователе по переданному AccessToken (из HTTP Header "Authorization") для контекста запроса
команды CommandRequest.
В результате команды, поле "passwordExpirationDateOpt" из UserContext всегда будет пустым, т.к. исходные данные о пользователе хранятся во внешней системе.
Имя вызова команды:mon_http_UserCommandContextData_OauthAccessToken.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: HTTP Header "Authorization:Bearer eyJhbGciOiJSUzI1NiI..." (в примере указано лишь начало AccessToken)
- На выходе: UserContextWithInvalidations
CloseAllUserSessions (mon-core)
Payload для команды
"a133f0c8-a516-4537-8f3f-915acb335e2c"
Результат выполнения команды (признак успешности исполнения)
true
Завершает все активные сессии выбранного пользователя. Завершение заключается в добавлении правила для инвалидации JWT с UserId.
Имя вызова команды:mon_http_CloseAllUserSessions.
Поддерживается только синхронный вызов.
Результат выполнения команды журналируется.
- На входе: UserId
- На выходе: Boolean
DeleteJwtInvalidation (mon-core)
Payload для команды
"a133f0c8-a516-4537-8f3f-915acb335e2c"
Результат выполнения команды (количество удаленных записей)
1
Удаляет из БД правило для инвалидации JWT с указанным идентификатором.
Имя вызова команды:mon_http_DeleteJwtInvalidation.
Поддерживается только синхронный вызов.
Результат выполнения команды журналируется.
- На входе: JwtInvalidationId
- На выходе: Int
CreateGroup (mon-core)
Payload для команды
{
"id": "id_of_my_first_group",
"name": "Название группы на руском языке",
"description": "Описание группы"
}
Результат выполнения команды
{
"id": "id_of_my_first_group",
"name": "Название группы на руском языке",
"modified": 1631707774,
"description": "Описание группы"
}
Добавляет новую группу пользователей с заданными параметрами. Отправляет событие о создании группы.
Имя вызова команды:mon_http_CreateGroup.
Поддерживается только синхронный вызов.
Результат выполнения команды журналируется.
- На входе: UpdateGroupDTO
- На выходе: GroupDto
GetGroup (mon-core)
Payload для команды
"id_of_my_first_group"
Результат выполнения команды
{
"id": "id_of_my_first_group",
"name": "Название группы на руском языке",
"modified": 1631707774,
"description": "Описание группы"
}
Поиск группы пользователей с заданным идентифкатором.
Имя вызова команды:mon_http_GetGroup.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
UpdateGroup (mon-core)
Payload для команды
{
"id": "id_of_my_first_group",
"name": "Новое название группы на каком-то языке",
"description": "Измененное описание группы"
}
Результат выполнения команды
{
"id": "id_of_my_first_group",
"name": "Новое название группы на каком-то языке",
"modified": 1631707774,
"description": "Измененное описание группы"
}
Обновляет данные о группе пользователей. Отправляет событие об обновлении группы.
Имя вызова команды:mon_http_UpdateGroup.
Поддерживается только синхронный вызов.
Результат выполнения команды журналируется.
- На входе: UpdateGroupDTO
- На выходе: GroupDto
DeleteGroup (mon-core)
Payload для команды
"id_of_my_first_group"
Результат выполнения команды (признак успешности исполнения)
true
Удаляет группу пользователей с заданным идентифкатором. Отправляет событие об удалении группы.
Имя вызова команды:mon_http_DeleteGroup.
Поддерживается только синхронный вызов.
Результат выполнения команды журналируется.
- На входе: GroupId
- На выходе: Boolean
ListGroups (mon-core)
Payload для команды
{
"sorting": {
"fieldName": "name",
"order": "asc"
},
"paging": {
"page": 1,
"count": 20
},
"query": "modified",
"context": {
"modified": "1631707774"
}
}
Результат выполнения команды
{
"total": 2,
"items": [
{
"group": {
"id": "id_of_my_first_group",
"name": "Новое название группы на каком-то языке",
"modified": 1631707774,
"description": "Измененное описание группы"
},
"usersCount": 2
},
{
"group": {
"id": "anotherGroup",
"name": "Название группы",
"modified": 1631707774,
"description": null
},
"usersCount": 0
}
]
}
Возвращает список всех групп пользователей.
Имя вызова команды:mon_http_ListGroups.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
По умолчанию сортировка производится по полю modified модели GroupDTO.
Запрос принимает параметры сортировки, фильтров и пейджинга в параметре Search.
Применяется к полям модели GroupDTO.
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров |
|---|---|
| groupId | InSetQuery, LikeQuery |
| name | InSetQuery, LikeQuery |
| description | InSetQuery, LikeQuery |
| modified | InSetQuery, LikeQuery, RangeQuery |
Применяется отдельно к полям:
count- количество пользователей, которые состоят в группе;
| Поле | Виды фильтров |
|---|---|
| count | InSetQuery, LikeQuery, RangeQuery |
Доступные поля для сортировки:
| Поле |
|---|
| groupId |
| name |
| description |
| modified |
| count |
ListGroupsByUserId (mon-core)
Payload для команды
{
"userId": "a133f0c8-a516-4537-8f3f-915acb335e2c",
"options": {
"sorting": {
"fieldName": "name",
"order": "asc"
},
"paging": {
"page": 1,
"count": 20
},
"query": "",
"context": {}
}
}
Результат выполнения команды
{
"total": 1,
"items": [
{
"group": {
"id": "id_of_my_first_group",
"name": "Новое название группы на каком-то языке",
"modified": 1631707774,
"description": "Измененное описание группы"
},
"usersCount": 2
}
]
}
Возвращает список всех групп пользователей, в которых состоит указанный пользователь.
Имя вызова команды:mon_http_ListGroupsByUserId.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: UserIdWithOptions
- На выходе: Page[GroupInfo]
По умолчанию сортировка производится по полю modified модели GroupDTO.
Запрос принимает параметры сортировки, фильтров и пейджинга в параметре Search в поле options входных данных.
Применяется к полям модели GroupDTO.
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров |
|---|---|
| groupId | InSetQuery, LikeQuery |
| name | InSetQuery, LikeQuery |
| description | InSetQuery, LikeQuery |
| modified | InSetQuery, LikeQuery, RangeQuery |
Применяется отдельно к полям:
count- количество пользователей, которые состоят в группе;
| Поле | Виды фильтров |
|---|---|
| count | InSetQuery, LikeQuery, RangeQuery |
Доступные поля для сортировки:
| Поле |
|---|
| groupId |
| name |
| description |
| modified |
| count |
ListGroupsByUserIds (mon-core)
Payload для команды
[
"9e04e443-9478-4f19-be0f-cac81aa17c7d",
"7d21f4e6-1031-42f9-8610-d07d6b15f976",
"7d21f4e6-1031-42f9-8610-d07d6b15f977"
]
Результат выполнения команды
[
{
"user": "9e04e443-9478-4f19-be0f-cac81aa17c7d",
"groups": [
{
"id": "users",
"name": "Пользователи",
"modified": 1675845168767,
"description": "Все пользователи системы"
}
]
},
{
"user": "7d21f4e6-1031-42f9-8610-d07d6b15f976",
"groups": []
},
{
"user": "7d21f4e6-1031-42f9-8610-d07d6b15f977",
"groups": [
{
"id": "users",
"name": "Пользователи",
"modified": 1675845168767,
"description": "Все пользователи системы"
},
{
"id": "admins",
"name": "Администраторы",
"modified": 1674741697650,
"description": null
}
]
}
]
Возвращает массив объектов, каждый из которых содержит id пользователя и массив всех групп, в которых состоит пользователь.
Команда не следит за существованием переданных id пользователей. Т.е. если передать во входных данных несуществующий id, то объект с таким id (с пустым списком групп) вернется в ответе
Имя вызова команды:mon_http_ListGroupsByUserIds.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: List[UserId]
- На выходе: List[UserIdWithGroups]
ListUserIdsByGroupIds (mon-core)
Payload для команды
[
"groupId1",
"groupId2"
]
Результат выполнения команды
{
"groupId1": [
"userId1",
"userId2"
],
"groupId2": [
"userId3"
]
}
Возвращает соответствующие переданным группам ID пользователей, которые в них состоят.
Имя вызова команды:mon_http_ListUserIdsByGroupIds.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway), не требует аутентификации.
AddUsersToGroup (mon-core)
Payload для команды
{
"groupIds": [
"id_of_my_first_group"
],
"users": [
"a133f0c8-a516-4537-8f3f-915acb335e2c",
"2595becc-e4a2-4507-88bf-e0114ab6d677"
]
}
Результат выполнения команды (признак успешности исполнения)
true
Добавляет новых пользователей в существующую группу. Отправляет событие о добавлении пользователей в группу.
Имя вызова команды:mon_http_AddUsersToGroup.
Поддерживается только синхронный вызов.
Результат выполнения команды журналируется.
- На входе: UsersInGroups]
- На выходе: Boolean
RemoveUsersFromGroup (mon-core)
Payload для команды
{
"groupIds": [
"id_of_my_first_group"
],
"users": [
"a133f0c8-a516-4537-8f3f-915acb335e2c",
"2595becc-e4a2-4507-88bf-e0114ab6d677"
]
}
Результат выполнения команды (признак успешности исполнения)
true
Удаляет пользователей, которые состоят в указанной группе. Отправляет событие об удалении пользователей из группы.
Имя вызова команды:mon_http_RemoveUsersFromGroup.
Поддерживается только синхронный вызов.
Результат выполнения команды журналируется.
- На входе: UsersInGroups]
- На выходе: Boolean
GetLicenseInfo (mon-core)
Результат выполнения команды
[
{
"kind": "Dev",
"expiredAt": 1906180561111,
"properties": [
{
"key": "description",
"value": "Лицензия по функционалу сервиса, использующего библиотеку Mon-core",
"description": "Описание лицензии"
},
{
"key": "globalSessionsLimit",
"value": "-1",
"description": "Глобальное ограничение на количество одновременных сессий за определенный промежуток времени (см. sessionWatchSec). Значение, которое меньше 0, означает \"без ограничений\"."
},
{
"key": "sessionsLimitPerUser",
"value": "-1",
"description": "Ограничение на количество сессий для одного пользователя. Значение, которое меньше 0, означает \"без ограничений\"."
},
{
"key": "sessionWatchSec",
"value": "300",
"description": "Время в секундах, в течении которого сессия учитывается при подсчете доступного лимита. Значение должно быть >= 0."
},
{
"key": "privilegedEmails",
"value": "mymega@email",
"description": "Список email-ов привилегированных пользователей. На этих пользователей не распространяются лицензионные ограничения: globalSessionsLimit, sessionsLimitPerUser, activeUserLimit, allowedActions."
},
{
"key": "allowedActions",
"value": "anything,can,be,done",
"description": "Действия, которые разрешены для выполнения под лицензией. Другие действия будут автоматически запрещены."
},
{
"key": "activeUserLimit",
"value": "-1",
"description": "Глобальное ограничение на количество активированных пользователей в системе. Значение, которое меньше 0, означает \"без ограничений\"."
},
{
"key": "jwtLifeTime",
"value": null,
"description": "Время действия токена JWT в секундах. Если установлено, то перекрывает значение переменной MON_JWT_LIFETIME. Значение должно быть >= 0."
}
]
}
]
Возвращает информацию об использующейся текущей лицензии сервиса Mon-core.
Имя вызова команды:mon_http_GetLicenseInfo.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: -
- На выходе: List[LicenseInfo]
Модели сервиса Mon-core (models)
User (mon-core)
Структура, описывающая сущность "пользователь"
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
id |
UserId | Да | Идентификатор пользователя |
email |
String | Да | Уникальный email пользователя |
status |
UserStatus | Да | Статус пользователя в виде строки |
info |
UserInfo | Нет | Опциональная информация о пользователе |
modified |
TimeStamp | Да | Время в миллисекундах последнего изменения полей id, email или status |
modifiedBy |
UserId | Нет | Пользователь, инициировавший последнее изменение полей id, email или status |
reason |
String | Нет | Причина последнего изменения полей id, email или status |
deactivateAt |
TimeStamp | Нет | Время в миллисекундах, после которого пользователь при попытке LoginByCredentials будет деактивирован |
UserInfo (mon-core)
Дополнительная информация о пользователе.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
firstName |
String | Нет | Имя пользователя |
lastName |
String | Нет | Фамилия пользователя |
middleName |
String | Нет | Отчество пользователя |
data |
Json | Нет | Дополнительные данные профиля пользователя |
UserRegistrationInfo (mon-core)
Дополнительная информация о пользователе, которая используется только при регистрации.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
firstName |
String | Да | Имя пользователя |
lastName |
String | Да | Фамилия пользователя |
middleName |
String | Нет | Отчество пользователя |
data |
Json | Нет | Дополнительные данные профиля пользователя |
UserStatus (mon-core)
Список вариантов статуса пользователя в системе. Имеет тип String.
| Название | Описание |
|---|---|
Pending |
Пользователь, ожидающий подтверждения регистрации |
Activated |
Обычный пользователь системы (выполнивший все условия/требования после регистрации) |
Deactivated |
Заблокированный пользователь системы |
UserWithGroupCount (mon-core)
Информация о пользователе и количестве групп, в которых он состоит.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
user |
User | Да | Пользователь |
groupsCount |
Int | Да | Количество групп, в которых состоит пользователь |
LoginCredentials (mon-core)
Данные необходимые для выполнения входа пользователя в систему
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
email |
String | Да | Email пользователя |
password |
String | Да | Пароль пользователя |
SuccessAuthentication (mon-core)
Результат, указывающий на успешный вход пользователя в систему. Содержит JWT.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
accessToken |
String | Да | JWT в виде строки |
expiresIn |
Int | Да | Время жизни JWT в секундах |
UserRegistrationDto (mon-core)
Данные, необходимые для регистрации пользователя в системе.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
email |
String | Да | Email пользователя |
password |
String | Да | Пароль, который будет использован для аутентификации |
info |
UserRegistrationInfo | Да | Дополнительная информация о пользователе |
notificationUrl |
String | Нет | URL, который нужно отправить в письме пользователю |
UserRegistrationResult (mon-core)
Результат, указывающий на успешный вход пользователя в систему. Содержит JWT.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
userId |
UserId | Да | Идентификатор группы пользователей |
verificationRequested |
Boolean | Да | Признак того, что было отправлено письмо для подтверждения регистрации |
ActionTokenId (mon-core)
Идентификатор токена (UUIDv4) для какого-либо действия.
В данный момент, доступно только 1 действие - подтверждение
регистрации пользователя. Вид действия для которого был создан токен определяется с помощью типа ActionTokenKind (
название вида токена, представлен в виде строки).
GroupDTO (mon-core)
Структура для описания группы пользователей
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
id |
GroupId | Да | Идентификатор группы пользователей |
name |
String | Да | Название группы для отображения (любая строка) |
modified |
TimeStamp | Да | Представляет время (UTC) в миллисекундах от 01.01.1970 |
description |
String | Нет | Описание группы |
UpdateGroupDTO (mon-core)
Структура для передачи измененных атрибутов группы пользователей
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
id |
GroupId | Да | Идентификатор группы пользователей | для CreateGroup:- уникальное значение для UpdateGroup:- существующее значение |
name |
String | Да | Название группы для отображения (любая строка) | |
description |
String | Нет | Описание группы |
UpdateDeactivationTimeInput (mon-core)
Структура для передачи данных для обновления времени деактивации аккаунта
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
userIds |
List[UserId] | Да | Список идентификаторов пользователей | |
newDeactivateAt |
TimeStamp | Нет | Представляет время (UTC) в миллисекундах от 01.01.1970 | |
reason |
String | Нет | Описание причины изменения |
UpdateResponse (mon-core)
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
updated |
Int | Да | Количество обновленных элементов |
GroupInfo (mon-core)
Информация о группе пользователей и количестве ее участников
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
group |
GroupDTO | Да | Информация о группе пользователей |
usersCount |
Int | Да | Количество пользователей в группе |
UsersInGroups (mon-core)
Структура для оперирования некоторыми пользователями из группы пользователей
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
groupId |
List[GroupId] | Да | Список идентификаторов групп пользователей | |
users |
List[UserId] | Да | Список идентификаторов пользователей |
UserIdWithOptions (mon-core)
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
userId |
UserId | Да | Идентификатор пользователя | |
options |
Search | Нет | Опции для списка |
UserIdWithStatus (mon-core)
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
userId |
UserId | Да | Идентификатор пользователя | |
status |
UserStatus | Да | Статус пользователя |
UserIdWithInfo (mon-core)
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
id |
UserId | Да | Идентификатор пользователя | |
info |
UserInfo | Да | Информация о пользователе |
UserIdWithEmail (mon-core)
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
id |
UserId | Да | Идентификатор пользователя |
email |
String | Да | Email пользователя |
GroupIdWithOptions (mon-core)
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
groupId |
GroupId | Да | Идентификатор группы пользователей | |
options |
Search | Нет | Опции для списка |
QueryParameters (mon-core)
Структура для передачи параметров, которые обычно должны быть переданы в качестве query string (например при входе по OpenID Connect провайдерам)
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
queryParameters |
Json | Да | Json-объект со строковыми значениями, являющийся перечнем query string параметров |
ChangePasswordDto (mon-core)
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
oldPassword |
String | Да | Текущий пароль пользователя | |
newPassword |
String | Да | Желаемый пароль пользователя |
PasswordRecoverRequestDto (mon-core)
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
email |
String | Да | Логин пользователя | |
notificationUrl |
String | Нет | URL, который нужно отправить в письме пользователю |
CheckTokenDto (mon-core)
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
actionTokenId |
uuid | Да | Идентификатор токена |
RecoverPasswordByTokenDto (mon-core)
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
token |
uuid | Да | Идентификатор токена | |
newPassword |
String | Да | Желаемый пароль пользователя |
UserAttributesMapping (mon-core)
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
firstName |
String | Да | Настройка маппинга атрибутов для поля UserInfo.firstName. Строка в формате AttributeMapping. |
lastName |
String | Да | Настройка маппинга атрибутов для поля UserInfo.lastName. Строка в формате AttributeMapping. |
middleName |
String | Да | Настройка маппинга атрибутов для поля UserInfo.middleName. Строка в формате AttributeMapping. |
email |
String | Да | Настройка маппинга атрибутов для поля User.email. Строка в формате AttributeMapping. |
AttributeParsingSettings (mon-core)
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
attribute |
String | Да | Название атрибута, из которого нужно использовать значение. Регистр не учитывается. |
position |
Int | Нет | Индекс сегмента, который нужно использовать из значения атрибута, если значение атрибута было разделено. Если указано поле delimiter, то это поле становится обязательным. |
delimiter |
String | Нет | Символ, по которому будет разделено значение атрибута. Если указано поле position, то это поле становится обязательным. |
limit |
Int | Нет | Максимальное количество сегментов, на которое нужно разделить значение атрибута. Если не задано, то количество сегментов не ограничено. |
UserIdWithGroups (mon-core)
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
user |
UserId | Да | Идентификатор пользователя |
groups |
List[GroupDTO] | Да | Массив групп пользователя |
UserWithGroups (mon-core)
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
user |
User | Да | Идентификатор пользователя |
groups |
List[GroupIdTitle] | Да | Массив групп пользователя |
GroupIdTitle (mon-core)
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
groupId |
GroupId | Да | Идентификатор группы |
name |
Title | Да | Имя группы |
LicenseInfo (mon-core)
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
kind |
String | Да | Вид лицензии |
expiredAt |
Int | Да | Время, когда лицензия истекает |
properties |
List[LicenseProperty] | Да | Список параметров модели LicenseDTO |
LicenseProperty (mon-core)
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
key |
String | Да | Название свойства лицензии |
value |
String | Нет | Значение свойства лицензии |
description |
String | Нет | Описание свойства. Значения для каждого свойства зафиксировано в таблице ниже |
Таблица значений поля description
Значение поля description для каждого свойства лицензии зафиксировано в коде:
key |
description |
|---|---|
description |
Описание лицензии. |
globalSessionsLimit |
Глобальное ограничение на количество одновременных сессий за определенный промежуток времени (см. sessionWatchSec). Значение, которое меньше 0, означает "без ограничений". |
sessionsLimitPerUser |
Ограничение на количество сессий для одного пользователя. Значение, которое меньше 0, означает "без ограничений". |
sessionWatchSec |
Время в секундах, в течении которого сессия учитывается при подсчете доступного лимита. Значение должно быть >= 0. |
privilegedEmails |
Список email-ов привилегированных пользователей. На этих пользователей не распространяются лицензионные ограничения: globalSessionsLimit, sessionsLimitPerUser, activeUserLimit, allowedActions. |
allowedActions |
Действия, которые разрешены для выполнения под лицензией. Другие действия будут автоматически запрещены. |
activeUserLimit |
Глобальное ограничение на количество активированных пользователей в системе. Значение, которое меньше 0, означает "без ограничений". |
jwtLifeTime |
Время действия токена JWT в секундах. Если установлено, то перекрывает значение переменной MON_JWT_LIFETIME. Значение должно быть >= 0. |
ActiveDirectory groups mapping (mon-core)
Для указания маппинга групп используются формат ADName=MonName, где
"ADName" может быть или GroupSID или Base64 строкой. "MonName" может быть только GroupId сервиса Mon.
Пример: S-1-5-21-4036403032-2978644966-1872548419-1100=TechAdmins;AQUAAAAAAAUVAAAAWJ+W8OaDirFD0pxvUgQAAA===Users.
Чтобы посмотреть информацию о группе, можно использовать команду
ldapsearch -H ldap://10.168.22.245 -x -W -D "tester@dev.embedika.ru" -b "dc=dev,dc=embedika,dc=ru" "(sAMAccountName=sso)",
где
10.168.22.245 - адрес AD,
tester@dev.embedika.ru - пользователь AD, от которого делается запрос (должен иметь доступ к просмотру группы),
sso - название группы.
В ответе, нас интересует поле objectSid.
Пример ответа ldapsearch
# sso, Users, dev.embedika.ru
dn: CN=sso,CN=Users,DC=dev,DC=embedika,DC=ru
objectClass: top
objectClass: group
cn: sso
member:: Q0490KTRgNC+0L3RgtC10L3QtNC10YAsQ049VXNlcnMsREM9ZGV2LERDPWVtYmVkaWthLERDPXJ1
member:: Q0490KLQtdGB0YLQtdGALENOPVVzZXJzLERDPWRldixEQz1lbWJlZGlrYSxEQz1ydQ==
distinguishedName: CN=sso,CN=Users,DC=dev,DC=embedika,DC=ru
instanceType: 4
whenCreated: 20221129100547.0Z
whenChanged: 20221129100626.0Z
uSNCreated: 12851
uSNChanged: 12857
name: sso
objectGUID:: +4z7l0Mwe0qRQohm48uhCw==
objectSid:: AQUAAAAAAAUVAAAAWJ+W8OaDirFD0pxvUgQAAA==
sAMAccountName: sso
sAMAccountType: 268435456
groupType: -2147483646
objectCategory: CN=Group,CN=Schema,CN=Configuration,DC=dev,DC=embedika,DC=ru
dSCorePropagationData: 16010101000000.0Z
# search reference
ref: ldap://ForestDnsZones.dev.embedika.ru/DC=ForestDnsZones,DC=dev,DC=embedika,DC=ru
# search reference
ref: ldap://DomainDnsZones.dev.embedika.ru/DC=DomainDnsZones,DC=dev,DC=embedika,DC=ru
# search reference
ref: ldap://dev.embedika.ru/CN=Configuration,DC=dev,DC=embedika,DC=ru
# search result
search: 2
result: 0 Success
# numResponses: 5
# numEntries: 1
# numReferences: 3
External profile attributes mapping (mon-core)
Для указания атрибутов профиля из внешнего хранилища (ActiveDirectory, Keycloak и т.п.), из которых нужно получить значения для профиля пользователя (например, для полей User или UserInfo), используется JSON массив со списком настроек. Каждый элемент массива является строкой со структурой AttributeParsingSettings.
Формат строки со структурой AttributeParsingSettings:
"attributeName;position;delimiter;limit",
где ; является разделителем между полями структуры. Пробелы игнорируются для всех полей, кроме delimiter (данное поле
может содержать пробелы).
Указание названия атрибута с разделителем может пригодиться, если нужно использовать только какой-то сегмент (по индексу
из поля position), а не все значение. В качестве примера можно привести атрибут displayName, который содержит ФИО, и
поле UserInfo.firstName, для которого требуется только Имя:
Атрибут: "displayName"
Значение атрибута: "Толстой Алексей Константинович"
Маппинг: "displayName; 1; ", где displayName - название атрибута, 1 - индекс сегмента (начиная с 0), (
пробел) - разделитель для сегментов. Limit сегментов не указан, т.к. опционален.
Выделение сегмента из значения атрибута реализовано через
java-вый String.split(delimiter, limit).
Особенности:
- Регистр названия атрибута не учитывается.
- Если указывается поле "position", то "delimiter" тоже нужно указывать (и наоборот).
Примеры строк с AttributeParsingSettings:
AttributeParsingSettings("mail", None, None, None)->"mail"При маппинге будет использовано значение из атрибута "mail" без изменений.AttributeParsingSettings("cn", Some(0), Some(" "), None)->"cn;0; ". При маппинге значение из атрибута "cn" будет разделено по символу" "и, из получившегося списка, будет использован первый элемент.AttributeParsingSettings("displayName", Some(2), Some(" "), Some(3))->"displayName; 2; ; 3". При маппинге значение из "displayName" будет разделено по символу" "с ограничением по длине списка в три элемента. Из получившегося списка будет использован третий элемент.
Примеры массива с настройками:
["surName"]["lastName", "sn", "cn;2; ;3", "displayName; 2; ; 3"]
Требования к настройкам клиента Keycloak (mon-core)
- Должны использоваться
Client Type = OpenId ConnectсAuthentication Flow = Standart Flow Client Authenticationдолжно быть включено, типCredentialsдолжен бытьClient Id and Secret.- Должен быть настроен
Valid redirect URIs, соответствующий URL, по которому фронт-энд отрабатывает коллбек от Keycloak. Пример такого URL:https://verdi.dev/keycloak-callback*(звездочка на конце необходима, чтобы можно было передавать query string параметры)
Требования к настройке notification limit (mon-core)
Notification limit - это проверка того, что команды порождающие отправку email, не отправляют email одному пользователю дважды. Для того чтобы осуществить эту проверку, требуется идентифицировать пользователя.
Сейчас существует 2 команды порождающие отправку email: mon_http_RegisterUser и mon_http_PasswordRecoverRequest.
В команде mon_http_PasswordRecoverRequest идентификация пользователя производится с помощью email, который передается на вход команде. По email из базы данных извлекается userId и используется как идентификатор.
В команде mon_http_RegisterUser идентификация пользователя производится с помощью связки IP-адрес пользователя + некоторые дополнительные заголовки, поступившие вместе с запросом пользователя. Если что-то из этого(IP либо какой-то из дополнительных заголовков) в запросе найдено не было, выполнение команды завершается ошибкой превышения лимитов. Список дополнительных заголовков можно указать в настройке NotificationSettings.additionalIdentityHeaders.
Замечание: при отсутствии у клиента заголовка User-Agent apigateway генерирует свой заголовок вида User-Agent: akka-http/10.2.10, поэтому клиент без User-Agent сможет первый раз выполнить команду.
IP-адрес пользователя поочередно ищется в заголовках X-Forwarded-For, X-Real-Ip и Forwarded и проверяется на то, является ли полученный заголовок валидным IP. Используется первый полученный таким образом IP.
Замечание: использование такого подхода подразумевает,
что прокси, получающие запрос пользователя, должны убедиться,
что заголовки X-Forwarded-For, X-Real-Ip и Forwarded
генерируются прокси, а не пробрасываются из запроса пользователя.
При этом если прокси передает заголовок X-Forwarded-For,
то достаточно убедиться, что был перезаписан именно он.
Но если прокси не передает заголовки X-Forwarded-For и X-Real-Ip, а
использует только Forwarded, ему кроме перезаписи Forwarded,
нужно также отфильтровать возможные клиентские заголовки X-Forwarded-For и X-Real-Ip.
Замечание: http-заголовки регистронезависимы, поэтому нужно также запретить пробрасывание от пользователя любых вариаций разных регистров, например X-ForWARDed-For
Mon (門): сервис аутентификации
Сервис аутентификации отвечает за создание пользователей и вход пользователей в систему. Данные сервиса хранятся в PostgreSQL. Команды могут приходить только по HTTP.
Сервис разбит на несколько модулей, в виде sbt проектов:
domain, в котором содержатся все доменные модели и их различные представления.infrastructure, в котором содержатся базовые компоненты для взаимодействия с инфраструктурой.store, содержит сервисы для сохранения и чтения из разных хранилищ доменных моделей.service, содержит сервисы бизнес логики, которые определяют правила взаимодействия компонентов между собой.route, содержит HTTP роуты.boot, содержит зависимости и описание для сборки и запуска сервиса.
Конфигурирование Mon
Требования к запуску Mon
Запуск локально из консоли с помощью SBT
MON_DB_HOST=localhost
MON_DB_PORT=5432
MON_DB_NAME=mon_db
MON_DB_USER=postgres
MON_DB_PASSWORD=postgres
MON_JWT_SIGNATURE=secretjwtstring
sbt boot/run
При запуске сервиса локально ожидается, что уже развернута необходимая инфраструктура:
- PostgreSQL база по адресу
{MON_DB_HOST}:{MON_DB_PORT}/{MON_DB_NAME}(localhost:5432/mon_db, если запуск как в примере) - Kafka по адресу
localhost:9092 - Consul по адресу
localhost:8500 - AuthZforce server по адресу
http://localhost:8080/authzforce-ce - По пути
MON_LICENSE_PATHлежит бинарный файл лицензии, подписанный с помощьюMON_LICENSE_KEY - Запущен инстанс сервиса
tech-constants
Конфигурирование Mon через Consul
В Consul можно добавить следующие ключи:
- адрес AuthZforce по ключу
authzforce_server_address(иначе будет взят адрес из переменной окруженияMON_AUTHZFORCE_ADDR)- В рантайме, исходя из наличия адреса AuthZforce, будет попытка получить доступный DomainID для AuthZforce из AuthZforce
- Иначе DomainID будет взят из переменной окружения
MON_AUTHZFORCE_DOMAIN - Если
MON_AUTHZFORCE_DOMAINбудет равен пустой строке, то приMON_AUTHORIZER_KIND= "authzforce", сервис не сможет запуститься
Список всех переменных окружения для сервиса Mon
| Переменная | Тип | Обязательная | Значение по умолчанию | Описание |
|---|---|---|---|---|
MON_HTTP_HOST |
string | Нет | 0.0.0.0 |
Хост для HttpListener. |
MON_HTTP_PORT |
int | Нет | 8192 |
Порт для HttpListener. |
MON_KAFKA_SERVERS |
string | Да | localhost:9092 |
Адрес Kafka. |
MON_KAFKA_TOPIC |
string | Нет | MON_commands |
Название топика для входящих команд. |
MON_KAFKA_PARTITIONS |
int | Нет | 10 |
Количество партиций в топике команд. |
MON_KAFKA_COMMANDEVENT_TOPIC |
string | Нет | commandevents |
Название топика для входящих/исходящих событий. |
MON_KAFKA_USEREVENT_TOPIC |
string | Нет | userEvents |
Название топика для отправки событий о действиях с пользователями. |
MON_KAFKA_CONSUMER_RESTART_MIN_BACKOFF |
duration string | Нет | 1 second |
Минимальная задержка перед перезапуском. |
MON_KAFKA_CONSUMER_RESTART_MAX_BACKOFF |
duration string | Нет | 30 seconds |
Максимально возможная задержка перед перезапуском. |
MON_KAFKA_CONSUMER_RESTART_RANDOM_FACTOR |
double | Нет | 0.2 |
Коэффициент величины дополнительной случайной задержки(jitter) относительно основной задержки (При значении 0.2 задержка может быть до 20% больше, чем при 0). Если после умножения задержки на MON_KAFKA_CONSUMER_RESTART_RANDOM_FACTOR получится меньше 1 миллисекунды, то jitter будет приравнен к нулю. |
MON_KAFKA_CONSUMER_RESTART_MAX_RESTARTS |
int | Нет | 5 |
Максимальное количество перезапусков в заданный период времени. После превышения этого числа сервис будет объявлен больным. Все рестарты для каждого отдельного сообщения увеличивают и общий счетчик рестартов консьюмера, поэтому при использовании MON_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS нужно указывать MON_KAFKA_CONSUMER_RESTART_MAX_RESTARTS > MON_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS или не указывать MON_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS совсем. |
MON_KAFKA_CONSUMER_RESTART_MAX_RESTARTS_WITHIN |
duration string | Нет | 5 minutes |
Период времени для ограничения перезапусков. |
MON_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS |
int | Нет | 2 |
Максимальное количество раз, которое консьюмер перезапустится с неизменной очередью сообщений(в пределах DATA_MODEL_KAFKA_CONSUMER_RESTART_MAX_RESTARTS_WITHIN), прежде чем проигнорировать сообщение, на котором происходит ошибка (Указано количество рестартов, а не прочтений. Если MON_KAFKA_CONSUMER_RESTART_MAX_RESTARTS = 2, то ошибочное сообщение будет обработано 3 раза, после чего произойдет 3ий рестарт и оно будет проигнорировано). Если указать 0, то перезапуск произойдет, но сообщение будет обработано только в первый раз, когда произошла ошибка. Если указать значение меньше 0, то перезапуски все равно будут происходить, но игнорирование сообщений, вызывающих ошибку, будет отключено. |
MON_KAFKA_CONSUMER_PER_MESSAGE_RESTART_CACHE_SIZE |
int | Нет | 100 |
Для каждого сообщения счетчик перепрочтений хранится в кэше. Максимальное количество значений в этом кэше. |
MON_KAFKA_CONSUMER_PER_MESSAGE_RESTART_CACHE_TTL |
duration string | Нет | 5 minutes |
Для каждого сообщения счетчик перепрочтений хранится в кэше.Максимальное время жизни элемента в этом кэше. В случае отсутствия значения время жизни элемента не будет ограничено. |
MON_KAFKA_CONSUMER_POLL_TIMEOUT |
duration string | нет | 10 milliseconds | timeout запроса poll для kafka consumer |
MON_KAFKA_CONSUMER_POLL_INTERVAL |
duration string | нет | 100 milliseconds | интервал между запросами poll для kafka consumer |
MON_KAFKA_CONSUMER_PROPS |
string | нет | "max.poll.records=500;max.partition.fetch.bytes=524288" | дополнительные параметры для kafka consumer в формате "key1=value1;key2=value2" |
MON_KAFKA_AUTH_USER |
string | Нет | "" |
Название учетной записи Kafka. Если название не указано, то настройки авторизации не будут применены. |
MON_KAFKA_AUTH_PASSWORD |
string | Нет | "" |
Пароль учетной записи Kafka. |
MON_KAFKA_AUTH_TRUSTSTORE_LOCATION |
string | Нет | "" |
Путь до хранилища сертификатов (Java key store). Если путь не указан, то сертификат применяться не будет. |
MON_KAFKA_AUTH_TRUSTSTORE_PASSWORD |
string | Нет | "" |
Пароль к хранилищу сертификатов. |
MON_KAFKA_AUTH_MODE |
string | Нет | static |
Режим аутентификации: static - одна учетная запись на все запросы, mapping - учетная запись зависит от запроса. |
MON_KAFKA_AUTH_CONFIG |
string | Нет | "" |
Настройки для аутентификации: если AuthMode = mapping, то необходим JSON с List[KafkaAuthConfig]. Переменная соответствует полю authConfig из KafkaAuthSettings. |
MON_KAFKA_AUTH_CACHE_SIZE |
int | Нет | Максимальный размер кеша для Kafka producer (количество активных соединений). | |
MON_KAFKA_CONNECTION_CHECK_TEST_MESSAGES_INTERVAL |
duration string | Нет | 4 minutes |
Применяется только для producer-ов со способом аутентификации kerberos. Интервал отправки тестовых сообщений кафки в топик connectionCheck.testMessagesTopicName. Тестовые сообщения (null, service producer test) отправляются регулярно с этим интервалом. |
MON_KAFKA_CONNECTION_CHECK_INTERVAL |
duration string | Нет | 60 seconds |
Применяется только для producer-ов со способом аутентификации kerberos. Интервал проверки того, сколько тестовых сообщений было отправлено за данный период. Если количество сообщений за этот период равно количеству сообщений за прошлый период, то начинается отсчет периода без сообщений. |
MON_KAFKA_CONNECTION_CHECK_FAILED_AFTER_INTERVAL |
duration string | Нет | 5 minutes |
Применяется только для producer-ов со способом аутентификации kerberos. Максимальная продолжительность периода без успешно отправленных тестовых сообщений. По ее достижении сервис будет объявлен больным. |
MON_KAFKA_AUTH_CACHE_TTL |
duration string | Нет | Время жизни Kafka producer в кеше. | |
MON_CONSUL_ADDR |
string | Да | http://localhost:8500 |
Адрес Сonsul. |
MON_CONSUL_AUTH_USER |
string | Нет | "" |
Название учетной записи Сonsul. Если название не указано, то настройки авторизации не будут применены. |
MON_CONSUL_AUTH_PASSWORD |
string | Нет | "" |
Пароль учетной записи Сonsul. |
MON_KAFKA_AUTH_PRINCIPAL |
string | Нет | "" |
Principal учетной записи Kafka в Kerberos(в случае соединения с kafka через Kerberos). |
MON_KAFKA_AUTH_KEYTAB_PATH |
string | Нет | "" |
Путь до keytab-файла(в случае соединения с kafka через Kerberos). |
MON_AUTHORIZER_KIND |
string | Нет | authzforce |
Вид авторизатора, который используется в сервисе. Допустимые значения: "authzforce", "oberto". При указании неизвестного значения будет использовано значение по-умолчанию. |
MON_AUTHZFORCE_ADDR |
string | Да | http://localhost:8080/authzforce-ce |
Адрес AuthZforce server. |
MON_AUTHZFORCE_DOMAIN |
string | Нет | Доступный DomainID в AuthZforce server. | |
MON_TRACE_DURATION |
boolean | Нет | false |
Нужно ли логировать длительность выполнения команд. |
MON_USERGROUP_DEFAULT |
string | Нет | "" |
Список групп пользователей, в которые необходимо добавлять новых пользователей (группы по-умолчанию). Список групп задается в виде одной строки, в которой пары GroupId и названия записываются так "id1,name1;id2,name2". Пустая строка = "никакие группы добавлять не нужно". |
MON_JWT_SIGNATURE |
string | Да | "" |
Сигнатура для подписи и расшифровки jwt-токенов, используемых для аутентификации. |
MON_JWT_LIFETIME |
duration string | Нет | 12 hours |
Время действия токена JWT. |
MON_JWT_COOKIE_EXPIRE_OFFSET |
duration string | Нет | 24 hours |
Cookie c jwt, которое выдается некоторыми командами mon, живет дольше, чем сам jwt, содержащийся внутри этой cookie. Переменная определяет то, на сколько срок жизни cookie превышает срок жизни jwt. |
MON_PASSWORD_RECOVERY_URL |
url string | Нет | http://localhost:8080/change-password?token=[[token]] |
Префикс URL используемый при генерации ссылки восстановления пароля. |
MON_VERIFICATION_TTL |
duration string | Нет | 1 day |
Время действия токена подтверждения регистрации. |
MON_RECOVERY_TTL |
duration string | Нет | 1 day |
Время действия токена восстановления пароля. |
MON_EXTERNAL_VERIFY_ENABLED |
boolean | Нет | false |
Проверять ли Email пользователя при регистрации. |
MON_EXTERNAL_VERIFY_REASON |
string | Нет | Registration confirmed |
Текст сообщения о причине изменения пользователя, который будет фиксироваться в БД при подтверждении Email при верификации зарегистрированного пользователя командой VerifyUserRegistration. |
MON_EXTERNAL_VERIFY_URL |
url string | Нет | http://localhost:8080/verify-user?token=[[token]] |
URL из письма для верификации. |
MON_NOTIFICATION_URL_REGEXPS |
string | Нет | http://localhost:8080/verify-user\\?token=\\[\\[token\\]\\] |
Набор регулярных выражений, разделенных ";", для проверки переданного в запросе notificationUrl. Формат соответствует scala строке для regexp (потому и двойное экранирование слешей "\"). |
MON_DISCOVERABLE_ID |
string | Нет | another_mon_instance |
ID данного сервиса. |
MON_DISCOVERABLE_NAME |
string | Нет | mon |
Название группы сервисов к которой принадлежит данный. |
MON_DISCOVERABLE_HOST |
string | Да | localhost |
Адрес текущего инстанса сервиса, который будет виден через ServiceDiscovery. |
MON_DISCOVERABLE_PORT |
int | Нет | ${MON_HTTP_PORT} |
Порт текущего инстанса сервиса, который будет виден через ServiceDiscovery. |
MON_DISCOVERABLE_LIVETIME |
duration string | Нет | 2 minutes |
Время с последнего HealthCheck, в течении которого сервис считается "живым". |
MON_DISCOVERABLE_HEALTHPASS |
duration string | Нет | 1 minute |
Периодичность отправки HealthCheck. |
MON_INTERNALCMD_ALLOW |
boolean | Нет | false |
Возможно ли сервису отправлять "внутренние" команды. |
MON_SENDERLIB_CONSIDER_ALL_COMMANDS_AS_INTERNAL |
boolean | Нет | false |
Флаг, определяющий будут ли все обращения в другие сервисы являться внутренними (т.е. не требовать авторизацию). Детальное описание механизма: Внутренние команды. |
MON_SENDERLIB_COMMANDS_CACHE_UPDATEPERIOD |
duration string | Нет | 10 minutes |
Время на которое будут кешироваться данные о командах. |
MON_SENDERLIB_SERVICES_CACHE_UPDATEPERIOD |
duration string | Нет | 30 seconds |
Время на которое будут кешироваться данные о сервисах. |
MON_DB_HOST |
string | Да | Хост сервера базы данных. | |
MON_DB_PORT |
int | Да | Порт сервера базы данных. | |
MON_DB_NAME |
string | Да | Название базы. | |
MON_DB_USER |
string | Да | Пользователь для базы данных. | |
MON_DB_PASSWORD |
string | Да | Пароль для пользователь для базы данных. | |
MON_DB_THREADS |
int | Нет | 10 |
Количество потоков в пуле потоков для соединения с БД. |
MON_DB_QUEUE_SIZE |
int | Нет | 300 |
Размер очереди для действий базы данных, которые не могут быть выполнены немедленно, когда все потоки заняты. За пределами этого значения новые действия немедленно завершаются неудачей. |
MON_DB_CONN_MAX |
int | Нет | 10 |
Максимальное количество одновременных подключений к БД. |
MON_DB_CONN_TIMEOUT |
duration string | Нет | 20 second |
Максимальное время ожидания ответа для соединения к БД. Если это время превышено, а соединение не становится доступным, будет брошено исключение SQLException. 1000 мс — минимальное значение. |
MON_DB_ISOLATION |
string | Нет | READ_COMMITTED |
Уровень изоляции транзакций для новых подключений. Допустимые значения: NONE, READ_COMMITTED, READ_UNCOMMITTED, REPEATABLE_READ, SERIALIZABLE. |
MON_DB_READONLY |
boolean | Нет | false |
Read-only SQL транзакция может изменять только временные таблицы. Этот параметр управляет статусом «только для чтения» по умолчанию для каждой новой транзакции. |
MON_DB_CONN_MIN |
int | Нет | ${MON_DB_THREADS} |
Минимальное количество одновременных подключений к БД. |
MON_DB_VALIDATION_TIMEOUT |
duration string | Нет | 1 seconds |
Максимальное время, в течение которого соединение будет проверяться на работоспособность. 1000 мс — минимальное значение. |
MON_DB_IDLE_TIMEOUT |
duration string | Нет | 10 minutes |
Максимальное время, в течение которого соединению разрешено простаивать в пуле. Значение 0 означает, что простаивающие соединения никогда не удаляются из пула. |
MON_DB_MAX_LIFETIME |
duration string | Нет | 30 minutes |
Максимальное время жизни соединения в пуле. Когда простаивающее соединение достигает этого времени ожидания, даже если оно недавно использовалось, оно будет удалено из пула. Значение 0 указывает на отсутствие максимального срока службы. |
MON_DB_INITIALIZATION_FAIL_FAST |
boolean | Нет | false |
Deprecated, начиная с версии Slick 3.3.0. Определяет, будет ли пул «быстро выходить из строя», если пул не может быть успешно заполнен начальными соединениями. Если соединения не могут быть созданы во время запуска пула, будет выдано исключение RuntimeException. Это свойство не имеет никакого эффекта, если minConnections равно 0. |
MON_DB_LEAK_DETECTION_THRESHOLD |
int | Нет | 0 |
Время, в течение которого соединение может находиться вне пула, прежде чем будет зарегистрировано сообщение, указывающее на возможную утечку соединения. Значение 0 означает, что обнаружение утечек отключено. Наименьшее приемлемое значение для включения обнаружения утечек составляет 10 с. |
MON_DB_CONNECTION_TEST_QUERY |
string | Нет | SELECT 1 |
Выражение, которое будет выполнено непосредственно перед получением соединения из пула для проверки того, что соединение с базой данных все еще активно. Оно зависит от базы данных и должно представлять собой запрос, требующий минимальной обработки базой данных (например, «VALUES 1»). Если этот параметр не установлен, вместо него используется метод JDBC4 Connection.isValid(). |
MON_DB_REGISTER_MBEANS |
boolean | Нет | false |
Зарегистрированы ли JMX Management Beans («MBeans»). |
MON_DB_AUTO_COMMIT |
boolean | Нет | true |
Это свойство определяет то, как будут вести себя по умолчанию возвращаемые соединения относительно autocommit-а. |
MON_DB_SCHEMA |
string | Нет | public |
Устанавливает schema по умолчанию. |
MON_DB_ISOLATE_INTERNAL_QUERIES |
boolean | Нет | false |
Определяет то, изолируются ли с помощью транзакций внутренние запросы пула(например запрос connection alive test). Свойство применяется только если autoCommit выключен. |
MON_DB_INITIALIZATION_FAIL_TIMEOUT |
int | Нет | 1 |
Работает, начиная с версии Slick 3.3.0. Определяет, будет ли пул «быстро выходить из строя», если пул не может быть успешно заполнен начальными соединениями. Любое положительное число считается числом миллисекунд для попытки получить начальное соединение; поток приложения будет заблокирован в течение этого периода. Если соединение не может быть получено до истечения этого времени, будет брошено исключение. Данный таймаут применяется после периода connectionTimeout. Если значение равно нулю (0), HikariCP попытается получить и проверить подключение. Если соединение получено, но проверка не пройдена, будет брошено исключение, и пул не будет запущен. Однако, если соединение не может быть получено, пул запустится, но последующие попытки получить соединение могут потерпеть неудачу. Значение меньше нуля пройдет любую первоначальную попытку подключения, и пул немедленно запустится, пытаясь получить соединения в фоновом режиме. Следовательно, последующие попытки получить соединение могут потерпеть неудачу. |
MON_READABLE_NAME |
string | Нет | Сервис пользователей |
Читаемое название этого сервиса. |
MON_DESCRIPTION |
string | Нет | Предназначен для определения схемы и хранения объектов |
Читаемое описание этого сервиса. |
MON_AUTHN_EXTERNAL_SESSION_LIFETIME |
duration string | Нет | 10 minutes |
Продолжительность внешней сессии (например, в случае сессии, хранящей данные о процессе OpenId Connect аутентификации - время, за которое пользователь должен завершить вход после получения ссылки на форму входа). |
MON_KRB_SVC_PRINCIPAL |
string | Нет | "" |
ID сервера в ActiveDirectory (если значение отсутствует/пустое, то Kerberos authentication не будет работать). |
MON_KRB_SVC_KEYTAB |
string | Нет | "" |
Путь к keytab файлу для MON_KRB_SVC_PRINCIPAL с настройками доступа к ActiveDirectory (если значение отсутствует/пустое, то Kerberos authentication не будет работать). |
MON_KRB_CALLBACK_URL |
string | Нет | "" |
Callback URL для редиректа после Kerberos authentication (в версии <= 1.6 не используется?) (если значение отсутствует/пустое, то Kerberos authentication не будет работать). |
MON_KRB_DEBUG |
boolean | Нет | false |
Debug логгирование Kerberos authentication в сторонней библиотеке. |
MON_KRB_LDAP_HOST |
string | Нет | localhost |
Хост ActiveDirectory (LDAP протокол) (если значение отсутствует/пустое, то Kerberos authentication не будет работать). Пример: "cloud.dev.embedika.ru". |
MON_KRB_LDAP_PORT |
int | Нет | 389 |
Порт ActiveDirectory (LDAP протокол) (если значение отсутствует/некорректное (port < 1), то Kerberos authentication не будет работать). |
MON_KRB_LDAP_BIND_USER |
string | Нет | "" |
Имя пользователя для привязки всех запросов в ActiveDirectory (если значение отсутствует/пустое, то Kerberos authentication не будет работать). Пример: "cn=Verdi Dev,cn=Users,dc=dev,dc=embedika,dc=ru". |
MON_KRB_LDAP_BIND_CREDS |
string | Нет | "" |
Пароль для MON_KRB_LDAP_BIND_USER (если значение отсутствует/пустое, то Kerberos authentication не будет работать). |
MON_KRB_LDAP_SERVER_BASE_DN |
string | Нет | "" |
Базовый DN в ActiveDirectory для всех объектов (если значение отсутствует/пустое, то Kerberos authentication не будет работать). Пример: "dc=dev,dc=embedika,rc=ru". |
MON_KRB_LDAP_CONNPOOL_SIZE_MIN |
int | Нет | 2 |
Минимальный размер пула подключений к ActiveDirectory. |
MON_KRB_LDAP_CONNPOOL_SIZE_MAX |
int | Нет | 128 |
Максимальный размер пула подключений к ActiveDirectory. |
MON_KRB_LDAP_CONNPOOL_TIMEOUT_WAIT |
duration string | Нет | 10 seconds |
Максимальное время ожидания свободного подключения в пуле. |
MON_KRB_LDAP_CONNPOOL_TIMEOUT_CONN |
duration string | Нет | 500 millis |
Максимальное время ожидания подключения к ActiveDirectory. |
MON_KRB_LDAP_CONNPOOL_TIMEOUT_RESP |
duration string | Нет | 1 seconds |
Максимальное время ожидания ответа от ActiveDirectory. |
MON_KRB_LDAP_USER_FIRSTNAME |
string | Нет | ["givenName", "cn;1; ;3", "displayName;1; ;3"] |
Настройки получения атрибута из профиля в ActiveDirectory для UserInfo.firstName в формате AttributeMapping. |
MON_KRB_LDAP_USER_LASTNAME |
string | Нет | ["sn", "cn;0; ;3", "displayName;0; ;3"] |
Настройки получения атрибута из профиля в ActiveDirectory для UserInfo.lastName в формате AttributeMapping. |
MON_KRB_LDAP_USER_MIDDLENAME |
string | Нет | ["middleName", "cn;2; ;3", "displayName;2; ;3"] |
Настройки получения атрибута из профиля в ActiveDirectory для UserInfo.middleName в формате AttributeMapping. |
MON_KRB_LDAP_USER_EMAIL |
string | Нет | ["mail", "emailaddress"] |
Настройки получения атрибута из профиля в ActiveDirectory для User.email в формате AttributeMapping. |
MON_KRB_LDAP_USER_OBJECT_ID |
string | Нет | ["sid", "objectsid"] |
Настройки получения атрибута из профиля в ActiveDirectory для ProviderKey (уникального ключа пользователя в провайдере профиля пользователя) в формате AttributeMapping. |
MON_KRB_GROUPS_MAPPING |
string | Нет | "" |
Конвертация групп из Active Directory в группы Mon. Формат "ADName1=MonName1;ADName2=MonName2". Подробнее в AD groups mapping. |
MON_KRB_GROUPS_NOT_REMOVE |
string | Нет | "" |
Группы Mon, из которых не нужно удалять пользователя, если они больше не приходят из Active Directory. Формат "MonName1;MonName2". |
MON_KEYCLOAK_CLIENT_ID |
string | Нет | "" |
ID клиента в Keycloak (если значение отсутствует, то Keycloak authentication не будет работать). |
MON_KEYCLOAK_CLIENT_SECRET |
string | Нет | "" |
Secret клиента в Keycloak (если значение отсутствует, то Keycloak authentication не будет работать). |
MON_KEYCLOAK_REALM |
string | Нет | "" |
Используемый Realm в Keycloak (если значение отсутствует, то Keycloak authentication не будет работать). |
MON_KEYCLOAK_BASE_URI |
url string | Нет | "" |
URI Keycloak (если значение отсутствует, то Keycloak authentication не будет работать). Пример: "http://keycloak:8080". |
MON_KEYCLOAK_DISCOVERY_URL |
url string | Нет | "" |
URI openid configuration в Keycloak (если значение отсутствует, то будет использован "$baseUri/realms/$realm/.well-known/openid-configuration"). Пример: "http://keycloak:8080/realms/test-realm/.well-known/openid-configuration". |
MON_KEYCLOAK_CALLBACK_URL |
url string | Нет | "" |
Callback URL для редиректа после входа по Keycloak (если значение отсутствует, то Keycloak authentication не будет работать). Пример: "http://verdi.dev/keycloak-callback". |
MON_KEYCLOAK_PKCE_METHOD |
string | Нет | S256 |
Используемый Challenge Method для PKCE (Proof Key for Code Exchange). Доступные варианты: "plain" и "S256". (если значение отсутствует, то Keycloak authentication не будет работать). |
MON_KEYCLOAK_GROUPS_MAPPING |
string | Нет | "" |
Конвертация ролей из Keycloak в группы Mon. Формат "KCName1=MonName1;KCName2=MonName2". |
MON_KEYCLOAK_GROUPS_NOT_REMOVE |
string | Нет | "" |
Группы Mon, из которых не нужно удалять пользователя, если соответствующие роли больше не приходят из Keycloak. Формат "MonName1;MonName2". |
MON_KEYCLOAK_USER_FIRSTNAME |
string | Нет | ["givenName", "given_name;1; ;3"] |
Настройки получения атрибута из профиля в Keycloak для UserInfo.firstName в формате AttributeMapping. |
MON_KEYCLOAK_USER_LASTNAME |
string | Нет | ["family_name"] |
Настройки получения атрибута из профиля в Keycloak для UserInfo.lastName в формате AttributeMapping. |
MON_KEYCLOAK_USER_MIDDLENAME |
string | Нет | ["middleName", "middle_name", "given_name;2; ;3"] |
Настройки получения атрибута из профиля в Keycloak для UserInfo.middleName в формате AttributeMapping. |
MON_KEYCLOAK_USER_EMAIL |
string | Нет | ["email", "mail", "emailaddress"] |
Настройки получения атрибута из профиля в Keycloak для User.email в формате AttributeMapping. |
LOG_LEVEL_AUTH |
string | Нет | INFO |
Уровень логирования операций во время аутентификации. |
LOG_LEVEL_AUTH_CONTEXT |
string | Нет | INFO |
Уровень логирования доступа к контексту аутентификации. Работает только в DEBUG. |
MON_SENDERLIB_COMMANDS_HTTP_RETRY_ATTEMPTS |
int | Нет | 5 |
Поле attempts из RetrySettings. |
MON_SENDERLIB_COMMANDS_HTTP_RETRY_DELAY |
duration string | Нет | 5 seconds |
Поле delay из RetrySettings. |
MON_SENDERLIB_COMMANDS_HTTP_RETRY_KIND |
string | Нет | OnSomeExceptions(ConnectException) |
CommandResultRetryConditionKind. |
MON_SENDERLIB_CONSUL_CONNECTION_RETRY_MAX |
int | нет | 5 |
Количество попыток переподключения к Consul |
MON_SENDERLIB_CONSUL_CONNECTION_RETRY_DELAY |
duration string | нет | 1 second |
Задержка при попытках переподключения к Consul |
MON_LICENSE_PATH |
string | Да | "" |
Путь до файла с лицензией (только binary format). |
MON_LICENSE_KEY |
string | Да | "" |
Путь до файла с публичным ключом лицензией. |
MON_LICENSE_PATH_PRIORITY |
string | Нет | "" |
Порядок использования лицензий. При пустом значении - порядок будет соответствовать порядку путей до файлов лицензий (MON_LICENSE_PATH). Строка должна содержать приоритет для каждой лицензии, приоритеты разделяются запятой (например, 1,5,2) - лицензии будут обрабатываться в порядке возрастания приоритета. |
MON_ACCOUNT_LIFETIME |
duration string | Нет | Срок жизни аккаунта пользователя. Устанавливается в момент создания аккаунта, при превышении срока жизни аккаунт деактивируется во время LoginByCredentials. | |
MON_ACCOUNT_PRIVILEGED_EMAILS |
string | Нет | Строка с регулярным выражением. Аккаунты пользователей, у которых email-ы подходят под выражение, освобождаются от установки и проверки срока жизни аккаунта. | |
MON_EMAIL_NOTIFICATION_LIMIT_ENABLE |
boolean | Нет | false |
Включена ли проверка того, что команды порождающие отправку email, не отправляют email одному пользователю дважды в течении MON_EMAIL_NOTIFICATION_DELAY_PER_USER. Подробнее о настройке этой функции можно узнать здесь. |
MON_EMAIL_NOTIFICATION_DELAY_PER_USER |
duration string | Нет | Период, в течении которого при MON_EMAIL_NOTIFICATION_LIMIT_ENABLE = true команды порождающие отправку email, не отправляют email одному пользователю дважды. Должен быть положительным и меньше 365 дней. | |
MON_EMAIL_NOTIFICATION_ADDITIONAL_IDENTITY_HEADERS |
string | Нет | "" |
Строка, содержащая перечисление через запятую дополнительных заголовков, которые учитываются при идентификации пользователя, чтобы запретить отправку email при MON_EMAIL_NOTIFICATION_LIMIT_ENABLE = true. Подробнее о работе с заголовками notification limit можно узнать здесь. |
MON_PASSWORD_EXPIRE_MIGRATION_START_TIME |
string | Нет | "" |
Время, в которое нужно запустить обновление поля PasswordInfo.passwordExpirationDate для пользователей у которых PasswordInfo.salt != null. Значение должно быть позже времени запуска сервиса, иначе миграция будет считаться выполненой. Валидное значение должно быть не пустым и соответствовать формату "yyyy-MM-dd HH:mm" (UTC timezone). |
MON_PASSWORD_EXPIRE_MIGRATION_VALUE |
string | Нет | "" |
Значение для поля PasswordInfo.passwordExpirationDate, которое будет установлено в процессе миграции. Значение должно быть не пустым и соответствовать формату "yyyy-MM-dd HH:mm" (UTC timezone). |
MON_DB_URL |
jdbc url string | Нет | "jdbc:postgresql://"${?MON_DB_HOST}":"${?MON_DB_PORT}"/"${?MON_DB_NAME} |
Адрес базы данных. Можно использовать вместо MON_DB_HOST, MON_DB_PORT и MON_DB_NAME. |
MON_KEYCLOAK_CLIENT_AUTHENTICATION_METHOD |
string | Нет | client_secret_basic |
Метод аутентификации keycloak-клиента. |
MON_AKKA_HTTP_CLIENT_MAXCON |
int | Нет | 512 |
Максимальное количество http-соединений к одному хосту, которое используемый akka-http-клиент может одновременно поддерживать у себя в пуле. |
MON_AKKA_HTTP_CLIENT_MAXREQ |
int | Нет | 1024 |
Максимальное количество http-запросов к одному хосту, которые в случае достижения количества одновременных запросов превышающих MON_AKKA_HTTP_CLIENT_MAXCON будут положены в очередь и обработаны akka-http-клиентом позже. |
MON_AKKA_HTTP_SERVER_MAXCON |
int | Нет | 1024 |
Максимальное количество одновременно открытых http-соединений, которое поддерживает akka-http-сервер через метод Http.bind и другие методы аналогичные ему. |
MON_EXPORT_FILE_NAME |
string | Нет | "Список пользователей <dd.MM.yyyy HH.mm>.xlsx" |
Название файла с экспортом. Внутри < > можно указать маску для даты. |
MON_EXPORT_TIME_ZONE |
string | Нет | Europe/Moscow |
Временная зона, используемая при форматировании названия и дат в экспорте. |
MON_EXPORT_DATE_FORMAT |
string | Нет | dd.MM.yyyy HH.mm |
Формат дат в файле экспорта. |
MON_EXPORT_BUCKET |
string | Нет | temp |
Бакет S3, в котором сохраняются файлы экспорта. |
MON_EXPORT_COLUMNS |
string | Нет | lastName,firstName,middleName,email,groups,status |
Колонки из БД, которые нужно поместить в файл экспорта, разделяются запятой. Поддерживаются все данные возвращаемые из ListUsersWithGroups включая строковые значения на произвольной глубине в data. Для каждого элемента в данной переменной должен быть элемент в MON_EXPORT_COLUMN_NAMES на соответствующей позиции, иначе сервис не запустится и в логе будет выведено сообщение с ошибкой. |
MON_EXPORT_COLUMN_NAMES |
string | Нет | Фамилия,Имя,Отчество,Email,Группы,Состояние |
Названия для колонок в файле экспорта, разделенные запятой. |
MON_EXPORT_PAGE_SIZE |
int | Нет | 256 |
Размер страниц, которыми извлекаются данные при экспорте. |
MON_EXPORT_READ_BUFFER_SIZE |
int | Нет | 4096 |
Размер буфера в операциях с файлами во время экспорта. |
MON_EXPORT_GROUPS_SEPARATOR |
string | нет | ; |
Разделитель для списка групп при выгрузке. |
MON_FS_URI |
string | Да | http://localhost:9000 |
Адрес S3 хранилища. |
MON_FS_ACCESS_KEY_ID |
string | Да | "" |
AccessKey S3 хранилища. |
MON_FS_SECRET_ACCESS_KEY |
string | Да | "" |
Секретный ключ S3 хранилища. |
MON_FS_UPLOAD_PARALLELISM |
int | Нет | 4 |
Параллельность при работе с S3. |
MON_FS_RETRY_ATTEMPTS |
int | Нет | 5 |
Количество ретраев, которое будет произведено в случае Exception-а в операции FSClient-а и при вычитывании стрима в get операциях FSClient-а. |
MON_FS_RETRY_DELAY |
duration string | Нет | 10 millis |
Задержка между ретраями операций FSClient-а. |
MON_FS_ZIO_SHORT_MESSAGE_MODE |
boolean | нет | false | Флаг включения режима сохранения ошибок работы с файловым хранилищем в сервисе журналирования nestor. При включении режима ошибки в логах будут отображаться в сокращенном формате: Short zio message mode. ExceptionType: ТИП ОШИБКИ, Exception id: 'СГЕНЕРИРОВАННЫЙ UUID' added to journal. Указанный id будет фиксироваться в event записи nestor'а в поле data.id |
MON_JOURNAL_MODE |
string | Нет | WriteToJournal |
Режим журналирования Nestor. Допустимые значения: WriteToJournal (Отправка в сервис журналирования), WriteToTopic (Отправка события в очередь) |
MON_JOURNAL_TOPIC |
string | Да, если переменная MON_JOURNAL_MODE = WriteToTopic |
"" |
Название очереди журналирования. Для режима WriteToJournal значение игнорируется. |
MON_AUTHN_HASH_ROUNDS |
int | Нет | 12 |
Количество раундов хэширования пароля при его сохранении в БД. Допустимые значения: от 4 до 30 включительно. |
MON_AUTHN_SIPHASH_COMPRESSION_ROUNDS |
int | Нет | 2 |
Количество раундов сжатия исходной строки при генерации хэша идентификатора для отправки писем при регистрации и сбросе пароля. Подробнее о логике данных почтовых уведомлений можно узнать здесь. Указанное значение должно быть больше 0. |
MON_AUTHN_SIPHASH_FINALIZATION_ROUNDS |
int | Нет | 4 |
Количество раундов финального преобразования при генерации хэша идентификатора для отправки писем при регистрации и сбросе пароля. Подробнее о логике данных почтовых уведомлений можно узнать здесь. Указанное значение должно быть больше 0. |
Список команд сервиса Mon (commands-list)
Список команд сервиса Mon аналогичен списку команд в библиотеке mon-core.
Модели сервиса Mon
Набор моделей сервиса mon аналогичен набору моделей в библиотеке mon-core.
Особенности Kerberos authentication
Особенности Kerberos authentication для mon аналогичны особенностям Kerberos authentication для mon-core
ActiveDirectory groups mapping (mon)
ActiveDirectory groups mapping в mon аналогичен activeDirectory groups mapping в mon-core
External profile attributes mapping (mon)
Маппинг атрибутов профиля из внешнего хранилища (ActiveDirectory, Keycloak и т.п.) в mon, аналогичен маппингу в mon-core
Требования к настройкам клиента Keycloak (mon)
Требования к настройкам клиента Keycloak в mon аналогичны требованиям клиента Keycloak в mon-core
Требования к настройке notification limit (mon)
Требования к настройке notification limit в mon
аналогичны требованиям к настройке notification limit в mon-core, за исключением того,
что в mon настройка NotificationSettings.additionalIdentityHeaders равна переменной
MON_EMAIL_NOTIFICATION_ADDITIONAL_IDENTITY_HEADERS.
Nestor-client: клиент для сервиса журнала
Примеры создания Nestor-client
Получение и валидация настроек
NestorConfig
make[NestorConfig].from { appSettings: ApplicationSettings =>
appSettings.nestor.validated.fold(throw _, identity)
}
Создание
NestorClient
make[NestorClient].from {
(
dispatcher: Dispatcher,
kafkaProducer: KafkaProducerApi[Either[ErrorResponse, Unit]],
nestorConfig: NestorConfig,
ec: ExecutionContext @Id("ec-services")
) =>
new LiveNestorClient(dispatcher, kafkaProducer, nestorConfig)(ec)
}
Создание
NestorClientTF[F]
// F[_]: Async: ContextShift
make[NestorClientTF[F]].from {
(
verdi: VerdiTF[F],
factory: VerdiFactory,
nestorConfig: NestorConfig,
ec: ExecutionContext @Id("ec-services")
) =>
NestorClientTF.make[F](verdi, factory.kafkaProducer, nestorConfig)(Async[F], ContextShift[F], ec)
}
Создание
NestorClientTF[F]на ZIO
import zio.interop.catz._
val nestorConfigLayer: RLayer[Has[AppConfig], Has[NestorConfig]] = ZLayer.fromServiceM { config =>
ZIO.fromEither(config.nestor.validated)
}
val nestorClientLayer
: URLayer[Has[VerdiTF[Task]] with Has[VerdiFactory] with Has[NestorConfig] with Has[ExecutionContext], Has[NestorClientTF[Task]]] =
ZLayer.fromServices[VerdiTF[Task], VerdiFactory, NestorConfig, ExecutionContext, NestorClientTF[Task]] { (verdi, factory, config, ec) =>
NestorClientTF.make[Task](verdi, factory.kafkaProducer, config)(Async[Task], ContextShift[Task], ec)
}
Для того чтобы использовать библиотеку nestor-client, нужно добавить зависимость
"com.embedika.verdi" %% "nestor-client" % verdiVersion.
KafkaProducerApi можно получить из VerdiFactory.kafkaProducer или использовать свой
Предоставляемый функционал NestorClient
addEvent- Сохранение нового события в журнале с помощью команды createEvent или отправка в указанную в настройках очередьgetEvent- Вызов команды getEventgetEvents- Поиск событий журналирования по указанным критериям с помощью команды searchEvents
Nestor: сервис журналирования
Общее описание архитектуры сервиса журналирования
Для работы с журналом необходимы действия: добавить одно событие, запросить событие по идентификатору, отфильтровать события. Для каждого из этих действий Nestor предоставляет verdi-команду. Добавление это асинхронная команда, все события поступаю в очередь кафки и сохраняются пачками, поэтому будет существовать временной лаг между созданием события и возможностью его просмотра через Nestor. Сохранение пачками сделано для снижения нагрузки на хранилище. Размер пачки событий ограничен максимальным кол-вом событий, а так же временем формирования пачки ( см. groupedWithin)
Список переменных окружения Nestor
| Переменная | Тип | Обязательная | Значение по умолчанию | Описание |
|---|---|---|---|---|
SERVER_PORT |
Int |
Нет | 8080 |
Порт, на котором слушает HTTP-сервер. |
CONSUMER_TOPIC |
String |
Нет | document |
Название Kafka-топика для команд журналирования событий. |
CONSUMER_CHUNK_SIZE |
String |
Нет | 1000 |
Размер пачки обрабатываемых событий. |
CONSUMER_CHUNK_WITHIN |
Duration String |
Нет | 10 seconds |
Время, за которое должна обработаться пачка событий, что определяет производительность сервиса. |
CONSUMER_GROUP |
String |
Нет | document |
Имя группы-консьюмеров сервиса журналирования. |
VERDI_CONSUL |
String |
Да | http://localhost:8500 |
Адрес Consul. |
VERDI_CONSUL_AUTH_USER |
String |
Нет | "" |
Название учетной записи Сonsul. Если название не указано, то настройки авторизации не будут применены. |
VERDI_CONSUL_AUTH_PASSWORD |
String |
Нет | "" |
Пароль учетной записи Сonsul. |
VERDI_KAFKA_ADDRESS |
String |
Да | localhost:9092 |
Адрес брокера Kafka. |
VERDI_KAFKA_TOPIC |
String |
Нет | commandevents |
Название Kafka-топика для отправки сообщений со статусами выполняемых команд. ОБЯЗАТЕЛЬНО должно соответствовать названию этого топика в сервисе статуса команд. |
VERDI_KAFKA_AUTH_USER |
String |
Нет | "" |
Название учетной записи Kafka. Если название не указано, то настройки авторизации не будут применены. |
VERDI_KAFKA_AUTH_PASSWORD |
String |
Нет | "" |
Пароль учетной записи Kafka. |
VERDI_KAFKA_AUTH_PRINCIPAL |
String |
Нет | "" |
Principal учетной записи Kafka в Kerberos(в случае соединения с kafka через Kerberos). |
VERDI_KAFKA_AUTH_KEYTAB_PATH |
String |
Нет | "" |
Путь до keytab-файла (в случае соединения с kafka через Kerberos). |
VERDI_KAFKA_AUTH_TRUSTSTORE_LOCATION |
String |
Нет | "" |
Путь до хранилища сертификатов (Java key store). Если путь не указан, то сертификат применяться не будет. |
VERDI_KAFKA_AUTH_TRUSTSTORE_PASSWORD |
String |
Нет | "" |
Пароль к хранилищу сертификатов. |
VERDI_KAFKA_AUTH_MODE |
String |
Нет | "" |
Режим аутентификации: static - одна учетная запись на все запросы, mapping - учетная запись зависит от запроса. |
VERDI_KAFKA_AUTH_CONFIG |
String |
Нет | "" |
Настройки для аутентификации: если AuthMode = mapping, то необходим JSON с List[KafkaAuthConfig]. Переменная соответствует полю authConfig из KafkaAuthSettings. |
VERDI_KAFKA_AUTH_CACHE_SIZE |
Int |
Нет | "" |
Максимальный размер кеша для Kafka producer (количество активных соединений). |
VERDI_KAFKA_CONNECTION_CHECK_TEST_MESSAGES_INTERVAL |
Duration String |
Нет | 4 minutes |
Применяется только для producer-ов со способом аутентификации kerberos. Интервал отправки тестовых сообщений кафки в топик connectionCheck.testMessagesTopicName. Тестовые сообщения (null, service producer test) отправляются регулярно с этим интервалом. |
VERDI_KAFKA_CONNECTION_CHECK_INTERVAL |
Duration String |
Нет | 60 seconds |
Применяется только для producer-ов со способом аутентификации kerberos. Интервал проверки того, сколько тестовых сообщений было отправлено за данный период. Если количество сообщений за этот период равно количеству сообщений за прошлый период, то начинается отсчет периода без сообщений. |
VERDI_KAFKA_CONNECTION_CHECK_FAILED_AFTER_INTERVAL |
Duration String |
Нет | 5 minutes |
Применяется только для producer-ов со способом аутентификации kerberos. Максимальная продолжительность периода без успешно отправленных тестовых сообщений. По ее достижении сервис будет объявлен больным. |
VERDI_KAFKA_AUTH_CACHE_TTL |
Duration String |
Нет | "" |
Время жизни Kafka producer в кэше. |
VERDI_HOST |
String |
Да | localhost |
Хост, публикуемый в ServiceDiscovery. По нему на данный сервис будут обращаться другие через HTTP. Указанный адрес должен быть виден другим сервисам. Пример: имя kubernetes/docker_swarm service. |
VERDI_TTL |
Duration String |
Нет | 30 seconds |
Период после последней отправки health check, в течение которого ServiceDiscovery считает данный сервис живым. |
VERDI_HEALTH_CHECK |
Duration String |
Нет | 10 seconds |
Периодичность отправки health check в ServiceDiscovery. |
VERDI_COMMAND_STORAGE_UPDATE_PERIOD |
Duration String |
Нет | 1 minutes |
Время кэширования данных по командам из CommandDiscovery. |
VERDI_SERVICE_DISCOVERY_UPDATE_PERIOD |
Duration String |
Нет | 30 seconds |
Время кэширования данных по сервисам из ServiceDiscovery. |
VERDI_ALLOW_INTERNAL_COMMANDS |
Boolean |
Нет | true |
Можно ли сервису отправлять внутрисистемные команды. |
VERDI_CONSIDER_ALL_COMMANDS_AS_INTERNAL |
Boolean |
Нет | false |
Флаг, определяющий будут ли все обращения в другие сервисы являться внутренними (т.е. не требовать авторизацию). Детальное описание механизма: Внутренние команды. |
VERDI_CONSUL_CONNECTION_MAX_RETRY |
Int |
Нет | 5 |
Максимальное количество попыток подключений к Consul. |
VERDI_CONSUL_CONNECTION_RETRY_DELAY |
Duration String |
Нет | 1 seconds |
Таймаут между неудачными попытками подключения к Consul. |
VERDI_KAFKA_SYNC_POLL_PERIOD |
Duration String |
Нет | 1 seconds |
Периодичность запроса статуса команды отправленной через Kafka. |
VERDI_KAFKA_SYNC_POLL_TIMEOUT |
Duration String |
Нет | 1 minute |
Время ожидания завершения команды отправленной через Kafka. |
TECHCONSTANT_SERVICE_NAME |
String |
Нет | Сервис журналирования событий |
Название сервиса для TechConstant. |
TECHCONSTANT_SERVICE_DESC |
String |
Нет | Сервис для хранения и доступа к событиям |
Описание сервиса для TechConstant. |
TECHCONSTANT_REGISTRATION_BASEDELAY |
Duration String |
Нет | 30 seconds |
Базовая задержка для "retry с экспоненциальной задержкой". |
ELASTIC_HOST |
String |
Нет | localhost |
Хост Elasticsearch. |
ELASTIC_PORT |
Int |
Нет | 9200 |
Порт Elasticsearch. |
ELASTIC_SSL |
Boolean |
Нет | false |
Использовать ли SSL для соединении с Elasticsearch. |
ELASTIC_TRACK_TOTAL_HITS |
Int |
Нет | null |
Управление переменной trackTotalHits в запросах к Elasticsearch. Обозначает ограничение количества документов которое будет найдено. Значение null обозначает снятие ограничения. |
ELASTIC_AUTH_USER |
String |
Нет | "" |
Название учетной записи для Elasticsearch. |
ELASTIC_AUTH_PASSWORD |
String |
Нет | "" |
Пароль учетной записи для Elasticsearch. |
ELASTIC_AUTH_STORE_TYPE |
String |
Нет | pem |
Тип хранилища сертификата для Elasticsearch. |
ELASTIC_AUTH_STORE_LOCATION |
String |
Нет | "" |
Путь до хранилища сертификата для Elasticsearch. |
EVENTSTORAGE_ELASTIC_INDEX |
String |
Нет | events-journal |
Название индекса для хранения журналов в Elasticsearch. |
EVENTSTORAGE_RETENTION |
Duration String |
Нет | 7 days |
Продолжительность хранения журналов. |
EVENTSTORAGE_MEMORY_CAP |
String |
Нет | 64 MB |
Максимальная доступная память для хранилища журналов. Необходимо для расчета процента используемой памяти. Возможные сокращения: b, kb, mb, gb. |
EVENTSTORAGE_MEMORY_WARNING_PERCENT |
Int |
Нет | 70 |
Процент используемой памяти, при котором будет сформировано событие в журнал. |
EVENTSTORAGE_MEMORY_CRITICAL_PERCENT |
Int |
Нет | 90 |
Процент используемой памяти, при котором сообщения из kafka перестанут потребляться, консьюмер будет выключен, а при EVENTSTORAGE_MAKE_ILL_ON_CRITICAL_PERCENT = true сервис будет помечен больным. |
EVENTSTORAGE_MAKE_ILL_ON_CRITICAL_PERCENT |
Boolean |
Нет | false |
Флаг, определяющий то, будет ли сервис помечен больным при достижении EVENTSTORAGE_MEMORY_CRITICAL_PERCENT. |
EVENTSTORAGE_MEMORY_CHECK_DELAY |
Duration String |
Нет | 10 seconds |
Период проверки используемой хранилищем памяти. |
EVENTSTORAGE_ROLLOVER |
String |
Нет | daily |
Периодичность создания новых индексов (т.к. нет возможности хранить все данные в одном): hourly - каждый час, daily - каждый день, weekly - каждую неделю. |
EVENTSTORAGE_ROLLOVER_ENABLED |
Boolean |
Нет | true |
Включен ли rollover для хранилища. OpenSearch не поддерживает rollover. |
EVENTSTORAGE_DEFAULT_PAGE_SIZE |
Int |
Нет | 10 |
Размер страницы по умолчанию, при выдачи списка событий. |
EVENTSTORAGE_DEFAULT_SORT_FIELD |
String |
Нет | eventDate |
Поле для сортировки по умолчанию, при выдачи списка событий. |
EVENTSTORAGE_DEFAULT_SORT_ORDER |
String |
Нет | Desc |
Направление для сортировки по умолчанию, при выдачи списка событий: Asc - "по возрастанию", Desc - "по убыванию". |
EVENTSTORAGE_UPDATE_TEMPLATE_PAGE_SIZE |
Int |
Нет | 1000 |
Количество элементов, которые запрашивает команда updateEventsTemplate на одной странице, когда выкачивает из базы события для обновления, подходящие под переданный запрос. |
ENGINE_TYPE |
String |
Нет | elastic |
Тип хранилища данных elastic или openSearch или clickhouse. Про работу с ClickHouse смотри подробнее в Особенности работы с Clickhouse. |
OPEN_SEARCH_HOST |
String |
Нет | localhost |
Хост OpenSearch. |
OPEN_SEARCH_PORT |
Int |
Нет | 9200 |
Порт OpenSearch. |
OPEN_SEARCH_SSL |
Boolean |
Нет | false |
Использовать ли SSL для соединении с OpenSearch. |
OPEN_SEARCH_TRACK_TOTAL_HITS |
Int |
Нет | null |
Управление переменной trackTotalHits в запросах к OpenSearch. Обозначает ограничение количества документов которое будет найдено. Значение null обозначает снятие ограничения. |
OPEN_SEARCH_AUTH_USER |
String |
Нет | "" |
Название учетной записи для OpenSearch. |
OPEN_SEARCH_AUTH_PASSWORD |
String |
Нет | "" |
Пароль учетной записи для OpenSearch. |
OPEN_SEARCH_AUTH_STORE_TYPE |
String |
Нет | pem |
Тип хранилища сертификата для OpenSearch. |
OPEN_SEARCH_AUTH_STORE_LOCATION |
String |
Нет | "" |
Путь до хранилища сертификата для OpenSearch. |
CLICKHOUSE_HOST |
String |
Нет | localhost |
Хост ClickHouse. |
CLICKHOUSE_PORT |
Int |
Нет | 8123 |
Порт ClickHouse. |
CLICKHOUSE_DATABASE |
String |
Нет | default |
Название базы данных в ClickHouse. |
CLICKHOUSE_DISKNAME |
String |
Нет | default |
Название используемого диска в ClickHouse. |
CLICKHOUSE_AUTH_USER |
String |
Нет | "" |
Название учетной записи для ClickHouse. Всегда требуется при использовании ENGINE_TYPE = "clickhouse". Сервис не поддерживает работу с ClickHouse, в котором отсутствует аутентификация. (Всегда должен быть логин и пароль). |
CLICKHOUSE_AUTH_PASSWORD |
String |
Нет | "" |
Пароль учетной записи для ClickHouse. Всегда требуется при использовании ENGINE_TYPE = "clickhouse". Сервис не поддерживает работу с ClickHouse, в котором отсутствует аутентификация. (Всегда должен быть логин и пароль). |
CLICKHOUSE_RETRIES |
Int |
Нет | 3 |
Количество ретраев при отправке запросов в ClickHouse. |
CLICKHOUSE_RESPONSE_TIMEOUT |
Duration String |
Нет | 1 second |
Время ожидания ответа от ClickHouse. |
CLICKHOUSE_QUEUE_SIZE |
Int |
Нет | 1024 |
Максимальный размер внутренней очереди запросов к ClickHouse. |
CLICKHOUSE_FRAME_MAX_SIZE |
Int |
Нет | 1048576 |
Максимальный размер одной строки при запросе данных от ClickHouse. |
CLICKHOUSE_CLUSTER |
String |
Нет | cluster |
Название используемого кластера ClickHouse. |
CLICKHOUSE_CONNECT_TYPE |
String |
Нет | cluster-aware |
Название режима подключения к ClickHouse. |
CLICKHOUSE_CONNECT_HEALTH_INTERVAL |
Duration String |
Нет | 10 seconds |
Минимальное время между 2 проверками работоспособности на одном хосте. |
CLICKHOUSE_CONNECT_HEALTH_TIMEOUT |
Duration String |
Нет | 1 seconds |
Максимальный тайм-аут простоя соединения для проверки работоспособности. |
CLICKHOUSE_CONNECT_SCANNING_INTERVAL |
Duration String |
Нет | 60 seconds |
Интервал между запросами в таблице кластеров для обновления хостов кластера клиентов. |
CLICKHOUSE_CONNECT_FALLBACK_CONFIG |
Boolean |
Нет | false |
Откат к хосту из конфигурации при инициализации. |
CLICKHOUSE_HTTP_COMPRESSION |
Boolean |
Нет | false |
Использовать ли сжатие при отправке по HTTP. |
VERDI_COMMANDS_HTTP_RETRY_ATTEMPTS |
Int |
Нет | 5 |
Поле attempts из RetrySettings. |
VERDI_COMMANDS_HTTP_RETRY_DELAY |
Duration String |
Нет | 5 seconds |
Поле delay из RetrySettings. |
VERDI_COMMANDS_HTTP_RETRY_KIND |
String |
Нет | OnSomeExceptions(ConnectException) |
CommandResultRetryConditionKind. |
SERVER_AUTHORIZER_KIND |
String |
Нет | authzforce |
Вид авторизатора, который используется в сервисе. Допустимые значения: authzforce, oberto. При указании неизвестного значения будет использовано значение по-умолчанию. |
AUTHZFORCE_ADDR |
String |
Нет | http://localhost:8080/authzforce-ce |
Адрес AuthZforce server (переменная должна быть непустой, если SERVER_AUTHORIZER_KIND="authzforce"). |
AUTHZFORCE_DOMAIN |
String |
Нет | "" |
Доступный DomainID в AuthZforce server (переменная должна быть непустой, если SERVER_AUTHORIZER_KIND="authzforce"). |
AUTHZFORCE_CONNECT_TIMEOUT |
Duration String |
Нет | 5 seconds |
Таймаут подключения к authzforce (переменная должна быть непустой, если SERVER_AUTHORIZER_KIND="authzforce"). |
Команды сервиса Nestor
Список реализованных в сервисе команд, моделей EntityType и действий Actions, которые можно использовать при настройке
авторизации.
Не все поля EntityType доступны для использования в настройке авторизации.
Если указан прочерк "-", то данное значение не влияет на авторизацию:
- если не указан Action, то никакой Action не проверяется (= без авторизации)
- если не указан EntityType, то на авторизацию влияет только Action
| Назначение команды | Название команды | EntityType | Actions |
|---|---|---|---|
| Поиск событий | searchEvents | Event | SearchEvents |
| Создание события | createEvent | - | - |
| Получение события | getEvent | Event | GetEvent |
| Обновление поля renderedData у событий | updateEventsTemplate | Event | Update |
UpdateEventsTemplate (Nestor)
На входе объект Search с фильтрами для получения списка событий, поле renderedData в которых нужно обновить (поля sorting и paging при поиске учитываться не будут)
{
"query": "",
"context": {},
"sorting": {
"fieldName": "title",
"order": "asc"
},
"paging": {
"page": 1,
"count": 10
}
}
На выходе объект со статистикой того, сколько успешных и неуспешных обновлений поля renderedData произошло для каждого конкретного eventType (results), а также того сколько событий не было обработано из-за ошибки их получения(unhandledEvents)
{
"unhandledEvents": 10,
"results": {
"createDataModel": {
"updated": 123,
"errors": 1,
"templateErrors": 1
},
"postmanTestEventType": {
"updated": 11,
"errors": 0,
"templateErrors": 4
}
}
}
Обновляет поле renderedData у всех событий, подходящих под критерии поиска, на основе значений из поля data и шаблона При этом sorting и paging при поиске не учитываются. Во время исполнения команды все подходящие под фильтры события вычитаются постранично последовательными запросами. При этом размер страницы, который будет получен в одном конкретном запросе будет равен значению переменной EVENTSTORAGE_UPDATE_TEMPLATE_PAGE_SIZE.
Запрос принимает параметры фильтров в параметре Search.
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров | Регистронезависимость |
|---|---|---|
| id | InSetQuery | только для ASCII-символов |
| eventDate | InSetQuery, RangeQuery | только для ASCII-символов |
| storeDate | InSetQuery, RangeQuery | только для ASCII-символов |
| eventType | InSetQuery, LikeQuery | только для ASCII-символов |
| userId | InSetQuery, LikeQuery | только для ASCII-символов |
| eventCategory | InSetQuery, LikeQuery | только для ASCII-символов |
| application | InSetQuery, LikeQuery | только для ASCII-символов |
| data | InSetQuery, LikeQuery, TsQuery при использовании openSearch и elasticSearch; InSetQuery, LikeQuery, TsQuery при использовании Clickhouse | полная |
| renderedData | LikeQuery, TsQuery при использовании openSearch и elasticSearch; InSetQuery, LikeQuery при использовании Clickhouse | полная |
| dependencies.entityClass | InSetQuery, AllInSetQuery, LikeQuery | только для ASCII-символов |
| dependencies.entityId | InSetQuery, AllInSetQuery, LikeQuery | только для ASCII-символов |
| dependencies.dependencyType | InSetQuery, AllInSetQuery, LikeQuery | только для ASCII-символов |
Маппинг фильтров nestor в запросы elasticSearch/openSearch и clickhouse аналогичен маппингу описанному для команды searchEvents
Имя команды для вызова: updateEventsTemplate.
Поддерживается синхронный и асинхронный вызов.
Результат выполнения команды журналируется.
- На входе: Search
- На выходе: UpdateEventsTemplateResult
CreateEvent (Nestor)
На входе данные нового события
{
"eventDate": 1683901401795,
"eventType": "journalDeleteGroup",
"userId": "0e7c15e6-2a7b-46c2-8571-d9dc9d6e3726",
"eventCategory": "Success",
"application": "Mon",
"data": "{\"eventType\":\"journalDeleteGroup\",\"payload\":\"CODECODE\",\"result\":true,\"data\":\"Наименование наименование\"}",
"dependencies": []
}
На выходе сообщение об успешности выполнения команды
{
"result": "success"
}
Сохраняет новое событие в журнале.
Имя вызова команды: createEvent.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway), не требует аутентификации.
- На входе: NewEvent
- На выходе: JSON с полем
resultи значениемsuccess
GetEvent (Nestor)
На входе JSON-объект с ID запрашиваемого события
{
"id": "42883340-f2cd-4eac-92ca-36ef46d4d038"
}
На выходе данные запрашиваемого события
{
"id": "42883340-f2cd-4eac-92ca-36ef46d4d038",
"eventDate": 1683901401795,
"storeDate": 1683901411816,
"eventType": "journalDeleteGroup",
"userId": "0e7c15e6-2a7b-46c2-8571-d9dc9d6e3726",
"eventCategory": "Success",
"application": "Mon",
"data": "{\"eventType\":\"journalDeleteGroup\",\"payload\":\"CODECODE\",\"result\":true,\"data\":\"Наименование наименование\"}",
"dependencies": []
}
Получение события по его ID.
Имя вызова команды: getEvent.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: JSON с полем
id, в значении которого указан ID искомого события - На выходе: Event
SearchEvents (Nestor)
На входе параметры поиска событий
{
"query": "eventType",
"context": {
"eventType": {
"kind": "any",
"values": [
"importCatalogs",
"journalDeleteGroup"
]
}
},
"sorting": {
"fieldName": "eventDate",
"order": "Desc"
},
"paging": {
"page": 1,
"count": 2
}
}
На выходе результат поиска
{
"items": [
{
"id": "42883340-f2cd-4eac-92ca-36ef46d4d038",
"eventDate": 1683901401795,
"storeDate": 1683901411816,
"eventType": "journalDeleteGroup",
"userId": "0e7c15e6-2a7b-46c2-8571-d9dc9d6e3726",
"eventCategory": "Success",
"application": "Mon",
"data": "{\"eventType\":\"journalDeleteGroup\",\"payload\":\"CODECODE\",\"result\":true,\"data\":\"Наименование наименование\"}",
"renderedData": "Была удалена группа пользователей \"Наименование наименование\" с кодом \"CODECODE\"",
"dependencies": []
},
{
"id": "881b3ffa-6273-44ed-a798-08e75959a644",
"eventDate": 1682515867969,
"storeDate": 1682515877987,
"eventType": "journalDeleteGroup",
"userId": "d5b8f850-1af6-4f94-82ef-fe304bb90618",
"eventCategory": "Success",
"application": "Mon",
"data": "{\"eventType\":\"journalDeleteGroup\",\"payload\":\"Test1\",\"result\":true,\"data\":\"Тестовая 1\"}",
"renderedData": "Была удалена группа пользователей \"Тестовая 1\" с кодом \"Test1\"",
"dependencies": []
}
],
"total": 206
}
Возвращает список событий, подходящих под критерии поиска и пагинации.
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров | Регистронезависимость |
|---|---|---|
| id | InSetQuery | только для ASCII-символов |
| eventDate | InSetQuery, RangeQuery | только для ASCII-символов |
| storeDate | InSetQuery, RangeQuery | только для ASCII-символов |
| eventType | InSetQuery, LikeQuery | только для ASCII-символов |
| userId | InSetQuery, LikeQuery | только для ASCII-символов |
| eventCategory | InSetQuery, LikeQuery | только для ASCII-символов |
| application | InSetQuery, LikeQuery | только для ASCII-символов |
| data | InSetQuery, LikeQuery, TsQuery при использовании openSearch и elasticSearch; InSetQuery, LikeQuery, TsQuery при использовании Clickhouse | полная |
| renderedData | LikeQuery, TsQuery при использовании openSearch и elasticSearch; InSetQuery, LikeQuery при использовании Clickhouse | полная |
| dependencies.entityClass | InSetQuery, AllInSetQuery, LikeQuery | только для ASCII-символов |
| dependencies.entityId | InSetQuery, AllInSetQuery, LikeQuery | только для ASCII-символов |
| dependencies.dependencyType | InSetQuery, AllInSetQuery, LikeQuery | только для ASCII-символов |
Маппинг фильтров nestor в запросы elasticSearch/openSearch и clickhouse:
| Фильтр | Запрос к nestor | Запрос elasticSearch/openSearch | Запрос к clickhouse |
|---|---|---|---|
| InSetQuery("value1", "value2") | {"query": "fieldName", "context" : {"fieldName": {"kind": "any","values": ["value1", "value2"]}} | {"query" : {"bool" : { "should" : [{"term" : {"fieldName" : {"value" : "value1", "case_insensitive": true}}}, {"term" : {"fieldName" : {"value" : "value2", , "case_insensitive": true}}}] }}} | select * from journal where lowerUTF8(fieldName) in ('value1', 'value2') |
| LikeQuery("value1") | {"query": "fieldName", "context" : {"fieldName": "like value1"}} | {"query" : {"term" : {"fieldName" : {"value" : "value1", "case_insensitive": true}}}} | select * from journal where fieldName ilike 'value1' |
| LikeQuery("%value1") | {"query": "fieldName", "context" : {"fieldName": "like %value1"}} | {"query" : {"regexp" : {"fieldName" : {"value" :".value1", "case_insensitive": true}}}} | select * from journal where fieldName ilike '%value1' |
| LikeQuery("__value1") | {"query": "fieldName", "context" : {"fieldName": "like __value1"}} | {"query" : {"regexp" : {"fieldName" : {"value" :".{2}value1", "case_insensitive": true}}}} | select * from journal where fieldName ilike '__value1' |
| RangeQuery(1, 4) | {"query": "fieldName", "context" : {"fieldName": "1_4"}} | {"query" : {"range" : {"fieldName" : {"gte" : 1, "lte" : 2}}}} | select * from journal where fieldName >= 1 and fieldName =< 4 |
| AllInSetQuery("value1", "value2") (для полей объектов массива) | {"query": "arrayFieldName.objectFieldName", "context" : {"arrayFieldName.objectFieldName": {"kind": "all","values": ["value1", "value2"]}}} | {"query" : {"bool" : {"must" : [{"nested": {"path": "arrayFieldName", "query": {"term" : {"arrayFieldName.objectFieldName" : {"value" : "value1", "case_insensitive": true}}} }}, {"nested": {"path": "arrayFieldName", "query": {"term" : {"arrayFieldName.objectFieldName" : {"value" : "value2", "case_insensitive": true}}} }}] }}} | select * from journal where arrayExist(element -> lowerUTF8(element) in ('value1', 'value2'), arrayFieldName.objectFieldName) |
| TsQuery("b + c - e * d & f: j ! h") | {"query": "fieldName", "context" : {"fieldName": "ts b + c - e * d & f:* j ! h"}} | {"query": {"simple_query_string": {"query": "b\+ c \- e \* d + f* j - h", "flags": "OR|AND|PREFIX|NOT|PRECEDENCE|WHITESPACE|ESCAPE|PHRASE", "fields": ["fieldName"]}}} | - |
Доступные поля для сортировки:
| Поле | Примечание |
|---|---|
| id | - |
| eventDate | - |
| storeDate | - |
| eventType | - |
| userId | - |
| eventCategory | - |
| application | - |
| dependencies.entityClass | - |
| dependencies.entityId | - |
| dependencies.dependencyType | - |
Если поле sorting отсутствует, то список сортируется согласно соответствующей конфигурации сервиса
(см. параметры EVENTSTORAGE_DEFAULT_SORT_FIELD и EVENTSTORAGE_DEFAULT_SORT_ORDER)
Если поле paging отсутствует, то в paging.page устанавливается 1,
а в paging.count используется значение из переменной окружения EVENTSTORAGE_DEFAULT_PAGE_SIZE.
Имя вызова команды: searchEvents.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
Модели сервиса Nestor
UpdateEventsTemplateResult (Nestor)
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| unhandledEvents | Int | да | Количество событий, которые не были обработаны из-за ошибки их получения |
| results | Map[String, UpdateEventsTemplateStats] | да | Результаты обновления событий, которые были получены, сгруппированные по типам событий |
UpdateEventsTemplateStats (Nestor)
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| updated | Int | да | Количество успешно обновленных событий |
| errors | Int | да | Количество событий, обновление которых завершилось с ошибкой |
| templateErrors | Int | да | Количество событий, обновление которых завершилось с ошибкой шаблона. К ошибкам шаблона относятся: отсутствие константы, отсутствие шаблона, исключения во время применения шаблона |
Dependency (Nestor)
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| entityClass | String | Да | Класс зависимости |
| entityId | String | Да | Идентификатор зависимости |
| dependencyType | String | Да | Тип зависимости |
case class Dependency(entityClass: String, entityId: String, dependencyType: String)
NewEvent (Nestor)
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| eventDate | Long | Да | Дата события |
| eventType | String | Да | Тип события |
| userId | UUID | Да | Идентификатор связанного с событием пользователя |
| eventCategory | String | Да | Статус события |
| application | String | Да | Идентификатор связанного с событием приложения |
| data | String | Да | Данные события |
| dependencies | List[Dependency] | Да | Иные связанные с событием сущности Dependency |
case class NewEvent(
eventDate: Long,
eventType: String,
userId: String,
eventCategory: String,
application: String,
data: String,
dependencies: List[Dependency]
)
Event (Nestor)
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | UUID | Да | Идентификатор события |
| eventDate | TimeStamp | Да | Дата события |
| storeDate | TimeStamp | Да | Дата сохранения события |
| eventType | String | Да | Тип события |
| userId | UUID | Да | Идентификатор связанного с событием пользователя |
| eventCategory | String | Да | Статус события |
| application | String | Да | Идентификатор связанного с событием приложения |
| data | String | Да | Данные события |
| renderedData | String | Да | Текст с результатом применения шаблона к данным события |
| dependencies | List[Dependency] | Да | Иные связанные с событием сущности Dependency |
case class Event(
id: UUID,
eventDate: Long,
storeDate: Long,
eventType: String,
userId: String,
eventCategory: String,
application: String,
data: String,
dependencies: List[Dependency]
)
Особенности работы с Clickhouse
Начиная с версии rc3.1.0 для работы с Clickhouse используется тип таблицы ReplicatedMergeTree. Для успешного функционирования сервиса с таким типом таблиц даже при использовании clickhouse, который содержит в себе только одну ноду, нужно обязательно иметь на стенде ноду Zookeeper или Clickhouse Keeper, настроенную для взаимодействия с нодой clickhouse как с кластером.
Oberto-client: клиент для сервиса Oberto
Библиотека предоставляет интерфейс и реализацию клиента для сервиса Oberto.
Пример создания Oberto-client
Пример внедрения зависимости:
make[ObertoClient[F]].from {
(
dispatcher: Dispatcher,
fromFuture: FromFuture[F],
executionContext: ExecutionContext
) =>
implicit val ff: FromFuture[F] = fromFuture
implicit val ec: ExecutionContext = executionContext
new LiveObertoClient[F](dispatcher)
}
Для регистрации клиента на
Futureследует использовать методmakeFutureBasedобъектаObertoClient:
make[ObertoClient[Future]].from {
(
dispatcher: Dispatcher,
executionContext: ExecutionContext
) =>
implicit val ec: ExecutionContext = executionContext
ObertoClient.makeFutureBased(dispatcher)
}
Для того чтобы использовать библиотеку oberto-client, нужно добавить зависимость
"com.embedika.verdi" %% "oberto-client" % verdiVersion.
Все классы находятся в пакетах с корнем com.embedika.verdi.oberto.
Основной интерфейс для взаимодействия ObertoClient[F[_]].
Реализация интерфейса LiveObertoClient[F[_]: Monad: FromFuture].
Предоставляемый функционал Oberto-client
Oberto-client предоставляет методы вызова соответствующих команд сервиса Oberto. Формат входных и выходных данных методов Oberto-client аналогичен формату входных и выходных данных команд сервиса Oberto.
Получение политик
Добавление или обновление политик
Удаление политик
Авторизация действий
Oberto: сервис системы прав
Сервис отвечает за редактирование правил доступа к различным ресурсам и проверку доступности пользователей к ресурсам. Команды могут приходить только по HTTP.
Проект сервиса содержит несколько директорий:
commandsсодержит описание команд и их публикации.handlersсодержит обработчики команд (бизнес логика), которые определяют правила взаимодействия компонентов между собой.httpсодержит HTTP роуты, описания форматов входных данных и исходящих ошибок.bootсодержит зависимости и описание для сборки и запуска сервиса.utilсодержит вспомогательные объекты.
В сервисе реализованы следующие команды (все команды "синхронные"):
- Список добавленных политик (V1)
- Список добавленных политик (V2)
- Получение данных отдельной политики (V1)
- Получение данных отдельной политики (V2)
- Удаление отдельной версии политики (V1)
- Удаление отдельной версии политики (V2)
- Удаление всех версий политики (V1)
- Удаление всех версий политики (V2)
- Добавление или обновление политики (V1)
- Добавление или обновление политики (V2)
- Авторизация списка действий для выбранного ресурса (V1)
- Авторизация списка действий для выбранного ресурса (V2)
- Авторизация списка действий для нескольких ресурсов (Пакетный запрос авторизации)
- Авторизация с указанными параметрами
- Перезапись политик из источника
Локальный запуск сервиса Oberto
При запуске сервиса ожидается, что уже развернута необходимая инфраструктура:
- AuthZforce server по адресу
http://localhost:8080/authzforce-ce - Kafka по адресу
localhost:9092 - Consul по адресу
localhost:8500 - В Consul будет добавлены следующие ключи или они указаны в
application.conf:- адрес AuthZforce по ключу
authzforce_server_address- В рантайме, исходя из наличия адреса AuthZforce, будет попытка получить доступный DomainID для AuthZforce (
также его можно указать в
application.conf)
- В рантайме, исходя из наличия адреса AuthZforce, будет попытка получить доступный DomainID для AuthZforce (
также его можно указать в
- адрес AuthZforce по ключу
Запуск Oberto из консоли с помощью SBT
sbt run
Список всех переменных окружения для сервиса Oberto
| Переменная | Тип | Обязательная | Значение по умолчанию | Описание |
|---|---|---|---|---|
OBERTO_HTTP_HOST |
string | Нет | 0.0.0.0 |
Хост для HttpListener. |
OBERTO_HTTP_PORT |
int | Нет | 8192 |
Порт для HttpListener. |
OBERTO_KAFKA_SERVERS |
string | Да | localhost:9092 |
Адрес Kafka. |
OBERTO_KAFKA_TOPIC |
string | Нет | OBERTO_commands |
Название топика для входящих команд. |
OBERTO_KAFKA_COMMANDEVENT_TOPIC |
string | Нет | commandevents |
Название топика для входящих/исходящих событий. |
OBERTO_KAFKA_CONSUMER_GROUP |
string | Нет | "" |
Название группы для чтения топика событий. |
OBERTO_KAFKA_CONSUMER_POLL_TIMEOUT |
duration string | нет | 10 milliseconds | timeout запроса poll для kafka consumer |
OBERTO_KAFKA_CONSUMER_POLL_INTERVAL |
duration string | нет | 100 milliseconds | интервал между запросами poll для kafka consumer |
OBERTO_KAFKA_CONSUMER_PROPS |
string | нет | "max.poll.records=500;max.partition.fetch.bytes=524288" | дополнительные параметры для kafka consumer в формате "key1=value1;key2=value2" |
OBERTO_KAFKA_AUTH_USER |
string | Нет | "" |
Название учетной записи Kafka. Если название не указано, то настройки авторизации не будут применены. |
OBERTO_KAFKA_AUTH_PASSWORD |
string | Нет | "" |
Пароль учетной записи Kafka. |
OBERTO_KAFKA_AUTH_PRINCIPAL |
string | Нет | "" |
Principal учетной записи Kafka в Kerberos(в случае соединения с kafka через Kerberos). |
OBERTO_KAFKA_AUTH_KEYTAB_PATH |
string | Нет | "" |
Путь до keytab-файла (в случае соединения с kafka через Kerberos). |
OBERTO_KAFKA_AUTH_TRUSTSTORE_LOCATION |
string | Нет | "" |
Путь до хранилища сертификатов (Java key store). Если путь не указан, то сертификат применяться не будет. |
OBERTO_KAFKA_AUTH_TRUSTSTORE_PASSWORD |
string | Нет | "" |
Пароль к хранилищу сертификатов. |
OBERTO_KAFKA_AUTH_MODE |
string | Нет | static |
Режим аутентификации: static - одна учетная запись на все запросы, mapping - учетная запись зависит от запроса. |
OBERTO_KAFKA_AUTH_CONFIG |
string | Нет | "" |
Настройки для аутентификации: если AuthMode = mapping, то необходим JSON с List[KafkaAuthConfig]. Переменная соответствует полю authConfig из KafkaAuthSettings. |
OBERTO_KAFKA_AUTH_CACHE_SIZE |
long | Нет | Максимальный размер кеша для Kafka producer (количество активных соединений). | |
OBERTO_KAFKA_CONNECTION_CHECK_TEST_MESSAGES_INTERVAL |
duration string | Нет | 4 minutes |
Применяется только для producer-ов со способом аутентификации kerberos. Интервал отправки тестовых сообщений кафки в топик connectionCheck.testMessagesTopicName. Тестовые сообщения (null, service producer test) отправляются регулярно с этим интервалом. |
OBERTO_KAFKA_CONNECTION_CHECK_INTERVAL |
duration string | Нет | 60 seconds |
Применяется только для producer-ов со способом аутентификации kerberos. Интервал проверки того, сколько тестовых сообщений было отправлено за данный период. Если количество сообщений за этот период равно количеству сообщений за прошлый период, то начинается отсчет периода без сообщений. |
OBERTO_KAFKA_CONNECTION_CHECK_FAILED_AFTER_INTERVAL |
duration string | Нет | 5 minutes |
Применяется только для producer-ов со способом аутентификации kerberos. Максимальная продолжительность периода без успешно отправленных тестовых сообщений. По ее достижении сервис будет объявлен больным. |
OBERTO_KAFKA_AUTH_CACHE_TTL |
duration string | Нет | Время жизни Kafka producer в кеше. | |
OBERTO_CONSUL_ADDR |
string | Да | http://localhost:8500 |
Адрес Сonsul. |
OBERTO_CONSUL_AUTH_USER |
string | Нет | "" |
Название учетной записи Сonsul. Если название не указано, то настройки авторизации не будут применены. |
OBERTO_CONSUL_AUTH_PASSWORD |
string | Нет | "" |
Пароль учетной записи Сonsul. |
OBERTO_TRACE_DURATION |
boolean | Нет | false |
Нужно ли логировать длительность выполнения команд. |
OBERTO_DISCOVERABLE_ID |
string | Нет | another_oberto_instance |
ID данного сервиса. |
OBERTO_DISCOVERABLE_NAME |
string | Да | oberto |
Название группы сервисов, к которой принадлежит данный. |
OBERTO_DISCOVERABLE_HOST |
string | Нет | localhost |
Адрес текущего инстанса сервиса, который будет виден через ServiceDiscovery. |
OBERTO_DISCOVERABLE_PORT |
int | Нет | ${OBERTO_HTTP_PORT} |
Адрес текущего инстанса сервиса, который будет виден через ServiceDiscovery. |
OBERTO_DISCOVERABLE_LIVETIME |
duration string | Нет | 2 minutes |
Время с последнего HeathCheck, в течении которого сервис считается "живым". |
OBERTO_DISCOVERABLE_HEALTHPASS |
duration string | Нет | 1 minute |
Периодичность отправки HeathCheck. |
OBERTO_INTERNALCMD_ALLOW |
boolean | Нет | true |
Можно ли сервису отправлять "внутренние" команды. |
OBERTO_SENDERLIB_CONSIDER_ALL_COMMANDS_AS_INTERNAL |
boolean | Нет | false |
Флаг, определяющий будут ли все обращения в другие сервисы являться внутренними (т.е. не требовать авторизацию). Детальное описание механизма: Внутренние команды. |
OBERTO_SENDERLIB_COMMANDS_CACHE_UPDATEPERIOD |
duration string | Нет | 10 minutes |
Время, на которое будут кешироваться данные о командах. |
OBERTO_SENDERLIB_SERVICES_CACHE_UPDATEPERIOD |
duration string | Нет | 30 seconds |
Время, на которое будут кешироваться данные о сервисах. |
OBERTO_AUTHZFORCE_ENABLE |
boolean | Нет | false |
Включены ли команды/функции связанные с AuthZforce server. |
OBERTO_AUTHZFORCE_ADDR |
string | Да | http://localhost:8080/authzforce-ce |
Адрес AuthZforce server. |
OBERTO_AUTHZFORCE_DOMAIN |
string | Нет | not defined |
Доступный DomainID в AuthZforce server. |
OBERTO_AUTHZFORCE_DEFAULT |
string | Нет | deny |
Поведение контроля доступа по умолчанию: deny - все запрещено, пока не будет получено разрешение; permit - все разрешено, пока не будет получен запрет. |
OBERTO_AUTHZFORCE_PREFER_RULE |
string | Нет | deny |
Выбор приоритета для правил: deny - при наличии двух и более применяемых правил для запроса авторизации, приоритет отдается первому запрещающему правилу; permit - в случае нескольких применяемых правил, приоритет отдается первому разрешающему правилу. |
OBERTO_AUTHZFORCE_PROVIDER_TYPE |
string | Нет | "" |
Тип AttributeProvider, который используется в Authzforce server (указан в его конфиге). Указывается в случае, если нужно работать с AttributeProvider из сервиса Oberto. |
OBERTO_AUTHZFORCE_PROVIDER_ID |
string | Нет | "" |
Идентификатор AttributeProvider, который используется в Authzforce server (указан в его конфиге). Указывается в случае, если нужно работать с AttributeProvider из сервиса Oberto. |
OBERTO_AUTHZFORCE_DEBUG_RETURN_POLICY_ID |
boolean | Нет | false |
Добавлять ли в ответ от Authzforce список политик, которые учитывались при расчете ответа. |
OBERTO_AUTHZFORCE_ATTRIBUTES_CACHE_SIZE |
long | Нет | 1000 |
Максимальный размер кеша атрибутов для локального AttributeProvider, который используется в Oberto. |
OBERTO_AUTHZFORCE_ATTRIBUTES_CACHE_TTL |
duration string | Нет | 5 minutes |
Максимальное время кеширования атрибутов для локального AttributeProvider, который используется в Oberto. |
OBERTO_AUTHZFORCE_ATTRIBUTES_REQUEST_TIMEOUT |
duration string | Нет | 30 seconds |
Максимальное время ожидания завершения запроса атрибутов из сервиса data-model для локального AttributeProvider, который используется в Oberto. |
OBERTO_AUTHZFORCE_ATTRIBUTES_CMD_MAPPING |
string | Нет | "" |
Список префиксов атрибутов и связанных с ними команд. Отображение 1 к 1. Требуется особый формат. |
OBERTO_AUTHZFORCE_POLICIES_REQUEST_TIMEOUT |
duration string | Нет | 30 seconds |
Максимальное время ожидания завершения запроса политики для локального PolicyProvider, который используется в Oberto. |
OBERTO_AUTHZFORCE_POLICIES_REF_DEPTH |
int | Нет | 10 |
Максимальная глубина вложенных ссылок на политики. |
OBERTO_AUTHZFORCE_POLICIES_MAX_VERSIONS |
int | Нет | 10 |
Максимальное количество версий для одной политики. |
OBERTO_AUTHZFORCE_POLICIES_CLEAN_PERIOD |
duration string | Нет | 10 minutes |
Период проверки списка политик для удаления версий, которые превышают лимит OBERTO_AUTHZFORCE_POLICIES_MAX_VERSIONS. |
OBERTO_AUTHZFORCE_POLICIES_DENY_BY_DEFAULT |
boolean | Нет | true |
Поведение по умолчанию: запрещено ли действие, если оно явно не регулируется. |
OBERTO_AUTHZFORCE_POLICIES_COMBINE_ALG |
string | Нет | urn:oasis:names:tc:xacml:1.0:policy-combining-algorithm:first-applicable |
Идентификатор алгоритма для комбинации политик. |
OBERTO_DEBUGMODE |
boolean | Нет | false |
Режим отладки, в котором можно редактировать политики без проверки наличия прав. |
OBERTO_READABLE_NAME |
string | Нет | Сервис системы прав |
Читаемое название этого сервиса. |
OBERTO_DESCRIPTION |
string | Нет | Сервис системы прав |
Читаемое описание этого сервиса. |
OBERTO_DB_URL |
jdbc url string | Нет | "jdbc:postgresql://"${?OBERTO_DB_HOST}":"${?OBERTO_DB_PORT}"/"${?OBERTO_DB_NAME} |
Адрес базы данных. Можно использовать вместо DB_HOST, DB_PORT и DB_NAME. |
OBERTO_DB_HOST |
string | Да | Хост сервера базы данных. | |
OBERTO_DB_PORT |
int | Да | Порт сервера базы данных. | |
OBERTO_DB_NAME |
string | Да | Название базы данных. | |
OBERTO_DB_USER |
string | Да | Пользователь базы данных. | |
OBERTO_DB_PASSWORD |
string | Да | Пароль для пользователя базы данных. | |
OBERTO_DB_THREADS |
int | Нет | 10 |
Количество потоков в пуле потоков для соединения с БД. |
OBERTO_DB_QUEUE_SIZE |
int | Нет | 300 |
Размер очереди для действий базы данных, которые не могут быть выполнены немедленно, когда все потоки заняты. За пределами этого значения новые действия немедленно завершаются неудачей. |
OBERTO_DB_CONN_MAX |
int | Нет | 10 |
Максимальное количество одновременных подключений к БД. |
OBERTO_DB_CONN_TIMEOUT |
duration string | Нет | 20 second |
Максимальное время ожидания ответа для соединения к БД. Если это время превышено, а соединение не становится доступным, будет брошено исключение SQLException. 1000 мс — минимальное значение. |
OBERTO_DB_ISOLATION |
string | Нет | READ_COMMITTED |
Уровень изоляции транзакций для новых подключений. Допустимые значения: NONE, READ_COMMITTED, READ_UNCOMMITTED, REPEATABLE_READ, SERIALIZABLE. |
OBERTO_DB_READONLY |
boolean | Нет | false |
Read-only SQL транзакция может изменять только временные таблицы. Этот параметр управляет статусом «только для чтения» по умолчанию для каждой новой транзакции. |
OBERTO_DB_CONN_MIN |
int | Нет | ${OBERTO_DB_THREADS} |
Минимальное количество одновременных подключений к БД. |
OBERTO_DB_VALIDATION_TIMEOUT |
duration string | Нет | 1 seconds |
Максимальное время, в течение которого соединение будет проверяться на работоспособность. 1000 мс — минимальное значение. |
OBERTO_DB_IDLE_TIMEOUT |
duration string | Нет | 10 minutes |
Максимальное время, в течение которого соединению разрешено простаивать в пуле. Значение 0 означает, что простаивающие соединения никогда не удаляются из пула. |
OBERTO_DB_MAX_LIFETIME |
duration string | Нет | 30 minutes |
Максимальное время жизни соединения в пуле. Когда простаивающее соединение достигает этого времени ожидания, даже если оно недавно использовалось, оно будет удалено из пула. Значение 0 указывает на отсутствие максимального срока службы. |
OBERTO_DB_INITIALIZATION_FAIL_FAST |
boolean | Нет | false |
Deprecated, начиная с версии Slick 3.3.0. Определяет, будет ли пул «быстро выходить из строя», если пул не может быть успешно заполнен начальными соединениями. Если соединения не могут быть созданы во время запуска пула, будет выдано исключение RuntimeException. Это свойство не имеет никакого эффекта, если minConnections равно 0. |
OBERTO_DB_LEAK_DETECTION_THRESHOLD |
int | Нет | 0 |
Время, в течение которого соединение может находиться вне пула, прежде чем будет зарегистрировано сообщение, указывающее на возможную утечку соединения. Значение 0 означает, что обнаружение утечек отключено. Наименьшее приемлемое значение для включения обнаружения утечек составляет 10 с. |
OBERTO_DB_CONNECTION_TEST_QUERY |
string | Нет | SELECT 1 |
Выражение, которое будет выполнено непосредственно перед получением соединения из пула для проверки того, что соединение с базой данных все еще активно. Оно зависит от базы данных и должно представлять собой запрос, требующий минимальной обработки базой данных (например, «VALUES 1»). Если этот параметр не установлен, вместо него используется метод JDBC4 Connection.isValid(). |
OBERTO_DB_AUTO_COMMIT |
boolean | Нет | true |
Это свойство определяет то, как будут вести себя по умолчанию возвращаемые соединения относительно autocommit-а. |
OBERTO_DB_SCHEMA |
string | Нет | public |
Устанавливает schema по умолчанию. |
OBERTO_DB_ISOLATE_INTERNAL_QUERIES |
boolean | Нет | false |
Определяет то, изолируются ли с помощью транзакций внутренние запросы пула (например запрос connection alive test). Свойство применяется только если autoCommit выключен. |
OBERTO_DB_INITIALIZATION_FAIL_TIMEOUT |
int | Нет | 1 |
Работает, начиная с версии Slick 3.3.0. Определяет, будет ли пул «быстро выходить из строя», если пул не может быть успешно заполнен начальными соединениями. Любое положительное число считается числом миллисекунд для попытки получить начальное соединение; поток приложения будет заблокирован в течение этого периода. Если соединение не может быть получено до истечения этого времени, будет брошено исключение. Данный таймаут применяется после периода connectionTimeout. Если значение равно нулю (0), HikariCP попытается получить и проверить подключение. Если соединение получено, но проверка не пройдена, будет брошено исключение, и пул не будет запущен. Однако, если соединение не может быть получено, пул запустится, но последующие попытки получить соединение могут потерпеть неудачу. Значение меньше нуля пройдет любую первоначальную попытку подключения, и пул немедленно запустится, пытаясь получить соединения в фоновом режиме. Следовательно, последующие попытки получить соединение могут потерпеть неудачу. |
OBERTO_DB_REGISTER_MBEANS |
boolean | Нет | false |
Зарегистрированы ли JMX Management Beans («MBeans»). |
OBERTO_SENDERLIB_COMMANDS_HTTP_RETRY_ATTEMPTS |
int | Нет | 5 |
Поле attempts из RetrySettings. |
OBERTO_SENDERLIB_COMMANDS_HTTP_RETRY_DELAY |
duration string | Нет | 5 seconds |
Поле delay из RetrySettings. |
OBERTO_SENDERLIB_COMMANDS_HTTP_RETRY_KIND |
string | Нет | OnSomeExceptions(ConnectException) |
CommandResultRetryConditionKind. |
OBERTO_SENDERLIB_CONSUL_CONNECTION_RETRY_MAX |
int | нет | 5 |
Количество попыток переподключения к Consul |
OBERTO_SENDERLIB_CONSUL_CONNECTION_RETRY_DELAY |
duration string | нет | 1 second |
Задержка при попытках переподключения к Consul |
OBERTO_LICENSE_PATH |
string | Да | "" |
Путь до файла с лицензией (только binary format). Данная переменная обязательна для работы. |
OBERTO_LICENSE_KEY |
string | Да | "" |
Путь до файла с публичным ключом лицензией. Данная переменная обязательна для работы. |
OBERTO_JOURNAL_MODE |
string | нет | WriteToJournal |
Режим журналирования Nestor. Допустимые значения: WriteToJournal (Отправка в сервис журналирования), WriteToTopic (Отправка события в очередь) |
OBERTO_JOURNAL_TOPIC |
string | Да, если переменная OBERTO_JOURNAL_MODE = WriteToTopic |
"" |
Название очереди журналирования. Для режима WriteToJournal значение игнорируется. |
OBERTO_LICENSE_PATH_PRIORITY |
string | Нет | "" |
Порядок использования лицензий. При пустом значении - порядок будет соответствовать порядку путей до файлов лицензий (OBERTO_LICENSE_PATH). Строка должна содержать приоритет для каждой лицензии, приоритеты разделяются запятой (например, 1,5,2) - лицензии будут обрабатываться в порядке возрастания приоритета. |
Режим отладки (debug mode)
Режим отладки нужен для того, чтобы добавить/удалить/изменить политики без наличия на это прав.
Например, когда политики настроены неверно и пропал доступ к редактированию самих политик.
Также этот режим может быть полезен при первоначальной настройке.
При разворачивании сервиса, в нем присутствует политика, которая разрешает все действия "permit-all", но пока не будет добавлена какая-либо политика.
Этот режим поможет избежать ситуации, когда политика, разрешающая редактирование политик, не была добавлена первой.
Режим отладки включается установкой переменной окружения OBERTO_DEBUGMODE=true.
Политики по умолчанию
При каждом запуске сервис Oberto проверят доступные хранилища политик на возможность создать политики по умолчанию.
Политиками по умолчанию являются:
- Политика разрешающая любые действия (название: "default_AllowEverything", приоритет: 1)
- Политика разрешающая работу с политиками (PolicySet), правилами (HighLevelRule) и доступ в раздел админки (
AdministrationSection) (название: "default_Control-Authorization", приоритет: 1000)
Такие политики создаются если: - в хранилище нет ни одной политики (даже root)
- в хранилище только одна root политика (стандартный кейс №1)
- в хранилище только root политика и политика со стандартным поведением (DefaultBehaviorPolicySet) (стандартный кейс
№2)
При добавлении политик также отправляется событие журнала "о добавлении политики".
Если в хранилище уже были добавлены какие-то нестандартные политики, то политики по умолчанию не добавляются.
Внешние AttributeProvider
Сервис Oberto, в добавок к стандартному DataModel, умеет работать с внешними AttributeProvider-ами, которые используются при проверке правил доступа к ресурсу.
AttributeProvider-ы нужны для получения атрибутов, которые используются в правиле, но не были переданы в запросе авторизации AuthorizationRequestDTO.
Пример:
- У нас есть правило
"User.id == datamodel.MyDocument.authorId" - В запрос авторизации, через метод
authorizer.authorizeCommand, передается тип ресурса, его id и контекст запроса, в котором происходит авторизация
В итоге, в момент проверки правила у нас есть следующие атрибуты:
User.idиз контекста запросаRequestContext- ResourceType из запроса авторизации (MyDocument)
- MyDocument.id из запроса авторизации
Неизвестный атрибут datamodel.MyDocument.authorId будет передан PdpEngine-ом (authzforce) в общий атрибут провайдер сервиса Oberto.
Процесс обработки запроса общим провайдером атрибутов
Все атрибуты должны соответствовать паттернам: либо ServiceName.Resource.PathToField либо Resource.PathToField.
Все сервисы (ServiceName) должны быть в маппинге сервис-команда (переменная OBERTO_AUTHZFORCE_ATTRIBUTES_CMD_MAPPING).
- Атрибут проверяется на соответствие паттернам
- Если в названии атрибута присутствует
ServiceName, то происходит попытка поиска команды из маппинга - Отправка запроса
- Если команда найдена в маппинге, то отправляется запрос с телом AttributeRequest
- Если команда не найдена, то отправляется запрос в сервис data-model:
internalGetObject(обычное поле) илиinternalRichGetObject(поле связанного объекта).
- При возможности, ответ от внешнего сервиса кешируется (зависит от настроек )
- После получения ответа от внешнего сервиса, ответ преобразуется в AttributeResponse
- общий провайдер атрибутов в Oberto извлекает из AttributeResponse поле
value, чтобы вернуть его вPdpEngine(authzforce)
К внешним AttributeProvider-ам предъявляются следующие требования:
- Внешние провайдеры должны реализовать 1 команду, которая принимает AttributeRequest и отвечает AttributeResponse
- В случае ошибок возвращается ErrorResponse
- Путь до поля в AttributeRequest всегда будет приходить в lower case.
- Префикс в начале атрибута до первой точки (
.) используется в качестве ключа для маппинга команд. - Поле context
Возможные ошибки
Ресурс не найден
{
"code": {
"statusCode": 404
},
"message": "ERROR: Entity object not found",
"stackTrace": null,
"businessError": null,
"data": null
}
Внешний провайдер должен вернуть
ErrorResponse(code = ErrorResponseCode.HttpError(404), message = Some("ERROR: Entity object not found"))
Запрашиваемое поле не найдено в ресурсе / несоответствие схеме
{
"code": "InvalidParameters",
"message": "ERROR: field first_field for entityType 'MyDocument' not found",
"stackTrace": null,
"businessError": null,
"data": null
}
Если запрашиваемое поле не соответствует схеме (например, "MyDocument" не содержит "first_field"),
то внешний провайдер должен вернуть
ErrorResponse(code = ErrorResponseCode.InvalidParameters, message = Some("ERROR: field first_field for entityType 'MyDocument' not found"))
Список команд сервиса Oberto
В описании команд используется путь/route для отправки команды в сам сервис, а не в ApiGateway. В качестве Input-а для команд, сервис всегда ожидает CommandRequest (как и любой другой сервис, принимающий команды), так что в описании команды указано лишь описание поля payload для CommandRequest.
Информация по добавлению команд можно прочитать в описании шаблона
Информация по описанию правил для разграничения доступов: Формат описания правил
| Название команды | EntityType | Actions |
|---|---|---|
| oberto_ListPolicyRecords | PolicySet | Edit |
| oberto_ListPolicyRecordsV2 | PolicySet | Edit |
| oberto_GetPolicyValue | PolicySet | Edit |
| oberto_GetPolicyValueV2 | PolicySet | Edit |
| oberto_DeletePolicy | PolicySet | Edit |
| oberto_DeletePolicyV2 | PolicySet | Edit |
| oberto_DeleteAllPolicyVersions | PolicySet | Edit |
| oberto_DeleteAllPolicyVersionsV2 | PolicySet | Edit |
| oberto_UpdatePolicy | PolicySet | Edit |
| oberto_UpdatePolicyV2 | PolicySet | Edit |
| oberto_OverridePoliciesFromSource | PolicySet | Edit |
| oberto_Authorize | - | - |
| oberto_AuthorizeV2 | - | - |
| oberto_AuthorizeList | - | - |
| oberto_AuthorizationRequest | - | - |
ListPolicyRecords (oberto)
Payload для команды
null
Результат выполнения команды
[
{
"id": "Any_Policy_Name",
"priority": 1000,
"versions": [
"0.1.0",
"0.1.1",
"0.1.2"
]
}
]
Возвращает список политик с информацией об их идентификаторе и приоритете, а также со списком их версий.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: null
- Result: List[PolicyRecord]
| Команда | Путь |
|---|---|
| oberto_ListPolicyRecords | HTTP POST "/v1/policy/list" |
ListPolicyRecordsV2 (oberto)
Payload для команды
null
Результат выполнения команды
[
{
"id": "Any_Policy_Name",
"priority": 1000,
"versions": [
"0.1.0",
"0.1.1",
"0.1.2"
]
}
]
Возвращает список политик с информацией об их идентификаторе и приоритете, а также со списком их версий.
В отличие от ListPolicyRecords, обращается за политиками не в authzforce по http, а в таблицу PolicySet базы данных сервиса oberto.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: null
- Result: List[PolicyRecord]
| Команда | Путь |
|---|---|
| oberto_ListPolicyRecordsV2 | HTTP POST "/v1/policy/list_v2" |
GetPolicyValue (oberto)
Payload для команды
{
"id": "Any_Policy_Name",
"version": "0.1.1"
}
Результат выполнения команды
{
"policyId": "Any_Policy_Name",
"version": "0.1.1",
"priority": 1000,
"description": "Policy effects description",
"rules": [
{
"ruleId": "Policy_rule_ID",
"rule": "permit Actions(View_WebDoc, somesvc_ListItems, other_UpdateEntity) if User.email endsWith '_employee@email.io'",
"priority": 1,
"filters": "ResourceType.innerObject.value >= '100'"
}
]
}
Возвращает данные указанной версии политики.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: SinglePolicy
- Result: Option[PolicyUpdateDto]
| Команда | Путь |
|---|---|
| oberto_GetPolicyValue | HTTP POST "/v1/policy/single" |
GetPolicyValueV2 (oberto)
Payload для команды
{
"id": "Any_Policy_Name",
"version": "0.1.1"
}
Результат выполнения команды
{
"policyId": "Any_Policy_Name",
"version": "0.1.1",
"priority": 1000,
"description": "Policy effects description",
"rules": [
{
"ruleId": "Policy_rule_ID",
"rule": "permit Actions(View_WebDoc, somesvc_ListItems ,other_UpdateEntity) if User.email endsWith '_employee@email.io'",
"priority": 1,
"filters": "ResourceType.innerObject.value >= '100'"
}
]
}
Возвращает данные указанной версии политики.
В отличие от GetPolicyValue, обращается за политиками не в authzforce по http, а в таблицу PolicySet базы данных сервиса oberto.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: SinglePolicy
- Result: Option[PolicyUpdateDto]
| Команда | Путь |
|---|---|
| oberto_GetPolicyValueV2 | HTTP POST "/v1/policy/single_v2" |
DeletePolicy (oberto)
Payload для команды
{
"id": "Any_Policy_Name",
"version": "0.1.1"
}
Результат выполнения команды
true
Удаляет указанную версию политики.
Поддерживается только синхронный вызов.
Результат выполнения команды журналируется.
- Payload: SinglePolicy
- Result: Boolean
| Команда | Путь |
|---|---|
| oberto_DeletePolicy | HTTP POST "/v1/policy/delete" |
DeletePolicyV2 (oberto)
Payload для команды
{
"id": "Any_Policy_Name",
"version": "0.1.1"
}
Результат выполнения команды
true
Удаляет указанную версию политики.
В отличие от DeletePolicy, обращается за политиками не в authzforce по http, а в таблицу PolicySet базы данных сервиса oberto.
Поддерживается только синхронный вызов.
Результат выполнения команды журналируется.
- Payload: SinglePolicy
- Result: Boolean
| Команда | Путь |
|---|---|
| oberto_DeletePolicyV2 | HTTP POST "/v1/policy/delete_v2" |
DeleteAllPolicyVersions (oberto)
Payload для команды
"Any_Policy_Name"
Результат выполнения команды
true
Удаляет все версии для указанного идентификатора политики.
Поддерживается только синхронный вызов.
Результат выполнения команды журналируется.
- Payload: PolicyId
- Result: Boolean
| Команда | Путь |
|---|---|
| oberto_DeleteAllPolicyVersions | HTTP POST "/v1/policy/deleteAll" |
DeleteAllPolicyVersionsV2 (oberto)
Payload для команды
"Any_Policy_Name"
Результат выполнения команды
true
Удаляет все версии для указанного идентификатора политики.
В отличие от DeleteAllPolicyVersions, обращается за политиками не в authzforce по http, а в таблицу PolicySet базы данных сервиса oberto.
Поддерживается только синхронный вызов.
Результат выполнения команды журналируется.
- Payload: PolicyId
- Result: Boolean
| Команда | Путь |
|---|---|
| oberto_DeleteAllPolicyVersionsV2 | HTTP POST "/v1/policy/deleteAll_v2" |
UpdatePolicy (oberto)
Payload для команды
{
"policyId": "Any_Policy_Name",
"version": "0.1.1",
"priority": 1000,
"description": "Policy effects description",
"rules": [
{
"ruleId": "Policy_rule_ID",
"rule": "permit Actions(View_WebDoc, somesvc_ListItems ,other_UpdateEntity) if User.email endsWith '_employee@email.io'",
"priority": 1,
"filters": "ResourceType.innerObject.value >= '100'"
}
]
}
Результат выполнения команды
true
Добавляет версию политики. Каждая версия должна иметь уникальное policyId и уникальную version внутри
политики. Policy_rule_ID должны быть уникальными внутри текущей версии.
Поддерживается только синхронный вызов.
Результат выполнения команды журналируется.
- Payload: PolicyUpdateDto
- Result: Boolean
| Команда | Путь |
|---|---|
| oberto_UpdatePolicy | HTTP POST "/v1/policy/update" |
UpdatePolicyV2 (oberto)
Payload для команды
{
"policyId": "Any_Policy_Name",
"version": "0.1.1",
"priority": 1000,
"description": "Policy effects description",
"rules": [
{
"ruleId": "Policy_rule_ID",
"rule": "permit Actions(View_WebDoc, somesvc_ListItems ,other_UpdateEntity) if User.email endsWith '_employee@email.io'",
"priority": 1,
"filters": "ResourceType.innerObject.value >= '100'"
}
]
}
Результат выполнения команды
true
Добавляет версию политики. Каждая версия должна иметь уникальное policyId и уникальную version внутри
политики. Policy_rule_ID должны быть уникальными внутри текущей версии.
В отличие от UpdatePolicy, обращается за политиками не в authzforce по http, а в таблицу PolicySet базы данных сервиса oberto.
Поддерживается только синхронный вызов.
Результат выполнения команды журналируется.
- Payload: PolicyUpdateDto
- Result: Boolean
| Команда | Путь |
|---|---|
| oberto_UpdatePolicyV2 | HTTP POST "/v1/policy/update_v2" |
OverridePoliciesFromSource (oberto)
На входе источник политик для override (поддерживает только значение "Authzforce")
"Authzforce"
На выходе количество добавленных версий политик
10
Удаляет все версии политик и добавляет последние версии из указанного источника политик.
Поддерживается только синхронный вызов.
Результат выполнения команды журналируется.
- Payload: XacmlPolicySource
- Result: Int
| Команда | Путь |
|---|---|
| oberto_OverridePoliciesFromSource | HTTP POST "/v1/policy/overridePoliciesFromSource" |
Authorize (oberto)
Payload для команды
{
"resourceId": "123456",
"resourceType": "ProposalFile",
"actions": [
"DownloadFile",
"View_WebDoc"
],
"attributes": {
"my_custom_attribute": [
"value_for_this_attribute",
"another_value"
]
}
}
Результат выполнения команды
{
"DownloadFile": true,
"View_WebDoc": true
}
Проверяет доступность действий для конкретного ресурса, указанных во входных параметрах.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: CommandsAuthorization
- Result: Map[String, Boolean]
| Команда | Путь |
|---|---|
| oberto_Authorize | HTTP POST "/v1/authorize" |
AuthorizeV2 (oberto)
Payload для команды
{
"resourceId": "123456",
"resourceType": "ProposalFile",
"actions": [
"DownloadFile",
"View_WebDoc"
],
"attributes": {
"my_custom_attribute": [
"value_for_this_attribute",
"another_value"
]
}
}
Результат выполнения команды
{
"DownloadFile": true,
"View_WebDoc": true
}
Проверяет доступность действий для конкретного ресурса, указанных во входных параметрах. Отличается от "первой версии" тем, что не делает вызов в Authzforce-server (локальный расчет политик).
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: CommandsAuthorization
- Result: Map[String, Boolean]
| Команда | Путь |
|---|---|
| oberto_AuthorizeV2 | HTTP POST "/v1/authorize_v2" |
AuthorizeList (oberto)
Payload для команды
[
{
"resourceId": "0000",
"resourceType": "resource_type_name_1",
"actions": [
"action_name_1",
"action_name_2"
],
"attributes": {}
},
{
"resourceId": "1111",
"resourceType": "resource_type_name_1",
"actions": [
"action_name_2"
],
"attributes": {}
},
{
"resourceId": "0000",
"resourceType": "resource_type_name_1",
"actions": [
"action_name_3"
],
"attributes": {}
}
]
Результат выполнения команды
[
{
"resourceId": "0000",
"resourceType": "resource_type_name_1",
"actions": {
"action_name_1": true,
"action_name_2": false,
"action_name_3": false
}
},
{
"resourceId": "1111",
"resourceType": "resource_type_name_1",
"actions": {
"action_name_2": false
}
}
]
Проверяет доступность действий для произвольного списка ресурсов, указанных во входных параметрах. Команда работает только с oberto. Сервис Authzforce не поддерживается.
Имя команды для вызова: oberto_AuthorizeList.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: List[CommandsAuthorization]
- Result: List[AuthorizeListCommandResponse]
| Команда | Путь |
|---|---|
| oberto_AuthorizeList | HTTP POST "/v1/authorizeList" |
AuthorizationRequest (oberto)
Payload для команды
{
"attributes": [
{
"id": "MyDocument.id",
"cat": "urn:oasis:names:tc:xacml:3.0:attribute-category:resource",
"values": [
"123",
"987"
]
},
{
"id": "User.departmentCode",
"cat": "urn:oasis:names:tc:xacml:1.0:subject-category:access-subject",
"values": [
"FirstDepartmentCode",
"SecondDepartmentCode"
]
}
],
"userContext": {
"id": "67287d83-25dd-4d3c-9559-e5cc02860a3f",
"emailOpt": "test_user_email@embedika.ru",
"groupIds": [
"group_for_regular_users",
"group_for_admins"
]
}
}
Результат выполнения команды
{
"allow": true,
"entityFilters": "MyResource.name contains 'Test resource'"
}
Выполняет запрос авторизации с указанными параметрами. Не делает вызов в Authzforce-server (локальный расчет политик). Если во входных данных не указано поле "userContext", то будут использованы данные пользователя, который вызвал данную команду.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- Payload: AuthorizationRequestDTO
- Result: AuthorizationResult
| Команда | Путь |
|---|---|
| oberto_AuthorizationRequest | HTTP POST "/v1/authorizationRequest" |
Модели сервиса Oberto
PolicyId (oberto)
Идентификатор политики. Соответствует типу String.
XacmlPolicySource (oberto)
Идентификатор источника политик. Поддерживаемые значения: Authzforce.
CommandsAuthorization (oberto)
Данные для авторизации набора действий по отношению к заданному ресурсу.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| resourceId | String | Нет | Идентификатор конкретного объекта с типом resourceType, для которого проверяются actions. |
| resourceType | String | Нет | Название типа ресурса, для которого проверяются actions. |
| actions | List[String] | Да | Список идентификаторов действий. Может быть пустым, но тогда и результат будет пустым (завершение команды без проверок доступа). |
| attributes | Map[String, List[String]] | Нет | Произвольный список атрибутов ресурса (можно задавать атрибуты любого ресурса). Пример: '{ "MyDocument.authorId": ["123"] }'. |
AuthorizeListCommandResponse (oberto)
Результат выполнения команды пакетной авторизации: данные о наличии доступа для набора действий по отношению к заданному ресурсу.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| resourceId | String | Нет | Идентификатор конкретного объекта с типом resourceType, для которого проверяются actions. |
| resourceType | String | Нет | Название типа ресурса, для которого проверяются actions. |
| actions | Map[String, Boolean] | Да | Список соответствия идентификатора действия и результата проверки наличия доступа. |
PolicyRecord (oberto)
Запись с информацией о политике и набором ее версий.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | PolicyId | Да | Идентификатор политики |
| priority | Int | Нет | Приоритет политики (чем меньше, тем раньше она будет проверена). null = после всех политик, у которых установлен приоритет. |
| versions | List[String] | Да | Список версий политик. Версия представлена в виде строки (semver) и должна соответствовать regexp "\d{1,16}\.\d{1,16}\.\d{1,16}", где доступны только цифры и точки: "0.1.0". |
SinglePolicy (oberto)
Идентификатор конкретной версии политики.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | PolicyId | Да | Идентификатор политики |
| version | String | Да | Версия политики. В данной структуре, версия не должна соответствовать какому-либо формату. |
PolicyUpdateDto (oberto)
Данные новой версии политики.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| policyId | PolicyId | Да | Идентификатор политики. Должен быть уникальным значением в рамках всей системы. |
| version | String | Да | Версия политики, представленная в виде строки (semver). Должна быть уникальной в рамках политики и соответствовать regexp "\d{1,16}\.\d{1,16}\.\d{1,16}". |
| priority | Int | Нет | Приоритет политики (чем меньше, тем раньше она будет проверена). null = после всех политик, у которых установлен приоритет. |
| description | String | Да | Описание политики. |
| rules | List[PolicyRuleDto] | Да | Список правил. |
PolicyRuleDto (oberto)
Описание правила применяемого в политике.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| ruleId | String | Да | Идентификатор правила. Должен быть уникальным значением в рамках политики. |
| rule | String | Да | Правило применения эффекта (permit/deny). Формат описания правил. |
| priority | Int | Да | Приоритет правила (чем меньше, тем раньше оно будет проверено). |
| filters | Condition | Нет | Фильтры, которые нужно применить при обращении к списку. |
AuthorizationRequestDTO (oberto)
Параметры запроса авторизации.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| attributes | List[AttributeWithValues] | Да | Список атрибутов и их значений для запроса. |
| userContext | UserContext | Нет | Данные о пользователе, для которого будет проверяться доступность. Нужно в том случае, если проверяемый пользователь отличается от пользователя, который вызвал запрос авторизации. |
AttributeProviderSettings (oberto)
Настройки провайдера атрибутов в Oberto.
| Поле | Тип | Обязательное | Описание | Значение по умолчанию |
|---|---|---|---|---|
| cacheConfig | VerdiCacheConfig | Нет | Настройки для кеша атрибутов. | maxSize = 1000, elementTTL = 5 minutes |
| requestTimeout | duration string | Нет | Время ожидания выполнения запроса к внешней системе. | 30 seconds |
| commandsMapping | string | Нет | Список префиксов атрибутов и связанных с ними команд. Отображение 1 к 1. | "" |
AttributeProvider-CommandsMapping (oberto)
Формат для маппинга префиксов атрибутов в команды внешних сервисов.
Для задания маппинга используется строка, в которой закодированы пары ключ значение через символ =.
В строке можно указывать несколько пар через разделитель ;, "Prefix1=CommandName1;Prefix2=CommandName2".
Например, MyResourceCode=My_Command_name; EntityType1 = internalGetObject ; Order= get_order_attribute_by_name.
Если в настройках задан некорректный формат, то при запуске сервиса Oberto будет ошибка ConfigurationException.
AttributeValueRequest (oberto)
Запрос значения атрибута у конкретного объекта.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| requestId | string | Да | Идентификатор запроса значения атрибута. |
| maybeServiceProvider | Option[string] | Нет | Префикс, который может быть использован в качестве ключа для маппинга. |
| objectIdentity | EntityObjectIdentity | Да | Идентификатор требуемого объекта. |
| fieldPathLowerCase | string | Да | Путь для требуемого атрибута в lower case. |
| context | Map[string, Seq[string]] | Да | Контекст запроса авторизации. |
AttributeRequest (oberto)
Настройки провайдера атрибутов в Oberto.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | EntityObjectIdentity | Да | Идентификатор требуемого объекта. |
| fieldPath | string | Да | Путь для требуемого атрибута в lower case. |
| context | Map[string, Seq[string]] | Да | Контекст запроса авторизации. |
AttributeResponse (oberto)
Настройки провайдера атрибутов в Oberto.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | EntityObjectIdentity | Да | Идентификатор объекта. |
| value | Either[Vector[string], string] | Да | Значение атрибута: Left - несколько значений, Right - одно значение. |
EntityObjectIdentity
Идентификатор объекта.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| entityType | string | Да | Типа сущности |
| objectId | uuid | Да | Идентификатор объекта, который уникален в рамках указанного типа |
Формат описания правил
RuleFormat (oberto)
Формат описания правил.
Шаблон для описания правил
{
permit
|
deny
} Actions(name, name, ...) if CONDITION
Варианты описания сравнения значений:
1) {User|name}.field.path Operation 'Value'
2) {anyOf|allOf} {User|name}.field.path Operation {anyOf|allOf} ['Value', 'Value', 'Value', ...]
Примеры правил: 1) разрешает редактирования политик (тип "PolicySet") если email пользователя начинается с "manager": permit Actions(Edit) if (resource.entityType == 'PolicySet' and User.email startsWith 'manager')
P.S. Условие на конкретный тип ресурса ("resource.entityType == 'PolicySet'") может быть записано, как только название ресурса без дополнительных условий ("PolicySet")
2) разрешает просмотр журнала событий (тип отсутствует, т.е. ограничивается только действием) если группа пользователя одна из списка или доступ требуется для определенного пользователя: permit Actions(ViewEventsJournal) if (User.groupId == anyOf ['manager', 'admin', 'business_admin'] or User.id = '123456789')
Описание правила можно разделить на несколько частей "Effect Actions IfClause"
- Effect может содержать одно из двух ключевых слов:
permin,deny - Actions содержит список действий, на которые будет распространяться правило. Список правил начинается со
слова
Actions, заключен в скобки и разделен запятыми.
Для списка A,B,C =>Actions(A, B, C). - IfClause содержит условия для пользователя и целевого ресурса, при выполнении которых будет применяться
правило.
Условия начинаются со словаifи разделены на группы. Внутри каждой группы могут быть другие группы условий или само условие.
Более подробно, структура описана на странице Condition.
Доступные операции для сравнения значений:
==два значения равны
>=левое значение больше или равно правому
<=левое значение меньше или равно правому
containsлевое значение содержит подстроку, равную правой
startsWithлевое значение начинается со строки, что справа
endsWithлевое значение заканчивается строкой, что справа
Plagiarism-plugin: плагин пересечений по тексту
Плагин отвечает за обработку одного из возможных шагов сервиса индексации - шага с payload-типом Plugin.
Плагин читает из kafka-топика сообщения от сервиса Indexation, содержащие stepProgress,
и обрабатывает файловые поля сущности stepProgress.entityObject. Обрабатываются только поля, содержащиеся в step.payload.fields.
Во время обработки плагин обращается к Lamp, чтобы найти файловые поля других сущностей, содержимое файлов в которых пересекается с содержимым полей step.payload.fields у сущности stepProgress.entityObject.
После этого, если степень похожести файлов превышает APP_MEASURE_THRESHOLD, между файловыми полями step.payload.fields сущности stepProgress.entityObject
и найденными файловыми полями других сущностей создаются ссылки в data-model.
Подробнее процесс обработки сообщений описан в документации трейта BaseFlow проекта IntelligentPluginCore.
Конфигурирование PlagiarismPlugin
Требования к запуску PlagiarismPlugin
Запуск из консоли с помощью SBT
sbt boot/run
При запуске сервиса ожидается, что уже развернута необходимая инфраструктура:
- Kafka по адресу
localhost:9092 - Consul по адресу
localhost:8500 - Lamp с версией, которая соответствует LAMP_USE_VERSION_2, по адресу
lamp-dev.dev.embedika.ru:443 - Если LAMP_USE_VERSION_2=false, то все файлы, присутствующие на стенде, должны быть закэшированы в Lamp
- Запущен инстанс сервиса tech-constants
- Сервис indexation зарегистрирован в tech-constants
Список переменных окружения для сервиса PlagiarismPlugin
| Переменная | Тип | Обязательная | Значение по умолчанию | Описание |
|---|---|---|---|---|
CONSUMER_TOPIC |
string | Нет | plagiarismPlugin |
Топик, в который поступает StepProgress на обработку. |
CONSUMER_GROUP |
string | Нет | plagiarismPlugin |
Имя группы-консьюмеров сервиса plagiarismPlugin. |
LAMP_USE_VERSION_2 |
boolean | Нет | false |
Использовать ли LAMP2 (true) или LAMP1 (false). |
LAMP_BUFFER_SIZE |
int | Нет | 10 |
Буфер на отправку сообщений в клиент LAMP. |
LAMP_RECONNECT_SCHEDULE |
string | Нет | I(2 seconds) |
Стратегия переподключения клиента LAMP (формат см. lamp.transport.model.Schedule). |
LAMP_HOST |
string | Нет | lamp-dev.dev.embedika.ru |
Адрес клиента LAMP (должен быть непустым, если LAMP_ENABLE=true). |
LAMP_PORT |
int | Нет | 443 |
Порт клиента LAMP (должен быть непустым, если LAMP_ENABLE=true). |
LAMP_TLS |
boolean | Нет | true |
Признак защищенного подключения к LAMP. |
LAMP_TLS_CERTIFICATE |
string | Нет | Путь файла с сертификатом для подключения к LAMP. | |
LAMP_TLS_PRIVATE_KEY |
string | Нет | Путь файла с приватным ключом для подключения к LAMP. | |
LAMP_TLS_ROOT_TRUSTED_CERTS |
string | Нет | Путь файла с центром сертификации (Certification Authority, CA) для подключения к LAMP. | |
LAMP_TIMEOUT |
duration string | Нет | 1 minute |
Таймаут отправки сообщения и получения результатов через клиент LAMP. |
LAMP_MAX_MESSAGE_SIZE |
int | Нет | 524288000 |
Максимальный допустимый размер сообщений в LAMP. |
LAMP_CACHEABLE_SERVICES |
string | Нет | extraction,keywords,lemmatization |
Строка, содержащая список сервисов LAMP, результаты которых будут кэшироваться внутри LAMP. При вызове одного рута LAMP может происходить обращение к нескольким сервисам LAMP. |
LAMP_PARAMETERS_OPERATION |
string | Нет | plagiarism |
Название операции, которое в качестве параметра передается в Lamp. |
APP_LINK_TYPE |
string | Нет | plagiarism |
Тип ссылки, создаваемой плагином в data-model. |
APP_LINK_OWNER |
string | Нет | plagiarism_mapper |
Link owner ссылки, создаваемой плагином в data-model. |
APP_MEASURE_NAME |
string | Нет | intersections |
measureName, которое будет использовано в объекте, лежащем в поле additionalData при создании ссылки в data-model. |
APP_MEASURE_THRESHOLD |
float | Нет | 0.5 |
Пороговое значение measure. Ссылки создаются только между документами, мера схожести между которыми больше или равна этому значению. |
APP_LAMP_ROUTE |
string | Нет | plagiarism_search_route |
Рут Lamp, к которому обращается плагин с запросом поиска пересекающихся файлов. |
APP_CREATE_LINKS_PER_MESSAGE |
int | Нет | 100 |
Размер батча для запроса к data-model c командой createObjectsLinks. |
PLUGIN_INFO_READABLE_NAME |
string | Нет | Плагин для построения ссылок на основе содержательных пересечений |
Значение в поле name у тех. константы плагина. |
PLUGIN_INFO_DESCRIPTION |
string | Нет | Проходит по всем объектам и строит ссылки между ними на основе содержательных пересечений их файлов |
Значение в поле description у тех. константы плагина. |
PLUGIN_INFO_VERSION |
int | Нет | 1 |
Значение в поле serviceVersion у тех. константы плагина. |
APP_INDEXATION_CHUNK_SIZE |
int | Нет | 100 |
Значения, поступающие в топик CONSUMER_TOPIC, обрабатываются батчами. Батч поступает в обработку либо если из топика было получено количество сообщений равное максимальному размеру батча, либо если от получения первого элемента батча прошло время равное максимальной разнице получения элементов в батче. Эта переменная устанавливает максимальный размер батча. |
APP_INDEXATION_WITHIN |
duration string | Нет | 1 minutes |
Значения, поступающие в топик CONSUMER_TOPIC, обрабатываются батчами. Батч поступает в обработку либо если из топика было получено количество сообщений равное максимальному размеру батча, либо если от получения первого элемента батча прошло время равное максимальной разнице получения элементов в батче. Эта переменная устанавливает максимальную разницу времени получения элементов в батче. |
APP_MAX_RETRY |
int | Нет | 2 |
Максимальное количество ретраев, которое произойдет при обращении к LAMP, если он возвращает ошибку. |
CONSUMER_PROGRESS_TOPIC |
string | Нет | progress |
Топик, в который плагин пишет об окончании обработки. |
PRODUCER_INDEXATION_EVENT_TOPIC |
string | Нет | entityObjectEvent |
Топик, в который плагин отправляет запрос на переиндексацию backlinks. |
VERDI_HOST |
string | Нет | localhost |
Адрес, который будет зарегистрирован за данным экземпляром сервиса. |
VERDI_TTL |
duration string | Нет | 30 seconds |
Время, в течение которого экземпляр сервиса считается "активным". Таймер обновляется каждый раз, когда сервис присылает "health check". |
VERDI_HEALTH_CHECK |
duration string | Нет | 10 seconds |
Периодичность отправки "health check". |
VERDI_CONSUL |
string | Нет | http://localhost:8500 |
Адрес Consul. |
VERDI_CONSUL_AUTH_USER |
string | Нет | Название учетной записи Сonsul. Если название не указано, то настройки авторизации не будут применены. | |
VERDI_CONSUL_AUTH_PASSWORD |
string | Нет | Пароль учетной записи Сonsul. | |
VERDI_KAFKA_ADDRESS |
string | Нет | localhost:9092 |
Адрес Kafka. |
VERDI_KAFKA_TOPIC |
string | Нет | commandevents |
Название топика для отправки сообщений со статусом команд. |
VERDI_KAFKA_PRODUCER_PROPS |
string | Нет | max.request.size=1048576 |
Дополнительные параметры для Kafka producer. Заполняются по шаблону "key1=value1;key2=value2". |
VERDI_KAFKA_AUTH_USER |
string | Нет | Название учетной записи Kafka. Если название не указано, то настройки авторизации не будут применены. | |
VERDI_KAFKA_AUTH_PASSWORD |
string | Нет | Пароль учетной записи Kafka. | |
VERDI_KAFKA_AUTH_PRINCIPAL |
string | Нет | Principal учетной записи Kafka в Kerberos (в случае соединения с kafka через Kerberos). | |
VERDI_KAFKA_AUTH_KEYTAB_PATH |
string | Нет | Путь до keytab-файла (в случае соединения с kafka через Kerberos). | |
VERDI_KAFKA_AUTH_TRUSTSTORE_LOCATION |
string | Нет | Путь до хранилища сертификатов (Java key store). Если путь не указан, то сертификат применяться не будет. | |
VERDI_KAFKA_AUTH_TRUSTSTORE_PASSWORD |
string | Нет | Пароль к хранилищу сертификатов. | |
VERDI_KAFKA_AUTH_MODE |
string | Нет | static |
Режим аутентификации: static - одна учетная запись на все запросы, mapping - учетная запись зависит от запроса. |
VERDI_KAFKA_AUTH_CONFIG |
string | Нет | Настройки для аутентификации: если AuthMode = mapping, то необходим JSON с List[KafkaAuthConfig]. Переменная соответствует полю authConfig из KafkaAuthSettings. | |
VERDI_KAFKA_AUTH_CACHE_SIZE |
int | Нет | Максимальный размер кэша для Kafka producer (количество активных соединений). | |
VERDI_KAFKA_AUTH_CACHE_TTL |
duration string | нет | Время жизни Kafka producer в кэше. | |
VERDI_ALLOW_INTERNAL_COMMANDS |
boolean | Нет | true |
Можно ли сервису отправлять внутрисистемные команды. |
VERDI_CONSIDER_ALL_COMMANDS_AS_INTERNAL |
boolean | Нет | false |
Флаг, определяющий будут ли все обращения в другие сервисы являться внутренними (т.е. не требовать авторизацию). Детальное описание механизма: Внутренние команды. |
VERDI_COMMAND_STORAGE_UPDATE_PERIOD |
duration string | Нет | 1 minutes |
Время кэширования данных по командам из CommandDiscovery. |
VERDI_SERVICE_DISCOVERY_UPDATE_PERIOD |
duration string | Нет | 30 seconds |
Время кэширования данных по сервисам из ServiceDiscovery. |
VERDI_CONSUL_CONNECTION_MAX_RETRY |
int | Нет | 5 |
Максимальное количество попыток подключения к Consul после обрыва соединения. |
VERDI_CONSUL_CONNECTION_RETRY_DELAY |
duration string | Нет | 1 seconds |
Задержка перед попыткой подключения к Consul. |
VERDI_KAFKA_SYNC_POLL_PERIOD |
duration string | Нет | 1 seconds |
Периодичность запроса статуса команды, отправленной через Kafka. |
VERDI_KAFKA_SYNC_POLL_TIMEOUT |
duration string | Нет | 1 minute |
Время ожидания завершения команды, отправленной через Kafka. |
VERDI_COMMANDS_HTTP_RETRY_ATTEMPTS |
int | Нет | 5 |
Поле attempts из RetrySettings. |
VERDI_COMMANDS_HTTP_RETRY_DELAY |
duration string | Нет | 5 seconds |
Поле delay из RetrySettings. |
VERDI_COMMANDS_HTTP_RETRY_KIND |
string | Нет | OnSomeExceptions(ConnectException) |
CommandResultRetryConditionKind. |
Команды сервиса PlagiarismPlugin
Сервис PlagiarismPlugin не содержит в себе никакие команды. Вместо этого он обрабатывает kafka-сообщения, поступающие из сервиса индексации.
Для обработки сообщений PlagiarismPlugin использует реализации BaseFlow, предоставляемые IntelligentPluginCore.
Два файла с идентификаторами id1 и id2 в PlagiarismPlugin считаются пересекающимися, если:
- при запросе c id1 к Lamp в ответ поступило сообщение message с типом PlagiarismMessage
- id2 содержится в message.foundIds
- id2 соответствует lampMeasure из message.originalities
- при этом (1 - min(1, lampMeasure)) >= APP_MEASURE_THRESHOLD.
Sagas: библиотека для описания cаг
Сага/Saga представляет собой цепочку переходов между состояниями (шагов)..
Каждый переход имеет две операции: переход к следующему состоянию (переход впепед) или откат изменений вызваных переходом (переход назад).
Под операцией перехода понимается любая операция, которая соответстует List[A] => A. Где, A это базовый класс для всех результатов операций.
Результаты выполненых операций складываются в один список, таким образом List[A] представляет собой состояние Саги, которое содержит результаты выполненых переходов.
Для описания состояния Саги используется класс SagaState. Для описания переходов есть несколько интерфесов, но все они расширяют базовый Transition. Для описания Саги, как списка переходов используется SagaDefinition.
Описание Саги в коде
Базовый тип для результатов выполнения переходов Саги
sealed trait StagesForSagaName
Результаты переходов
object StagesForSagaName {
// init or empty stage
case class FirstStage(args: SagaArgumentClass) extends StagesForSagaName
case class SecondStage(firstStageRes: Option[FirstOperationResult]) extends StagesForSagaName
case class ThirdStage() extends StagesForSagaName
case class FourthStage(thirdStageRes: ThirdOperationResult) extends StagesForSagaName
}
Реализация переходов
case class FirstWithoutCommandsOp_SagaName(dispatcher: Dispatcher,
sagaLogger: Logger)
(implicit ec: ExecutionContext)
extends SyncSagaStageTransition[Future, StagesForSagaName] {
override protected type OperationContext = Unit
override protected def transitionImpl(previousStages: List[StagesForSagaName], context: Unit): Future[StagesForSagaName] = {
sagaLogger.info("Execute FirstOperation in SagaName")
val operationArguments = convertToForwardArgs(previousStages)
val opResult = FirstOperationResult(operationArguments.toList.mkString(" => "))
val resultStage = StagesForSagaName.SecondStage(Some(opResult))
Future.successful(resultStage)
}
override protected def rollbackImpl(previousStages: List[StagesForSagaName], context: Unit): Future[Unit] = {
sagaLogger.info("Execute compensation for FirstOperation in SagaName: Nothing to do")
Future.successful(())
}
override protected def transitionResultByOperationId(operationIdentifier: Option[OperationId]): Future[Option[Future[StagesForSagaName]]] = Future.successful(None)
override protected def rollbackResultByOperationId(operationIdentifier: Option[OperationId]): Future[Option[Future[Unit]]] = Future.successful(None)
override protected def generateOperationContext(isRollback: Boolean, previousStages: List[StagesForSagaName]): Future[Unit] = Future.successful(())
override protected def extractOperationId(context: Unit): Option[OperationId] = None
private def convertToForwardArgs(s: List[StagesForSagaName]): SagaArgumentClass = ???
}
case class SecondSyncOp_SagaName(durationTracingEnable: Boolean,
dispatcher: Dispatcher,
sagaLogger: Logger)
(implicit ec: ExecutionContext)
extends SyncSagaStageTransition[Future, StagesForSagaName]
with CommandSendingSupport
with OperationIdAsCommandIdHelper {
override protected def transitionImpl(previousStages: List[StagesForSagaName], context: RequestContext): Future[StagesForSagaName] = {
sagaLogger.info("Execute SecondOperation")
val commandArgs = convertToForwardArgs(previousStages)
dispatcher.sendCommandSync(CommandsForSagaName.CommandToCallOn_SecondStage, commandArgs)(context)
.flatMap {
case Right(commandResult) =>
commandResult.value.flatMap(_.as[SecondOperationResult].toOption) match {
case Some(secondStageRes) if secondStageRes.someInnerResult > 100 =>
val resultStage = StagesForSagaName.ThirdStage()
Future.successful(resultStage)
case _ =>
// rollback
Future.failed(new RuntimeException("Second operation in SagaName ended unexpectedly"))
}
case Left(_) =>
Future.failed(new RuntimeException("Failed to send command for Second operation in SagaName"))
}
}
override protected def rollbackImpl(previousStages: List[StagesForSagaName], context: RequestContext): Future[Unit] = {
sagaLogger.info("Execute compensation for SecondOperation")
val compensationArgs = convertToRollbackArgs(previousStages)
dispatcher.sendCommandSync(CommandsForSagaName.CommandToCallOn_SecondStage_Compensation, compensationArgs)(context)
.flatMap {
case Right(result) => // ignore compensation result
val resultStage = StagesForSagaName.SecondStage(None)
Future.successful(resultStage)
case Left(_) =>
Future.failed(new RuntimeException("Failed to sent command"))
}
}
override protected def transitionResultByOperationId(operationIdentifier: Option[OperationId]): Future[Option[Future[StagesForSagaName]]] = {
sagaLogger.info(s"SecondOperation result have be restored from operationIdentifier '$operationIdentifier'")
commandResultByOperationId[SecondOperationResult](operationIdentifier).map { resultOpt =>
resultOpt.map(_ => Future.successful(StagesForSagaName.ThirdStage()))
}
}
override protected def rollbackResultByOperationId(operationIdentifier: Option[OperationId]): Future[Option[Future[Unit]]] = {
sagaLogger.info("SecondOperation compensation result have be restored from operationIdentifier '$operationIdentifier'")
commandResultByOperationId[Json](operationIdentifier).map { resultOpt =>
resultOpt.map(_ => Future.successful(Some()))
}
}
override protected def generateOperationContext(isRollback: Boolean, previousStages: List[StagesForSagaName]): Future[RequestContext] = {
val cr = if (!isRollback)
makeRequestContext("Second operation in SagaName")
else
makeRequestContext("Compensation for Second operation in SagaName")
Future.successful(cr)
}
private def convertToForwardArgs(s: List[StagesForSagaName]): Json = ???
private def convertToRollbackArgs(s: List[StagesForSagaName]): Json = ???
}
case class ThirdAsyncOp_SagaName(durationTracingEnable: Boolean,
dispatcher: Dispatcher,
sagaLogger: Logger)
(implicit ec: ExecutionContext)
extends AsyncSagaStageTransition[Future, StagesForSagaName]
with FutureRollbackCallbackDefaultImpl {
override protected type OperationContext = RequestContext
override protected implicit val applicativeInstance: Applicative[Future] = cats.implicits.catsStdInstancesForFuture(ec)
override protected def transitionImpl(previousStages: List[StagesForSagaName], context: RequestContext): Future[OperationCallback[Future, StagesForSagaName]] = {
sagaLogger.info("Execute ThirdOperation")
implicit val cr: RequestContext = makeRequestContext("???")
val commandArgs = convertToForwardArgs(previousStages)
dispatcher.sendCommandAsync(CommandsForSagaName.CommandToCallOn_ThirdStage, commandArgs)
.flatMap {
case Right(commandId) =>
val cb = getTransitionCallback(commandId)
Future.successful(cb)
case Left(_) =>
Future.failed(new RuntimeException("Failed to sent command"))
}
}
override protected def rollbackImpl(previousStages: List[StagesForSagaName], context: RequestContext): Future[OperationCallback[Future, Unit]] = {
sagaLogger.info("Execute compensation for ThirdOperation")
implicit val cr: RequestContext = makeRequestContext("???")
val compensationArgs = convertToRollbackArgs(previousStages)
dispatcher.sendCommandAsync(CommandsForSagaName.CommandToCallOn_ThirdStage_Compensation, compensationArgs)
.flatMap {
case Right(commandId) =>
val cb = getRollbackCallback(commandId)
Future.successful(cb)
case Left(_) =>
Future.failed(new RuntimeException("Failed to sent command"))
}
}
override def getTransitionCallback(commandId: CommandId): OperationCallback[Future, StagesForSagaName] = new ThirdOpTransitCallback(commandId)
override protected def generateOperationContext(isRollback: Boolean, previousStages: List[StagesForSagaName]): Future[RequestContext] = {
val cr = if (!isRollback)
makeRequestContext("Third operation in SagaName")
else
makeRequestContext("Compensation for third operation in SagaName")
Future.successful(cr)
}
override protected def extractOperationId(context: RequestContext): Option[OperationId] =
Some(OperationId.fromCommandId(context.commandId))
private def convertToForwardArgs(s: List[StagesForSagaName]): Json = ???
private def convertToRollbackArgs(s: List[StagesForSagaName]): Json = ???
}
final class ThirdOpTransitCallback(val commandId: CommandId)
extends OperationCallback[Future, StagesForSagaName] {
override def callback(commandAggregatedStatus: CommandAggregatedStatus): Future[StagesForSagaName.FourthStage] = {
commandAggregatedStatus.value.flatMap(_.as[ThirdOperationResult].toOption) match {
case Some(thirdStageRes) =>
val stageResult = StagesForSagaName.FourthStage(thirdStageRes)
Future.successful(stageResult)
case None =>
Future.failed(new RuntimeException("Third operation in SagaName ended unexpectedly"))
}
}
}
case class SagaNameDefinition(sagaStageService: SagaStatePersistService[Future, StagesForSagaName],
firstOp: FirstWithoutCommandsOp_SagaName,
secondOp: SecondSyncOp_SagaName,
thirdOp: ThirdAsyncOp_SagaName)
extends SagaDefinition[Future, SagaArgumentClass, StagesForSagaName] {
override val steps: StageList[Future, StagesForSagaName] =
StepsList(
firstOp,
secondOp,
thirdOp
)
override protected def initStage(arguments: SagaArgumentClass): StagesForSagaName =
StagesForSagaName.FirstStage(arguments)
override def sendSagaEvent(message: SagaEventMessage): Future[Boolean] =
// Например, отправка в Kafka topic
Future.successful(true)
override def wholeSagaResult(sagaId: SagaId, sagaState: SagaState[TestStage]): Future[Option[Json]] =
// Создание результата всей саги на основе состояния саги после завершения
Future.successful(None)
}
Чтобы описать Сагу как цепочку переходов нужно:
- Создать базовый тип (очень желательно
sealed trait), к которому можно будет привести все результаты переходов (для полученияList[A]) - Добавить 1+ классов для результатов переходов, которые будут расширять базовый тип
- Добавить переходы, расширяя
SyncSagaStageTransitionилиAsyncSagaStageTransitiontrait-ы. Расширяя данные trait-ы, необходимо описать две операцииtransitionиrollback. - Создать реализацию
SagaDefinition, которая будет содержатьStageListописывающий список переходов.
Используемые структуры
SagaDefinition
Описание саги в виде списка шагов/переходов. Это описание запускается с помощью SagaRunner
SagaRunner
Раннер саг, который контролирует выполнение саги на основе ее описания.
SagaState
Состояние саги, которое включает общий статус саги, результаты выполненных шагов и идентификатор операции предыдущей попытки выполнить шаг.
Идентификатор в поле relatedOperationId относится к идентификатору в поле index.
StepsList
Список шагов/переходов Саги, который позволяет получить следующий шаг на основе состояния Саги. Для этого у каждого элемента в списке есть свой идентификатор.
StepsListElement
Обертка над SagaTransition, которая выбирает нужный метод для вызова.
SagaTransition
Описывает шаг Саги. Переход между двумя состояниями/стадиями. Каждый переход имеет две операции: прямой переход и откат.
Условия "успеха или не успеха", необходимость повторных попыток и сложности параллельного выполнения/отката операций (в разных Сагах) не лежат в зоне отвественности Саги. Т.е. все аспекты выполнения операции должны быть описаны при реализации трейта.
SyncSagaTransition
Описывает синхронный переход между состояниями саги.
AsyncSagaTransition
Описывает асинхронный переход между состояниями саги.
В данной реализации, результат операции - OperationCallback, который завязан на команды Verdi.
OperationCallback
Callback, который будет вызван при завершении команды с заданным CommandId.
SagaManager
Менеджер callback-ов саг, который вызывает необходимый callback при завершении команды или удаляет его если время ожидания превышено.
SagaStatus
Статус Саги.
| Значение | Описание |
|---|---|
| Initiated | Сага была иницирована, т.е. был присвоен Идентификатор и созданно состояние |
| Running | Сага запущенна, т.е. первая операция уже была запущенна и Сага в процессе прямого выполнения |
| Rollback | Сага откатывается, т.е. был начат процесс отката |
| Success | Сага успешно завершенна, т.е. Сага была запущенна и прямое выполнение завершилось без вызова отката. |
| Failure | Сага неудачно завершенна, т.е. был вызван процесс отката и Сага завершила откат. |
SagaEvent
Тип события саги.
| Значение | Описание |
|---|---|
| Initiated | Сага иницирована, т.е. ей присвоен SagaId и первоначальное состояние. |
| Started | Начался процесс прямого выполнения саги |
| RollbackStarted | Начался процесс отката саги |
| FinishedSuccess | Вся сага завершена успешно |
| FinishedFailure | Вся сага завершена. Т.к. был процесс отката, то завершение считается неуспешным. |
| StepStarted | Началось выполнение шага саги |
| StepCompleted | Шаг саги завершен успешно |
| StepFailed | Шаг саги завершен неуспешно/с ошибкой |
SagaEventMessage
Сообщение описывающее событие саги
SagaStateService
Интерфейс для получения состояния саги из хранилища. Хранилище может быть любое: in-memory, Redis, PostgreSQL и т.п.
SagaStatePersistService
Интерфейс для записи состояния саги в хранилище. Хранилище может быть любое: in-memory, Redis, PostgreSQL и т.п.
Пример описания Саги
Полный пример описания Саги
package com.embedika.verdi.sagas.example
import cats.Applicative
import com.embedika.verdi.models.RequestContext
import com.embedika.verdi.models.command.{CommandAggregatedStatus, CommandId, CommandName, CommandStatus}
import com.embedika.verdi.sagas._
import com.embedika.verdi.senderlib.Dispatcher
import io.circe.{Decoder, Json}
import io.circe.generic.semiauto.deriveDecoder
import org.slf4j.Logger
import scala.concurrent.{ExecutionContext, Future}
import scala.util.Success
//
// stages description
//
case class SagaArgumentClass() {
def toList: List[String] = ???
}
object SagaArgumentClass {
implicit val jsonDecoder: Decoder[SagaArgumentClass] = deriveDecoder
}
case class FirstOperationResult(data: String)
object FirstOperationResult {
implicit val jsonDecoder: Decoder[FirstOperationResult] = deriveDecoder
}
case class SecondOperationResult(someInnerResult: Int)
object SecondOperationResult {
implicit val jsonDecoder: Decoder[SecondOperationResult] = deriveDecoder
}
case class ThirdOperationResult(data: Json, nedata: Json)
object ThirdOperationResult {
implicit val jsonDecoder: Decoder[ThirdOperationResult] = deriveDecoder
}
sealed trait StagesForSagaName
object StagesForSagaName {
// init or empty state
case class FirstStage(args: SagaArgumentClass) extends StagesForSagaName
case class SecondStage(firstStageRes: Option[FirstOperationResult]) extends StagesForSagaName
case class ThirdStage() extends StagesForSagaName
case class FourthStage(thirdStageRes: ThirdOperationResult) extends StagesForSagaName
}
object CommandsForSagaName {
val CommandToCallOn_SecondStage = CommandName("second_stage_command")
val CommandToCallOn_ThirdStage = CommandName("third_stage_command")
val CommandToCallOn_FourthStage = CommandName("fourth_stage_command")
val CommandToCallOn_SecondStage_Compensation = CommandName("second_stage_command_Compensation")
val CommandToCallOn_ThirdStage_Compensation = CommandName("third_stage_command_Compensation")
val CommandToCallOn_FourthStage_Compensation = CommandName("fourth_stage_command_Compensation")
}
//
// stages implementation
//
case class SagaNameDefinition(sagaStageService: SagaStatePersistService[Future, StagesForSagaName],
firstOp: FirstWithoutCommandsOp_SagaName,
secondOp: SecondSyncOp_SagaName,
thirdOp: ThirdAsyncOp_SagaName)
extends SagaDefinition[Future, SagaArgumentClass, StagesForSagaName] {
override val steps: StepsList[Future, StagesForSagaName] =
StepsList(
firstOp,
secondOp,
thirdOp
)
override protected def initStage(arguments: SagaArgumentClass): StagesForSagaName =
StagesForSagaName.FirstStage(arguments)
override def sendSagaEvent(message: SagaEventMessage): Future[Boolean] = Future.successful(true)
override def wholeSagaResult(sagaId: SagaId, sagaState: SagaState[TestStage]): Future[Option[Json]] =
Future.successful(None)
}
case class FirstWithoutCommandsOp_SagaName(dispatcher: Dispatcher,
sagaLogger: Logger)
(implicit ec: ExecutionContext)
extends SyncSagaTransition[Future, StagesForSagaName] {
override protected type OperationContext = Unit
override protected def transitionImpl(previousStages: List[StagesForSagaName], context: Unit): Future[StagesForSagaName] = {
sagaLogger.info("Execute FirstOperation in SagaName")
val operationArguments = convertToForwardArgs(previousStages)
val opResult = FirstOperationResult(operationArguments.toList.mkString(" => "))
val resultStage = StagesForSagaName.SecondStage(Some(opResult))
Future.successful(resultStage)
}
override protected def rollbackImpl(previousStages: List[StagesForSagaName], context: Unit): Future[Unit] = {
sagaLogger.info("Execute compensation for FirstOperation in SagaName: Nothing to do")
Future.successful(())
}
override protected def transitionResultByOperationId(operationIdentifier: Option[OperationId]): Future[Option[Future[StagesForSagaName]]] = Future.successful(None)
override protected def rollbackResultByOperationId(operationIdentifier: Option[OperationId]): Future[Option[Future[Unit]]] = Future.successful(None)
override protected def generateOperationContext(isRollback: Boolean, previousStages: List[StagesForSagaName]): Future[Unit] = Future.successful(())
override protected def extractOperationId(context: Unit): Option[OperationId] = None
private def convertToForwardArgs(s: List[StagesForSagaName]): SagaArgumentClass = ???
}
case class SecondSyncOp_SagaName(durationTracingEnable: Boolean,
dispatcher: Dispatcher,
sagaLogger: Logger)
(implicit ec: ExecutionContext)
extends SyncSagaTransition[Future, StagesForSagaName]
with CommandSendingSupport
with OperationIdAsCommandIdHelper {
override protected def transitionImpl(previousStages: List[StagesForSagaName], context: RequestContext): Future[StagesForSagaName] = {
sagaLogger.info("Execute SecondOperation")
val commandArgs = convertToForwardArgs(previousStages)
dispatcher.sendCommandSync(CommandsForSagaName.CommandToCallOn_SecondStage, commandArgs)(context)
.flatMap {
case Right(commandResult) =>
commandResult.value.flatMap(_.as[SecondOperationResult].toOption) match {
case Some(secondStageRes) if secondStageRes.someInnerResult > 100 =>
val resultStage = StagesForSagaName.ThirdStage()
Future.successful(resultStage)
case _ =>
// rollback
Future.failed(new RuntimeException("Second operation in SagaName ended unexpectedly"))
}
case Left(_) =>
Future.failed(new RuntimeException("Failed to send command for Second operation in SagaName"))
}
}
override protected def rollbackImpl(previousStages: List[StagesForSagaName], context: RequestContext): Future[Unit] = {
sagaLogger.info("Execute compensation for SecondOperation")
val compensationArgs = convertToRollbackArgs(previousStages)
dispatcher.sendCommandSync(CommandsForSagaName.CommandToCallOn_SecondStage_Compensation, compensationArgs)(context)
.flatMap {
case Right(result) => // ignore compensation result
val resultStage = StagesForSagaName.SecondStage(None)
Future.successful(resultStage)
case Left(_) =>
Future.failed(new RuntimeException("Failed to sent command"))
}
}
override protected def transitionResultByOperationId(operationIdentifier: Option[OperationId]): Future[Option[Future[StagesForSagaName]]] = {
sagaLogger.info(s"SecondOperation result have be restored from operationIdentifier '$operationIdentifier'")
commandResultByOperationId[SecondOperationResult](operationIdentifier).map { resultOpt =>
resultOpt.map(_ => Future.successful(StagesForSagaName.ThirdStage()))
}
}
override protected def rollbackResultByOperationId(operationIdentifier: Option[OperationId]): Future[Option[Future[Unit]]] = {
sagaLogger.info("SecondOperation compensation result have be restored from operationIdentifier '$operationIdentifier'")
commandResultByOperationId[Json](operationIdentifier).map { resultOpt =>
resultOpt.map(_ => Future.successful(Some()))
}
}
override protected def generateOperationContext(isRollback: Boolean, previousStages: List[StagesForSagaName]): Future[RequestContext] = {
val cr = if (!isRollback)
makeRequestContext("Second operation in SagaName")
else
makeRequestContext("Compensation for Second operation in SagaName")
Future.successful(cr)
}
private def convertToForwardArgs(s: List[StagesForSagaName]): Json = ???
private def convertToRollbackArgs(s: List[StagesForSagaName]): Json = ???
}
case class ThirdAsyncOp_SagaName(durationTracingEnable: Boolean,
dispatcher: Dispatcher,
sagaLogger: Logger)
(implicit ec: ExecutionContext)
extends AsyncSagaTransition[Future, StagesForSagaName]
with FutureRollbackCallbackDefaultImpl {
override protected type OperationContext = RequestContext
override protected implicit val applicativeInstance: Applicative[Future] = cats.implicits.catsStdInstancesForFuture(ec)
override protected def transitionImpl(previousStages: List[StagesForSagaName], context: RequestContext): Future[OperationCallback[Future, StagesForSagaName]] = {
sagaLogger.info("Execute ThirdOperation")
implicit val cr: RequestContext = makeRequestContext("???")
val commandArgs = convertToForwardArgs(previousStages)
dispatcher.sendCommandAsync(CommandsForSagaName.CommandToCallOn_ThirdStage, commandArgs)
.flatMap {
case Right(commandId) =>
val cb = getTransitionCallback(commandId)
Future.successful(cb)
case Left(_) =>
Future.failed(new RuntimeException("Failed to sent command"))
}
}
override protected def rollbackImpl(previousStages: List[StagesForSagaName], context: RequestContext): Future[OperationCallback[Future, Unit]] = {
sagaLogger.info("Execute compensation for ThirdOperation")
implicit val cr: RequestContext = makeRequestContext("???")
val compensationArgs = convertToRollbackArgs(previousStages)
dispatcher.sendCommandAsync(CommandsForSagaName.CommandToCallOn_ThirdStage_Compensation, compensationArgs)
.flatMap {
case Right(commandId) =>
val cb = getRollbackCallback(commandId)
Future.successful(cb)
case Left(_) =>
Future.failed(new RuntimeException("Failed to sent command"))
}
}
override def getTransitionCallback(commandId: CommandId): OperationCallback[Future, StagesForSagaName] = new ThirdOpTransitCallback(commandId)
override protected def generateOperationContext(isRollback: Boolean, previousStages: List[StagesForSagaName]): Future[RequestContext] = {
val cr = if (!isRollback)
makeRequestContext("Third operation in SagaName")
else
makeRequestContext("Compensation for third operation in SagaName")
Future.successful(cr)
}
override protected def extractOperationId(context: RequestContext): Option[OperationId] =
Some(OperationId.fromCommandId(context.commandId))
private def convertToForwardArgs(s: List[StagesForSagaName]): Json = ???
private def convertToRollbackArgs(s: List[StagesForSagaName]): Json = ???
}
final class ThirdOpTransitCallback(val commandId: CommandId)
extends OperationCallback[Future, StagesForSagaName] {
override def callback(commandAggregatedStatus: CommandAggregatedStatus): Future[StagesForSagaName.FourthStage] = {
commandAggregatedStatus.value.flatMap(_.as[ThirdOperationResult].toOption) match {
case Some(thirdStageRes) =>
val stageResult = StagesForSagaName.FourthStage(thirdStageRes)
Future.successful(stageResult)
case None =>
// rollback
Future.failed(new RuntimeException("Third operation in SagaName ended unexpectedly"))
}
}
}
Преобразование поисковой строки в DSL поиска
Поисковая строка может содержать ключи фильтров, скобки, операторы || и && Для поисковой строки должен существовать контекст - словарь ключей фильтров и значений для фильтрации
Пример реализации и использования QueryEvaluator
Пример поисковый строки
val query = "date && (eventType || user)"
Пример контекста
val context = Map("date" -> "1188583200000_", "type" -> "type1,type2", "user"->"user1")
Цель получить например sql
... eventDate >= 1188583200000 AND (eventType IN ('type1', 'type2') AND userId = 'user1')
В качестве DSL поиска будем использовать Fragment из doobie.util.fragment.Fragment Нам нужно определить type class для Fragment, который должен уметь создавать нейтральный элемент (в sql например это будет TRUE, т.к. TRUE может быть скомбинирован с любыми другими выражениями, не изменяя результат этих выражения, и выражение только с WHERE TRUE будет корректным sql) и реализовывать конъюнкцию и дизъюнкцию (AND и OR)
import com.embedika.verdi.search.MultiMonoid
import doobie.util.fragment.Fragment
import doobie.util.fragments.{ whereAnd, whereOr }
implicit val doobieAlg: MultiMonoid[Fragment] = new MultiMonoid[Fragment] {
override def multiply(x: Fragment, y: Fragment): Fragment = whereAnd(x, y)
override def empty: Fragment = Fragment.empty
override def combine(x: Fragment, y: Fragment): Fragment = whereOr(x, y)
}
Пример реализации фильтров
import doobie.Fragments
import doobie.implicits._
import cats.data.{ Kleisli, NonEmptyList }
import com.embedika.verdi.persistence.filters.{ RangeQuery, FilterQueryContext, InSetQuery }
val filters: Map[String, Kleisli[Option, FilterQueryContext, Fragment]] = Map(
"date" -> Kleisli {
case InSetQuery(values) => NonEmptyList.fromList(values).map(nonEmptyValues => Fragments.in(fr""""MyTable".date""", nonEmptyValues))
case RangeQuery(Some(from), Some(to)) => Some(fr""""MyTable".date >= $from and "MyTable".date <= $to""")
case RangeQuery(Some(from), None) => Some(fr""""MyTable".date >= $from""")
case RangeQuery(None, Some(to)) => Some(fr""""MyTable".date <= $to""")
case _ => None
},
"type" -> Kleisli {
case InSetQuery(values) => NonEmptyList.fromList(values).map(nonEmptyValues => Fragments.in(fr""""MyTable".type""", nonEmptyValues))
case _ => None
},
"user" -> Kleisli {
case InSetQuery(values) if values.length == 1 => Some(fr""""MyTable".user = ${values.head}""")
case _ => None
}
)
В фильтрах должны описываться алгоритмы преобразования "1188583200000_" в "eventDate >= 1188583200000", "type1,type2" в "eventType IN ('type1', 'type2')" и т.д. В конце получаем финальный Fragment
import com.embedika.verdi.search.QueryEvaluator
def searchSomething(search: Search) = {
val parsedContexts: Map[String, FilterQueryContext] = parseSearchContext(search.context)
val evaluator = FiltersQueryEvaluator.create[FilterQueryContext, Fragment](parsedSearchContext, filters)
val searchQuery = evaluator.evaluate(request.query)
}
private def parseSearchContext(context: Map[String, Json]): Map[String, FilterQueryContext] =
context.flatMap { case (fieldName, queryContext) =>
FilterQueryContext
.decode(queryContext)
.map { parsedContext =>
fieldName.trim -> parsedContext
}
}
Senderlib: библиотека для работы с командами
Библиотека предоставляет API для отправки команд, получения их статуса, регистрации команд и регистрации сервиса обрабатывающего команды.
API библиотеки можно разделить на 3 секции:
- Регистрация сервисов: ServiceDiscovery
- Регистрация команд: CommandDiscovery
- Отправка команд: Dispatcher
Используемые структуры поделены на отдельные пакеты по сущностям.
Структуры models.command
- CommandId
- CommandName
- CommandAggregatedStatus
- CommandAggregatedStatusJson
- CommandEvent
- CommandInfo
- CommandStatus
Структуры models.dispatch
Структуры models.service
Общие структуры
Структуры для настройки Kafka
ServiceDiscovery
Предоставляет API реестра сервисов, который хранит реальные адреса сервисов
Методы
RegisterServiceInstance
Регистрирует инстанс сервиса в реестре сервисов с указанными параметрами
Регистрация экземпляра сервиса
import com.embedika.verdi.models._
import com.embedika.verdi.models.service._
import com.embedika.verdi.senderlib.ServiceDiscovery
import scala.concurrent.ExecutionContext
import scala.concurrent.Future
import scala.concurrent.duration._
import scala.util.{Failure, Success}
def registration(serviceRegistry: ServiceDiscovery,
ec: ExecutionContext): Future[(ServiceId, AsyncStoppable)] = {
val serviceId = ServiceId("someid")
val serviceName = ServiceName("somename")
val healthCheckingAtConsulPeriod = 2.minutes
val healthCheckPassingToConsulPeriod = 1.minutes
val serviceInfo = DiscoverableService(
id = serviceId,
name = serviceName,
host = "localhost",
port = 8080,
version = "v1",
ttl = healthCheckingAtConsulPeriod
)
serviceRegistry.registerServiceInstance(serviceInfo)
.transform {
case Success(registerSuccess) if registerSuccess =>
val cancellation = serviceRegistry.startServiceHealthChecking(serviceId, healthCheckPassingToConsulPeriod)
Success((serviceId, cancellation))
case Success(_) =>
Failure(new Exception(s"Service instance registration failed:\n$serviceInfo"))
case Failure(ex) =>
Failure(ex)
}(ec)
}
DeregisterServiceInstance
Удаляет определенный эксземпляр сервиса из реестра сервисов, чтобы его нельзя было найти
Удаление зарегистрированного экземпляра сервиса
import com.embedika.verdi.models._
import com.embedika.verdi.models.service._
import com.embedika.verdi.senderlib.ServiceDiscovery
import scala.concurrent.ExecutionContext
import scala.concurrent.Future
val ec: ExecutionContext = ???
val serviceRegistry: ServiceDiscovery = ???
def registration(): Future[(ServiceId, AsyncStoppable)] = ???
registration().map { case (serviceId, healthCheckPassing) =>
/* wait for the instance to stop working and become needless */
healthCheckPassing.stop()
serviceRegistry.deregisterServiceInstance(serviceId)
}(ec)
StartServiceHealthChecking
Стартует процесс отправки состояния текущего экземпляра в реестр сервисов. Для отправки состояния создается задача, которая будет периодически запускаться. Результатом задачи является обновление статуса сервиса, чтобы сервис считался "активным" в реестре. Задача будет выполнятся в 0, T, 2T, 3T.
Регистрация экземпляра сервиса
import com.embedika.verdi.models.service._
import com.embedika.verdi.senderlib.ServiceDiscovery
import scala.concurrent.ExecutionContext
import scala.concurrent.duration._
import scala.util.{Failure, Success}
val ec: ExecutionContext = ???
val serviceRegistry: ServiceDiscovery = ???
val serviceId: ServiceId = ???
val serviceInfo: DiscoverableService = ???
val healthCheckPassingToRegistryPeriod: FiniteDuration = 1.minutes
serviceRegistry
.registerServiceInstance(serviceInfo)
.transform {
case Success(registerSuccess) if registerSuccess =>
val cancellation = serviceRegistry.startServiceHealthChecking(serviceId, healthCheckPassingToRegistryPeriod)
Success((serviceId, cancellation))
case Success(_) =>
Failure(new Exception(s"Service instance registration failed:\n$serviceInfo"))
case Failure(ex) =>
Failure(ex)
}(ec)
IsAlive
Проверяет есть ли живой экземпляр сервиса в реестре сервисов.
CommandDiscovery
Предоставляет API для работы с хранилищем команд.
Методы
CommandInfo
Ищет метаинформацию о команде по имени команды.
Получение информации о команде
import com.embedika.verdi.models.command._
import com.embedika.verdi.senderlib.CommandDiscovery
import scala.concurrent.ExecutionContext
val ec: ExecutionContext = ???
val commandDiscovery: CommandDiscovery = ???
def handleCommandInfo[A](cmdInfo: CommandInfo): A = ???
val commandName = CommandName("somename")
commandDiscovery
.commandInfo(commandName)
.map { infoOpt =>
infoOpt.map(handleCommandInfo)
}(ec)
PublishCommands
Публикует метаинформацию о командах. Метаинформацию об отдельных командах после можно найти по имени команды.
Публикация команд
import com.embedika.verdi.models.command.{CommandInfo, CommandName}
import com.embedika.verdi.models.dispatch._
import com.embedika.verdi.models.service.ServiceName
import com.embedika.verdi.senderlib.CommandDiscovery
import io.circe.syntax._
import scala.concurrent.ExecutionContext
val ec: ExecutionContext = ???
val commandDiscovery: CommandDiscovery = ???
def handleCommandsPublishingResult[A](isPublished: Seq[Boolean]): A = ???
val serviceName = ServiceName("somename")
val dispatchParameters = HttpDispatchParameters(
method = HttpMethod.POST,
route = Some("/someroute")
)
val commandName = CommandName("somename")
val commandMeta = CommandInfo(
commandName = commandName,
dispatchType = DispatchType.Http,
serviceName = serviceName,
parameters = dispatchParameters.asJson,
permissions = Seq.empty,
entityType = "EntityToImpact",
description = Some("Http command that returns result when receives arguments"),
isInternalCommand = true,
withoutEvents = false
)
commandDiscovery
.publishCommands(Seq(commandMeta))
.map(isPublished => handleCommandsPublishingResult(isPublished))(ec)
ListCommandsInfo
Возвращает список всех команд, опубликованных в хранилище команд на данный момент.
Список команд
import com.embedika.verdi.models.command._
import com.embedika.verdi.senderlib.CommandDiscovery
import scala.concurrent.ExecutionContext
val ec: ExecutionContext = ???
val commandDiscovery: CommandDiscovery = ???
def handleCommandInfo[A](cmdInfo: Either[(CommandName, Exception), CommandInfo]): A = ???
commandDiscovery
.listCommandsInfo()
.map { infoList =>
infoList.map(handleCommandInfo)
}(ec)
UnpublishCommand
Удаляет команду по ее имени из хранилища команд.
Dispatcher
Предоставляет API для отправки комманд
Методы
SendCommandSync
Отправляет команду и дожидается завершения ее выполнения. Команда считается завершенной, если ее статус изменился на один из "конечных".
Возвращает CommandId и CommandAggregatedStatusJson отправленной команды. В случае ошибки, возвращает DispatchError.
Синхронное выполнение команды
import com.embedika.verdi.models.debug.TracingContext
import com.embedika.verdi.models._
import com.embedika.verdi.models.command._
import com.embedika.verdi.senderlib.Dispatcher
import scala.concurrent.ExecutionContext
import scala.concurrent.Future
import scala.util.{Failure, Success}
import io.circe.{Decoder, Json}
import io.circe.syntax._
val ec: ExecutionContext = ???
val dispatcher: Dispatcher = ???
val commandArgumentsAsJson: Json = ???
val commandArgumentsAsString = commandArgumentsAsJson.noSpaces
val commandName = CommandName("someAction")
case class CommandResult(res: Int)
object CommandResult {
implicit val decoder: Decoder[CommandResult] = ???
}
val durationTracingEnable: Boolean = ???
val initBuilder = RequestContext.builder()
val reqCtxBuilder = if (durationTracingEnable) {
initBuilder.withTracing("Doing '$commandName' synchronously")
} else {
initBuilder
}
implicit val reqCtx: RequestContext = reqCtxBuilder.build()
def handleCommandResult[A](r: CommandResult): A = ???
dispatcher.sendCommandSync(commandName, commandArgumentsAsString)
.transform {
case Success(Right(commandAggregatedStatus)) =>
val handledResult: Option[_] = for {
commandResultAsJson <- commandAggregatedStatus.value
commandResult <- commandResultAsJson.as[CommandResult].toOption
} yield {
handleCommandResult(commandResult)
}
Success(handledResult)
case _ =>
Success(None)
}(ec)
SendCommandAsync
Отправляет команду без ожидания завершения ее выполнения.
Возвращает CommandId отправленной команды. В случае ошибки, возвращает DispatchError.
Асинхронное выполнение команды
import com.embedika.verdi.models.debug.TracingContext
import com.embedika.verdi.models._
import com.embedika.verdi.models.command._
import com.embedika.verdi.senderlib.Dispatcher
import scala.concurrent.ExecutionContext
import scala.concurrent.Future
import scala.util.{Failure, Success}
import io.circe.{Decoder, Json}
import io.circe.syntax._
val ec: ExecutionContext = ???
val dispatcher: Dispatcher = ???
val commandArgumentsAsJson: Json = ???
val commandArgumentsAsString = commandArgumentsAsJson.noSpaces
val commandName = CommandName("someAction")
case class CommandResult(res: Int)
object CommandResult {
implicit val decoder: Decoder[CommandResult] = ???
}
val durationTracingEnable: Boolean = ???
val initBuilder = RequestContext.builder()
val reqCtxBuilder = if (durationTracingEnable) {
initBuilder.withTracing("Doing '$commandName' asynchronously")
} else {
initBuilder
}
implicit val reqCtx: RequestContext = reqCtxBuilder.build()
dispatcher.sendCommandAsync(commandName, commandArgumentsAsString)
.transform {
case Success(Right(commandId)) =>
Success(Some(commandId))
case _ =>
Success(None)
}(ec)
SendCommandEvent
Отправляет событие CommandEvent о процессе выполнения команды, которое будет учитываться в CommandAggregatedStatus
Возвращает Right(()) при успешной отправке события, иначе Left(errorResponse), где errorResponse - DispatchError, произошедшая в процессе.
Асинхронное выполнение команды
import com.embedika.verdi.models.command._
import com.embedika.verdi.senderlib.Dispatcher
import scala.concurrent.ExecutionContext
import scala.concurrent.Future
import io.circe.Encoder
import io.circe.syntax._
case class CommandResult(res: Int)
object CommandResult {
implicit val encoder: Encoder[CommandResult] = ???
}
trait CommandStateSwitcher {
protected val ec: ExecutionContext = ???
protected val dispatcher: Dispatcher = ???
def completeCommand(commandId: CommandId,
result: CommandResult): Future[Either[ErrorResponse, Unit]] = {
val eventPayload: Option[String] = Some(result.asJson.noSpaces)
dispatcher.sendCommandEvent(commandId = commandId,
newState = CommandStatus.Completed,
payload = eventPayload)
}
}
Status
Возвращает текущий статус CommandAggregatedStatusJson команды по ее CommandId, если он существует.
Получение текущего статуса команды
import com.embedika.verdi.models.debug.TracingContext
import com.embedika.verdi.models.{RequestContext, RequestContextBuilder}
import com.embedika.verdi.models.command._
import com.embedika.verdi.senderlib.Dispatcher
import scala.concurrent.ExecutionContext
import scala.concurrent.Future
import io.circe.Decoder
import io.circe.syntax._
import scala.util.{Failure, Success}
case class CommandResult(res: Int)
object CommandResult {
implicit val decoder: Decoder[CommandResult] = ???
}
val ec: ExecutionContext = ???
val dispatcher: Dispatcher = ???
val commandId: CommandId = ???
def handleCommandResult[A](r: CommandResult): A = ???
def handleCommandError[A](error: ErrorResponse): A = ???
val durationTracingEnable: Boolean = ???
val initBuilder = RequestContext.builder()
val reqCtxBuilder = if (durationTracingEnable) {
initBuilder.withTracing("Doing '$commandName' asynchronously")
} else {
initBuilder
}
implicit val reqCtx: RequestContext = reqCtxBuilder.build()
dispatcher
.status(commandId)
.transform {
case Success(Right(Some(commandAggregatedStatus))) =>
val handledResult: Option[_] = for {
commandResultAsJson <- commandAggregatedStatus.value
commandResult <- commandResultAsJson.as[CommandResult].toOption
} yield {
handleCommandResult(commandResult)
}
Success(handledResult)
case Success(Left(error)) =>
handleCommandError(error)
Success(None)
case _ =>
Success(None)
}(ec)
PollStatus
Возвращает статус CommandAggregatedStatusJson команды по ее CommandId с задержкой
Поведение команды и ее результат зависят от ситуации:
* Если найден результат команды, то сразу же без задержки возвращает его.
* Если результат не найден, то ждет его в течении timeout. Если по его прошествию результат все еще не найден, то возвращает последний статус, если он есть.
Получение результата или статуса команды
import com.embedika.verdi.models.debug.TracingContext
import com.embedika.verdi.models.{RequestContext, RequestContextBuilder}
import com.embedika.verdi.models.command._
import com.embedika.verdi.senderlib.Dispatcher
import scala.concurrent.ExecutionContext
import scala.concurrent.Future
import scala.concurrent.duration._
import io.circe.Decoder
import io.circe.syntax._
import scala.util.{Failure, Success}
case class CommandResult(res: Int)
object CommandResult {
implicit val decoder: Decoder[CommandResult] = ???
}
val ec: ExecutionContext = ???
val dispatcher: Dispatcher = ???
val commandId: CommandId = ???
def handleCommandResult[A](r: CommandResult): A = ???
def handleCommandError[A](error: ErrorResponse): A = ???
val durationTracingEnable: Boolean = ???
val initBuilder = RequestContext.builder()
val reqCtxBuilder = if (durationTracingEnable) {
initBuilder.withTracing("Doing '$commandName' asynchronously")
} else {
initBuilder
}
implicit val reqCtx: RequestContext = reqCtxBuilder.build()
dispatcher
.pollStatus(commandId, 5.seconds)
.transform {
case Success(Right(Some(commandAggregatedStatus))) if commandAggregatedStatus.status == CommandStatus.Completed =>
val handledResult: Option[_] = for {
commandResultAsJson <- commandAggregatedStatus.value
commandResult <- commandResultAsJson.as[CommandResult].toOption
} yield handleCommandResult(commandResult)
Success(handledResult)
case Success(Left(error)) =>
handleCommandError(error)
Success(None)
case _ =>
Success(None)
}(ec)
models.command
Структуры, которые описывают команды.
CommandId
Содержит идентификатор команды.
| Название поля | Описание |
|---|---|
| raw | ID в виде строки |
CommandName
Содержит наименование команды.
| Название поля | Описание |
|---|---|
| raw | Имя в виде строки |
CommandAggregatedStatus
Содержит последний известный результат выполнения команды.
| Название поля | Описание |
|---|---|
| status | Статус выполнения команды |
| timestamp | Время получения результата команды (кол-во миллисекунд с 1970-01-01T00:00:00Z). Для HTTP команд это время получения ответа, а для Kafka - время события завершения команды. |
| value | Опциональный результат выполнения команды. Может быть как JSON строкой, так и JSON объектом. |
| httpHeaders | Заголовки HTTP ответа команды, которые нужно передавать клиенту также в виде заголовков HTTP. На APIGateway данное поле переносится из тела ответа в заголовки. |
CommandAggregatedStatusJson
Содержит наименование команды.
| Название поля | Описание |
|---|---|
| raw | JSON представление CommandAggregatedStatus в виде строки. |
CommandEvent
Содержит описание события по команде.
Если размер контента в поле "value" превышает допустимый лимиты Kafka topic, то значение поля "value" будет заменено но стандратное сообщение:
"The command response size ($valueBytes) exceeded $valueMaxBytes bytes limit. The response could not be sent.".
В случае, если "value" содержит описание ошибки в структуре ErrorResponse, то эта структура будет сохранена, но будут заменены поля:
"message" = стандартное сообщение,
"stackTrace" = null.
| Название поля | Описание |
|---|---|
| id | ID события |
| status | Новый статус выполнения команды |
| timestamp | Время изменения статуса команды |
| value | Опциональный результат выполнения команды, которы соответствует статусу. Может быть как JSON строкой, так и JSON объектом. |
CommandInfo
Содержит описание команды.
| Название поля | Описание |
|---|---|
| незаполненная | таблица |
CommandStatus
Описывает статус выполнения команды.
| Возможные значения | Описание | Дополнительно |
|---|---|---|
| Created | Команда создана | Обязательный начальный статус |
| InProcess | Началась обработка команды | Необязательный промежуточный статус |
| Completed | Команда завершена | Конечный статус. Считается успешным. |
| Failed | Команда завершена с ошибкой | Конечный статус. Считается неуспешным. |
| TimedOut | Команда не завершилась за заданное время. Выполнение прекращено. | Конечный статус. Считается неуспешным. |
ErrorResponse
Ответ команды с ошибкой в качестве результата.
| Название поля | Тип | Обязательное | Описание |
|---|---|---|---|
| code | ErrorResponseCode | да | Тип ошибки |
| message | String | нет | Сообщение об ошибке (см. https://confluence.dev.embedika.ru/pages/viewpage.action?pageId=889782432) |
| stackTrace | String | нет | Информация о стеке вызовов во время ошибки |
| businessError | businesserror | нет | Константа описывающая бизнес-ошибку (контекстно-специфичный код ошибки) |
| data | Json | нет | Данные, которые необходимо передавать клиенту вместе с ошибкой |
| cause | Throwable | нет | Поле не участвует в сериализации. Содержит исключение, которое является причиной ошибки. |
ErrorResponseCode
Код обозначающий тип ошибки в ответе.
| Возможные значения | Тип | Описание |
|---|---|---|
| InvalidParameters | String | Для команды переданы неверные параметры. |
| NotAvailableDestinations | String | Нет ни одного доступного получателя для данной команды. |
| NotValidResponse | String | Некорректный HTTP ответ по команде. |
| CannotWaitCommandCompletion | String | Async команда не успела завершится за определенное время. |
| CannotSend | String | Невозможно отправить команду или результат ее работы. Содержит описание причины. |
| Exception | String | Необработанный exception. Может содержать Throwable и его сообщение, являющийся причиной ошибки. |
| HttpError(statusCode: Int) | Json | Результат команды следует интерпретировать как HttpResponse с определенным статусом. |
BusinessError
Значение описывающий бизнес-ошибку (контекстно-специфичный код ошибки). Соответствует типу String.
Список используемых значений для ошибок учетной записи пользователя:
ACC001- Время действия учетной записи закончилось
Список используемых значений для ошибок лицензионных ограничений:
LCN001- Превышено ограничение на кол-во зарегистрированных пользователейLCN002- Превышено ограничение на активные сессии
models.dispatch
Структуры, которые описывают способ отправки команд.
DispatchError
Содержит идентификатор команды.
| Возможные значения | Описание |
|---|---|
| InvalidParameters | Для команды переданы неверные параметры |
| NotAvailableDestinations | Нет ни одного доступного получателя для данной команды |
| NotValidResponse | Некорректный HTTP ответ по команде |
| CannotWaitCommandCompletion | Команда не завершена |
| CannotSend | Невозможно отправить команду или результат ее работы. Содержит описание причины. |
| Exception | Необработанный exception. Содержит Throwable, являющийся причиной ошибки. |
DispatchType
Описывает тип отправки команды
| Возможные значения | Описание |
|---|---|
| Http | Отправка команды с помощью HTTP (HTTP request) |
| Kafka | Отправка команды с помощью Kafka (Kafka message) |
HttpDispatchParameters
Содержит параметры отправки команды по HTTP.
| Возможные значения | Описание |
|---|---|
| незаполненная | таблица |
HttpMethod
Описывает используемый метод HTTP
| Возможные значения | Описание |
|---|---|
| GET | GET запрос |
| POST | POST запрос |
KafkaDispatchParameters
Содержит параметры отправки команды через Apache Kafka.
| Название поля | Описание |
|---|---|
| незаполненная | таблица |
models.service
Структуры, которые описывают принимающий команды сервис.
ServiceId
Содержит идентификатор сервиса. Например, "documents-service-instance-1".
| Название поля | Описание |
|---|---|
| raw | ID в виде строки |
ServiceName
Содержит наименование сервиса. Например, "documents-service".
| Название поля | Описание |
|---|---|
| raw | Имя в виде строки |
ServiceAddress
Содержит адрес сервиса. Например, "192.168.0.1".
| Название поля | Описание |
|---|---|
| raw | Адрес в виде строки |
DiscoverableService
Описание сервиса, который можно найти в реестре сервисов.
| Название поля | Описание |
|---|---|
| незаполненная | таблица |
GeneralStructs
Общие структуры, не привязанные к какой-либо сущности.
AsyncStoppable
Некоторая продолжительная операция или непрерывная обработка, которую можно явным образом прервать. Прерывание является асинхронным.
Имеет метод def stop(): Future[Boolean], который останавливает текущую операцию.
SyncStoppable
Интерфейс описывающий процесс, который можно синхронно прервать
Senderlib-kafka
KafkaAuthConfig (senderlib)
Параметры для авторизации kafka-клиента (доступ к топикам).
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
| passwordBased | PasswordBasedCredentials | Нет | Реквизиты для аутентификации в kafka с помощью пароля | Должно быть заполнено, если не заполнено kerberosBased |
| kerberosBased | KerberosBasedCredentials | Нет | Реквизиты для аутентификации в kafka с помощью kerberos | Должно быть заполнено, если не заполнено passwordBased |
| truststore | TrustStoreConfig | Нет | Параметры для хранилища сертификатов | |
| topic | string | Нет | Название топика, к которому привязаны данные | |
| kind | string | Нет | Тип сущности, к которой привязаны данные | "producer" или "consumer" или "both"(равнозначно параметрам, валидным для "producer" и "consumer") или "admin"(не входит в "both") |
PasswordBasedCredentials (senderlib)
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
| user | string | Да | Имя пользователя | |
| password | string | Да | Пароль пользователя |
KerberosBasedCredentials (senderlib)
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
| principal | string | Да | Kerberos principal, соответствующий пользователю | |
| keytabPath | string | Да | Путь до файла keytab |
TrustStoreConfig (senderlib)
Параметры для хранилища сертификатов (Java key store)
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
| location | string | Да | Путь до хранилища сертификатов | |
| password | string | Нет | Пароль к хранилищу сертификатов |
KafkaAuthSettings (senderlib)
Параметры для авторизации kafka-клиента (доступ к топикам).
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
| staticAuth | KafkaAuthConfig | Нет | Данные для статической аутентификации (не зависит от топика) | |
| authMode | string | Нет | Режим аутентификации | "Static"(одна учетная запись на все запросы) или "Mapping"(учетная запись зависит от запроса) |
| authConfig | string | Нет | Данные для аутентификации в указанном режиме, если он отличается от KafkaAuthMode.Static | Строка в формате JSON с типом List[KafkaAuthConfig] |
| clientsCache | VerdiCacheConfig | Нет | Настройки кеширования Kafka-клиентов |
RetrySettings (senderlib)
Настойки для повтороного вызова функций
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
| attempts | string | Да | Максимальное количество повторных вызовов. Чтобы исключить возможность повторного вызова, нужно установить значение 0. | |
| delay | duration string | Да | Константная задержка перед повторным вызовом |
CommandResultRetryConditionKind (senderlib)
Вид условия, по которому результат команды будет считаться неуспешным и команду следует вызвать повторно. Соответствует типу String.
| Возможные значения | Описание |
|---|---|
| OnFailStatuses | Если результат команды ErrorResponse или результат имеет CommandStatus, который является неуспешным |
| OnAllExceptions | Если результат команды ErrorResponse и имеет ErrorResponseCode = Exception |
| OnSomeExceptions(Name1, Name2, ..) | Содержит список значений с разделителем , (запятая). Если результат команды ErrorResponse, имеет ErrorResponseCode = Exception. Значения в полях message или cause должны содержать одно из значений. |
SenderLibSettings
Настойки для создания senderlib-объектов через VerdiFactory. Для создания SenderLibSettings используется конфиг com.typesafe.config.Config.
| Поле | Тип | Обязательное | Значение по умолчанию | Описание | Ограничения |
|---|---|---|---|---|---|
| allowInternalCommands | bool | да | Возможность отправлять внутренние команды | ||
| commandsCacheUpdatePeriod | duration string | да | "0 ns" | Период обновления кеша с информацией о командах | |
| servicesCacheUpdatePeriod | duration string | да | "0 ns" | Период обновления кеша с информацией о сервисах | |
| commandsPrefix | string | нет | "commands" | Префикс в kv хранилище для команд | |
| consulConnectionMaxRetry | int | нет | 5 | Максимальное кол-во попыток подключения к Consul | |
| consulConnectionRetryDelay | duration string | нет | "1 seconds" | Фиксированные интервалы между попытками подключения к Consul | |
| kafkaSyncPollingTimeout | duration string | нет | "10 seconds" | Время ожидания завершения kafka-команд, которые клиент отправил "синхронно" | |
| httpCommandsRetryAttempts | int | нет | 5 | Максимальное количество повторных вызовов для HTTP команд | |
| httpCommandsRetryDelay | duration string | нет | "5 seconds" | Константная задержка перед повторным вызовом HTTP команды | |
| httpCommandsRetryKind | int | нет | "OnSomeExceptions(ConnectException)" | Вид условия, по которому результат команды будет считаться неуспешным и команду следует вызвать повторно | |
| considerAllCommandsAsInternal | bool | нет | false | Флаг настройки отправки всех команд как внутренних |
Similarity-plugin: плагин пересечений по смыслу
Плагин отвечает за обработку одного из возможных шагов сервиса индексации - шага с payload-типом Plugin.
Плагин читает из kafka-топика сообщения от сервиса Indexation, содержащие stepProgress,
и обрабатывает файловые поля сущности stepProgress.entityObject. Обрабатываются только поля, содержащиеся в step.payload.fields.
Во время обработки плагин обращается к Lamp, чтобы найти файловые поля других сущностей, содержимое файлов в которых по смыслу похоже на содержимое файлов соответствующих полей step.payload.fields у сущности stepProgress.entityObject.
После этого, если степень похожести файлов превышает APP_MEASURE_THRESHOLD, между файловыми полями step.payload.fields сущности stepProgress.entityObject
и найденными файловыми полями других сущностей создаются ссылки в data-model.
Подробнее процесс обработки сообщений описан в документации трейта BaseFlow проекта IntelligentPluginCore.
Конфигурирование SimilarityPlugin
Требования к запуску SimilarityPlugin
Запуск из консоли с помощью SBT
sbt boot/run
При запуске сервиса ожидается, что уже развернута необходимая инфраструктура:
- Kafka по адресу
localhost:9092 - Consul по адресу
localhost:8500 - Lamp с версией, которая соответствует LAMP_USE_VERSION_2, по адресу
lamp-dev.dev.embedika.ru:443 - Если LAMP_USE_VERSION_2=false, то все файлы, присутствующие на стенде, должны быть закэшированы в Lamp
- Запущен инстанс сервиса tech-constants
- Сервис indexation зарегистрирован в tech-constants
Список переменных окружения для сервиса SimilarityPlugin
| Переменная | Тип | Обязательная | Значение по умолчанию | Описание |
|---|---|---|---|---|
CONSUMER_TOPIC |
string | Нет | similarityPlugin |
Топик, в который поступает StepProgress на обработку. |
CONSUMER_GROUP |
string | Нет | similarityPlugin |
Имя группы-консьюмеров сервиса similarityPlugin. |
LAMP_USE_VERSION_2 |
boolean | Нет | false |
Использовать ли LAMP2 (true) или LAMP1 (false). |
LAMP_BUFFER_SIZE |
int | Нет | 10 |
Буфер на отправку сообщений в клиент LAMP. |
LAMP_RECONNECT_SCHEDULE |
string | Нет | I(2 seconds) |
Стратегия переподключения клиента LAMP (формат см. lamp.transport.model.Schedule). |
LAMP_HOST |
string | Нет | lamp-dev.dev.embedika.ru |
Адрес клиента LAMP (должен быть непустым, если LAMP_ENABLE=true). |
LAMP_PORT |
int | Нет | 443 |
Порт клиента LAMP (должен быть непустым, если LAMP_ENABLE=true). |
LAMP_TLS |
boolean | Нет | true |
Признак защищенного подключения к LAMP. |
LAMP_TLS_CERTIFICATE |
string | Нет | Путь файла с сертификатом для подключения к LAMP. | |
LAMP_TLS_PRIVATE_KEY |
string | Нет | Путь файла с приватным ключом для подключения к LAMP. | |
LAMP_TLS_ROOT_TRUSTED_CERTS |
string | Нет | Путь файла с центром сертификации (Certification Authority, CA) для подключения к LAMP. | |
LAMP_TIMEOUT |
duration string | Нет | 1 minute |
Таймаут отправки сообщения и получения результатов через клиент LAMP. |
LAMP_MAX_MESSAGE_SIZE |
int | Нет | 524288000 |
Максимальный допустимый размер сообщений в LAMP. |
LAMP_CACHEABLE_SERVICES |
string | Нет | extraction,keywords,lemmatization |
Строка, содержащая список сервисов LAMP, результаты которых будут кэшироваться внутри LAMP. При вызове одного рута LAMP может происходить обращение к нескольким сервисам LAMP. |
LAMP_PARAMETERS_OPERATION |
string | Нет | faiss |
Название операции, которое в качестве параметра передается в Lamp. |
APP_LINK_TYPE |
string | Нет | similarity |
Тип ссылки, создаваемой плагином в data-model. |
APP_LINK_OWNER |
string | Нет | faiss_similarity |
Link owner ссылки, создаваемой плагином в data-model. |
APP_MEASURE_NAME |
string | Нет | similarity |
measureName, которое будет использовано в объекте, лежащем в поле additionalData при создании ссылки в data-model. |
APP_MEASURE_THRESHOLD |
float | Нет | 0.5 |
Пороговое значение measure. Ссылки создаются только между документами, мера схожести между которыми больше или равна этому значению. |
APP_LAMP_ROUTE |
string | Нет | faiss_search_route |
Рут Lamp, к которому обращается плагин с запросом поиска пересекающихся файлов. |
APP_CREATE_LINKS_PER_MESSAGE |
int | Нет | 100 |
Размер батча для запроса к data-model c командой createObjectsLinks. |
PLUGIN_INFO_READABLE_NAME |
string | Нет | Плагин для построения ссылок между объектами, близкими по смыслу |
Значение в поле name у тех. константы плагина. |
PLUGIN_INFO_DESCRIPTION |
string | Нет | Проходит по всем объектам и строит ссылки между ними на основе близости по смыслу их файлов |
Значение в поле description у тех. константы плагина. |
PLUGIN_INFO_VERSION |
int | Нет | 1 |
Значение в поле serviceVersion у тех. константы плагина. |
APP_INDEXATION_CHUNK_SIZE |
int | Нет | 100 |
Значения, поступающие в топик CONSUMER_TOPIC, обрабатываются батчами. Батч поступает в обработку либо если из топика было получено количество сообщений равное максимальному размеру батча, либо если от получения первого элемента батча прошло время равное максимальной разнице получения элементов в батче. Эта переменная устанавливает максимальный размер батча. |
APP_INDEXATION_WITHIN |
duration string | Нет | 1 minutes |
Значения, поступающие в топик CONSUMER_TOPIC, обрабатываются батчами. Батч поступает в обработку либо если из топика было получено количество сообщений равное максимальному размеру батча, либо если от получения первого элемента батча прошло время равное максимальной разнице получения элементов в батче. Эта переменная устанавливает максимальную разницу времени получения элементов в батче. |
APP_MAX_RETRY |
int | Нет | 2 |
Максимальное количество ретраев, которое произойдет при обращении к LAMP, если он возвращает ошибку. |
CONSUMER_PROGRESS_TOPIC |
string | Нет | progress |
Топик, в который плагин пишет об окончании обработки. |
PRODUCER_INDEXATION_EVENT_TOPIC |
string | Нет | entityObjectEvent |
Топик, в который плагин отправляет запрос на переиндексацию backlinks. |
VERDI_HOST |
string | Нет | localhost |
Адрес, который будет зарегистрирован за данным экземпляром сервиса. |
VERDI_TTL |
duration string | Нет | 30 seconds |
Время, в течение которого экземпляр сервиса считается "активным". Таймер обновляется каждый раз, когда сервис присылает "health check". |
VERDI_HEALTH_CHECK |
duration string | Нет | 10 seconds |
Периодичность отправки "health check". |
VERDI_CONSUL |
string | Нет | http://localhost:8500 |
Адрес Consul. |
VERDI_CONSUL_AUTH_USER |
string | Нет | Название учетной записи Сonsul. Если название не указано, то настройки авторизации не будут применены. | |
VERDI_CONSUL_AUTH_PASSWORD |
string | Нет | Пароль учетной записи Сonsul. | |
VERDI_KAFKA_ADDRESS |
string | Нет | localhost:9092 |
Адрес Kafka. |
VERDI_KAFKA_TOPIC |
string | Нет | commandevents |
Название топика для отправки сообщений со статусом команд. |
VERDI_KAFKA_PRODUCER_PROPS |
string | Нет | max.request.size=1048576 |
Дополнительные параметры для Kafka producer. Заполняются по шаблону "key1=value1;key2=value2". |
VERDI_KAFKA_AUTH_USER |
string | Нет | Название учетной записи Kafka. Если название не указано, то настройки авторизации не будут применены. | |
VERDI_KAFKA_AUTH_PASSWORD |
string | Нет | Пароль учетной записи Kafka. | |
VERDI_KAFKA_AUTH_PRINCIPAL |
string | Нет | Principal учетной записи Kafka в Kerberos (в случае соединения с kafka через Kerberos). | |
VERDI_KAFKA_AUTH_KEYTAB_PATH |
string | Нет | Путь до keytab-файла (в случае соединения с kafka через Kerberos). | |
VERDI_KAFKA_AUTH_TRUSTSTORE_LOCATION |
string | Нет | Путь до хранилища сертификатов (Java key store). Если путь не указан, то сертификат применяться не будет. | |
VERDI_KAFKA_AUTH_TRUSTSTORE_PASSWORD |
string | Нет | Пароль к хранилищу сертификатов. | |
VERDI_KAFKA_AUTH_MODE |
string | Нет | static |
Режим аутентификации: static - одна учетная запись на все запросы, mapping - учетная запись зависит от запроса. |
VERDI_KAFKA_AUTH_CONFIG |
string | Нет | Настройки для аутентификации: если AuthMode = mapping, то необходим JSON с List[KafkaAuthConfig]. Переменная соответствует полю authConfig из KafkaAuthSettings. | |
VERDI_KAFKA_AUTH_CACHE_SIZE |
int | Нет | Максимальный размер кэша для Kafka producer (количество активных соединений). | |
VERDI_KAFKA_AUTH_CACHE_TTL |
duration string | нет | Время жизни Kafka producer в кэше. | |
VERDI_ALLOW_INTERNAL_COMMANDS |
boolean | Нет | true |
Можно ли сервису отправлять внутрисистемные команды. |
VERDI_CONSIDER_ALL_COMMANDS_AS_INTERNAL |
boolean | Нет | false |
Флаг, определяющий будут ли все обращения в другие сервисы являться внутренними (т.е. не требовать авторизацию). Детальное описание механизма: Внутренние команды. |
VERDI_COMMAND_STORAGE_UPDATE_PERIOD |
duration string | Нет | 1 minutes |
Время кэширования данных по командам из CommandDiscovery. |
VERDI_SERVICE_DISCOVERY_UPDATE_PERIOD |
duration string | Нет | 30 seconds |
Время кэширования данных по сервисам из ServiceDiscovery. |
VERDI_CONSUL_CONNECTION_MAX_RETRY |
int | Нет | 5 |
Максимальное количество попыток подключения к Consul после обрыва соединения. |
VERDI_CONSUL_CONNECTION_RETRY_DELAY |
duration string | Нет | 1 seconds |
Задержка перед попыткой подключения к Consul. |
VERDI_KAFKA_SYNC_POLL_PERIOD |
duration string | Нет | 1 seconds |
Периодичность запроса статуса команды, отправленной через Kafka. |
VERDI_KAFKA_SYNC_POLL_TIMEOUT |
duration string | Нет | 1 minute |
Время ожидания завершения команды, отправленной через Kafka. |
VERDI_COMMANDS_HTTP_RETRY_ATTEMPTS |
int | Нет | 5 |
Поле attempts из RetrySettings. |
VERDI_COMMANDS_HTTP_RETRY_DELAY |
duration string | Нет | 5 seconds |
Поле delay из RetrySettings. |
VERDI_COMMANDS_HTTP_RETRY_KIND |
string | Нет | OnSomeExceptions(ConnectException) |
CommandResultRetryConditionKind. |
Команды сервиса SimilarityPlugin
Сервис SimilarityPlugin не содержит в себе никакие команды. Вместо этого он обрабатывает kafka-сообщения, поступающие из сервиса индексации.
Для обработки сообщений SimilarityPlugin использует реализации BaseFlow, предоставляемые IntelligentPluginCore.
Два файла с идентификаторами id1 и id2 в SimilarityPlugin считаются пересекающимися, если:
- при запросе c id1 к Lamp в ответ поступило сообщение message с типом FaissMessage
- id2 содержится в message.ids
- id2 соответствует lampMeasure из message.similarities
- при этом lampMeasure >= APP_MEASURE_THRESHOLD.
Tagging-plugin: плагин присвоения тегов файлам
Плагин отвечает за обработку одного из возможных шагов сервиса индексации - шага с payload-типом Plugin.
Плагин читает из kafka-топика сообщения от сервиса indexation, содержащие stepProgress,
и обрабатывает файловые поля из stepProgress.files сущности stepProgress.entityObject.
Сервис индексации присылает в stepProgress.files только поля, содержащиеся в step.payload.fields.
Во время обработки плагин:
- Из каждого полученного
stepProgressизвлекает список информации о файловых полях изstepProgress.filesдля последующей обработки. - Для каждого обрабатываемого файлового поля плагин выполняет следующие шаги:
- Обращается к S3 и получает метаданные файла. Из них извлекает
fileName. - Пытается достать из кэша объект TaggingRules. В случае успеха игнорирует шаги 3-5 и переходит сразу к шагу 6.
- В случае отсутствия TaggingRules в кэше плагин обращается к сервису alexandrina и получает список CatalogItem, которые содержатся в справочнике с кодом, равным значению
TAGS_CATALOG_CODE. Архивные CatalogItem игнорируются. - У каждого полученного CatalogItem плагин достает из json-поля
metadataполеextensions. Полеextensionsсодержит список расширений файла, которые могут использоваться для того, чтобы сопоставить файлу тэг с идентификаторомсatalogItem.code. - Записывает в кэш объект TaggingRules - соответствие между расширением и списком тэгов, которые нужно сопоставить файлу с таким расширением.
- Извлекает из
fileName, полученного в шаге 1 расширение файлаsomeExtension. Обращается к data-model с командой WriteFileTags и таким образом прикрепляет к файлу все тэги, которые соответствуют расширениюsomeExtensionв TaggingRules. У одного файла может быть несколько тэгов.
- Обращается к S3 и получает метаданные файла. Из них извлекает
Конфигурирование TaggingPlugin
Требования к запуску TaggingPlugin
Запуск из консоли с помощью SBT
sbt boot/run
При запуске сервиса ожидается, что уже развернута необходимая инфраструктура:
- Kafka по адресу
localhost:9092 - Consul по адресу
localhost:8500 - S3 по адресу
localhost:9000 - Запущены инстансы сервисов alexandrina и tech-constants
- Сервис indexation зарегистрирован в tech-constants
Список переменных окружения для сервиса TaggingPlugin
| Переменная | Тип | Обязательная | Значение по умолчанию | Описание |
|---|---|---|---|---|
CONSUMER_TOPIC |
string | Нет | taggingPlugin |
Топик, в который поступает StepProgress на обработку. |
CONSUMER_GROUP |
string | Нет | taggingPlugin |
Имя группы-консьюмеров сервиса taggingPlugin. |
PLUGIN_INFO_READABLE_NAME |
string | Нет | Плагин для тегирования файлов |
Значение в поле name у тех. константы плагина. |
PLUGIN_INFO_DESCRIPTION |
string | Нет | Проходит по всем файлам и назначаем им теги на основе их расширения |
Значение в поле description у тех. константы плагина. |
PLUGIN_INFO_VERSION |
int | Нет | 1 |
Значение в поле serviceVersion у тех. константы плагина. |
TAGS_CATALOG_CODE |
string | Нет | FileTags |
Код справочника в сервисе alexandrina, который хранит доступные в системе тэги. |
TAGS_CATALOG_TITLE |
string | Нет | Типы файлов |
Человекочитаемое описание справочника в сервисе alexandrina, который хранит доступные в системе тэги. |
TAGS_CACHE_LIFETIME |
duration string | Нет | 1 hour |
Время жизни TaggingRules в кеше. |
TAGS_CACHE_FILLTIME |
duration string | Нет | 10 seconds |
Максимальное время выполнения запроса к alexandrina для получения элементов каталога тегов и преобразования их в TaggingRules. |
FS_URI |
url string | Нет | http://localhost:9000/ |
Адрес для подключения к хранилищу файлов по S3-API. |
FS_ACCESS_KEY_ID |
string | Да | Ключ доступа для хранилища файлов (aka логин). | |
FS_SECRET_ACCESS_KEY |
string | Да | Секретный ключ для хранилища файлов (aka пароль). | |
FS_UPLOAD_PARALLELISM |
int | Нет | 4 |
Параллелизм для загрузки файлов. |
FS_AUTH_MODE |
string | Нет | static |
Режим аутентификации: static - одна учетная запись на все запросы, mapping - учетная запись зависит от запроса. |
FS_AUTH_CONFIG |
string | Нет | Настройки для аутентификации: если AuthMode = mapping, то необходим JSON с маппингом учетных записей. | |
FS_CACHE_SIZE |
int | Нет | 1 |
Максимальный размер кеша клиентов для хранилища файлов (количество активных соединений). |
FS_CACHE_TTL |
duration string | Нет | Время жизни клиента в кеше. | |
FS_RETRY_ATTEMPTS |
int | нет | 5 | Количество ретраев, которое будет произведено в случае Exception-а в операции FSClient-а и при вычитывании стрима в get операциях FSClient-а. |
FS_RETRY_DELAY |
duration string | нет | 10 millis | Задержка между ретраями операций FSClient-а. |
FS_ZIO_SHORT_MESSAGE_MODE |
boolean | нет | false | Флаг включения режима сохранения ошибок работы с файловым хранилищем в сервисе журналирования nestor. При включении режима ошибки в логах будут отображаться в сокращенном формате: Short zio message mode. ExceptionType: ТИП ОШИБКИ, Exception id: 'СГЕНЕРИРОВАННЫЙ UUID' added to journal. Указанный id будет фиксироваться в event записи nestor'а в поле data.id |
APP_INDEXATION_CHUNK_SIZE |
int | Нет | 100 |
Значения, поступающие в топик CONSUMER_TOPIC, обрабатываются батчами. Батч поступает в обработку либо если из топика было получено количество сообщений равное максимальному размеру батча, либо если от получения первого элемента батча прошло время, равное максимальной разнице получения элементов в батче. Эта переменная устанавливает максимальный размер батча. |
APP_INDEXATION_WITHIN |
duration string | Нет | 1 minutes |
Значения, поступающие в топик CONSUMER_TOPIC, обрабатываются батчами. Батч поступает в обработку либо если из топика было получено количество сообщений равное максимальному размеру батча, либо если от получения первого элемента батча прошло время, равное максимальной разнице получения элементов в батче. Эта переменная устанавливает максимальную разницу времени получения элементов в батче . |
APP_MAX_RETRY |
int | Нет | 2 |
Максимальное количество ретраев, которое произойдет при обращении LAMP, если он возвращает ошибку. |
CONSUMER_PROGRESS_TOPIC |
string | Нет | progress |
Топик, в который плагин пишет об окончании обработки. |
VERDI_HOST |
string | Нет | localhost |
Адрес, который будет зарегистрирован за данным экземпляром сервиса. |
VERDI_TTL |
duration string | Нет | 30 seconds |
Время, в течение которого экземпляр сервиса считается "активным". Таймер обновляется каждый раз, когда сервис присылает "health check". |
VERDI_HEALTH_CHECK |
duration string | Нет | 10 seconds |
Периодичность отправки "health check". |
VERDI_CONSUL |
string | Нет | http://localhost:8500 |
Адрес Consul. |
VERDI_CONSUL_AUTH_USER |
string | Нет | Название учетной записи Сonsul. Если название не указано, то настройки авторизации не будут применены. | |
VERDI_CONSUL_AUTH_PASSWORD |
string | Нет | Пароль учетной записи Сonsul. | |
VERDI_KAFKA_ADDRESS |
string | Нет | localhost:9092 |
Адрес Kafka. |
VERDI_KAFKA_TOPIC |
string | Нет | commandevents |
Название топика для отправки сообщений со статусом команд. |
VERDI_KAFKA_PRODUCER_PROPS |
string | Нет | max.request.size=1048576 |
Дополнительные параметры для Kafka producer. Заполняются по шаблону "key1=value1;key2=value2". |
VERDI_KAFKA_AUTH_USER |
string | Нет | Название учетной записи Kafka. Если название не указано, то настройки авторизации не будут применены. | |
VERDI_KAFKA_AUTH_PASSWORD |
string | Нет | Пароль учетной записи Kafka. | |
VERDI_KAFKA_AUTH_PRINCIPAL |
string | Нет | Principal учетной записи Kafka в Kerberos (в случае соединения с kafka через Kerberos). | |
VERDI_KAFKA_AUTH_KEYTAB_PATH |
string | Нет | Путь до keytab-файла (в случае соединения с kafka через Kerberos). | |
VERDI_KAFKA_AUTH_TRUSTSTORE_LOCATION |
string | Нет | Путь до хранилища сертификатов (Java key store). Если путь не указан, то сертификат применяться не будет. | |
VERDI_KAFKA_AUTH_TRUSTSTORE_PASSWORD |
string | Нет | Пароль к хранилищу сертификатов. | |
VERDI_KAFKA_AUTH_MODE |
string | Нет | static |
Режим аутентификации: static - одна учетная запись на все запросы, mapping - учетная запись зависит от запроса. |
VERDI_KAFKA_AUTH_CONFIG |
string | Нет | Настройки для аутентификации: если AuthMode = mapping, то необходим JSON с List[KafkaAuthConfig]. Переменная соответствует полю authConfig из KafkaAuthSettings. | |
VERDI_KAFKA_AUTH_CACHE_SIZE |
int | Нет | Максимальный размер кэша для Kafka producer (количество активных соединений). | |
VERDI_KAFKA_AUTH_CACHE_TTL |
int | Нет | Время жизни Kafka producer в кэше. | |
VERDI_ALLOW_INTERNAL_COMMANDS |
boolean | Нет | true |
Можно ли сервису отправлять внутрисистемные команды. |
VERDI_CONSIDER_ALL_COMMANDS_AS_INTERNAL |
boolean | Нет | false |
Флаг, определяющий будут ли все обращения в другие сервисы являться внутренними (т.е. не требовать авторизацию). Детальное описание механизма: Внутренние команды. |
VERDI_COMMAND_STORAGE_UPDATE_PERIOD |
duration string | Нет | 1 minutes |
Время кэширования данных по командам из CommandDiscovery. |
VERDI_SERVICE_DISCOVERY_UPDATE_PERIOD |
duration string | Нет | 30 seconds |
Время кэширования данных по сервисам из ServiceDiscovery. |
VERDI_CONSUL_CONNECTION_MAX_RETRY |
int | Нет | 5 |
Максимальное количество попыток подключения к Consul после обрыва соединения. |
VERDI_CONSUL_CONNECTION_RETRY_DELAY |
duration string | Нет | 1 seconds |
Задержка перед попыткой подключения к Consul. |
VERDI_KAFKA_SYNC_POLL_PERIOD |
duration string | Нет | 1 seconds |
Периодичность запроса статуса команды отправленной через Kafka. |
VERDI_KAFKA_SYNC_POLL_TIMEOUT |
duration string | Нет | 1 minute |
Время ожидания завершения команды отправленной через Kafka. |
VERDI_COMMANDS_HTTP_RETRY_ATTEMPTS |
int | Нет | 5 |
Поле attempts из RetrySettings. |
VERDI_COMMANDS_HTTP_RETRY_DELAY |
duration string | Нет | 5 seconds |
Поле delay из RetrySettings. |
VERDI_COMMANDS_HTTP_RETRY_KIND |
string | Нет | OnSomeExceptions(ConnectException) |
CommandResultRetryConditionKind. |
JOURNAL_MODE |
string | нет | WriteToJournal |
Режим журналирования Nestor. Допустимые значения: WriteToJournal (Отправка в сервис журналирования), WriteToTopic (Отправка события в очередь) |
JOURNAL_TOPIC |
string | да, если переменная JOURNAL_MODE = WriteToTopic |
"" | Название очереди журналирования. Для режима WriteToJournal значение игнорируется. |
Модели сервиса TaggingPlugin
TaggingRules (tagging-plugin)
Соответствует типу Map[String, Set[String]].
Ключом в данном Map является строка с расширением файла, а значением - набор идентификаторов тэгов, соответствующих этому расширению.
CatalogItem (tagging-plugin)
Элемент справочника.
Копия модели CatalogItem из сервиса alexandrina без поля isProtected.
| Поле | Тип | Обязательное | Значение по умолчанию | Описание | Ограничения |
|---|---|---|---|---|---|
| id | uuid string | да | ID элемента справочника | ||
| catalogId | uuid string | да | ID справочника | Комбинация catalogId и code каждого элемента справочника должна быть уникальной. | |
| code | string | да | Строковый код элемента | Длина не более 32 символов. Комбинация catalogId и code каждого элемента справочника должна быть уникальной. |
|
| title | string | да | Человекочитаемое название элемента | Длина не более 200 символов. | |
| archived | boolean | да | Признак архивности | ||
| metadata | json object | да | Дополнительные данные справочника - объект JSON | ||
| created | TimeStamp | нет | TimeStamp.now |
Дата создания элемента справочника | |
| modified | TimeStamp | нет | TimeStamp.now |
Дата последнего изменения элемента справочника | |
| version | integer | нет | 1 | Версия данных элемента. Нужна для оптимистичных блокировок |
Tech-constants: сервис технического справочника
Сервис технического справочника предназначен для настройки и хранения констант - данных сервисов, которые относятся к сквозным функциональностям.
Константа помимо кода имеет человекочитаемое название, описание и поле для дополнительных настроек. Константа относится к определенному сервису и типу, которые также регистрируются в сервисе тех.справочников. Подразумевается, что константы регистрируются сервисами автоматически (автоматические константы), а при необходимости могут быть переопределены пользователем (создаются ручные константы, которые приоритетнее автоматических).
Пример использования:
Для функциональности журналирования сервисы регистрируют константы типа journalEventType с наименованием и шаблоном описания событий, которые используются на фронтенде для отображения необходимой информации в человекочитаемом виде.
Информация по добавлению команд можно прочитать в описании шаблона.
Конфигурирование TechConstants
Требования к запуску TechConstants
Запуск из консоли с помощью SBT
TECH_CONSTANTS_DB_HOST=localhost
TECH_CONSTANTS_DB_PORT=5432
TECH_CONSTANTS_DB_NAME=techConstants_db
TECH_CONSTANTS_DB_USER=$TECH_CONSTANTS_DB_USER
TECH_CONSTANTS_DB_PASSWORD=$TECH_CONSTANTS_DB_PASSWORD
sbt boot/run
При запуске сервиса ожидается, что уже развернута необходимая инфраструктура:
- PostgreSQL база по адресу, указанному в конфиге (см. ниже)
- Kafka по адресу
localhost:9092 - Consul по адресу
localhost:8500 - Добавлены необходимые переменные окружения:
TECH_CONSTANTS_DB_HOSTTECH_CONSTANTS_DB_PORTTECH_CONSTANTS_DB_NAMETECH_CONSTANTS_DB_USERTECH_CONSTANTS_DB_PASSWORD
Список переменных окружения для сервиса TechConstants
| Переменная | Тип | Обязательная | Значение по умолчанию | Описание |
|---|---|---|---|---|
TECH_CONSTANTS_HTTP_HOST |
string | Нет | 0.0.0.0 |
Хост для HttpListener. |
TECH_CONSTANTS_HTTP_PORT |
int | Нет | 8192 |
Порт для HttpListener. |
TECH_CONSTANTS_KAFKA_SERVERS |
string | Нет | localhost:9092 |
Адрес Kafka. |
TECH_CONSTANTS_KAFKA_TOPIC |
string | Нет | tech_constants_commands |
Название топика для команд. |
TECH_CONSTANTS_KAFKA_TOPIC_PARTITIONS |
int | Нет | 10 |
Количество партиций в топике команд. |
TECH_CONSTANTS_KAFKA_CONSUMER_GROUP |
string | Нет | tech_constants_consumer_group |
Название consumer-группы для чтения команд. |
TECH_CONSTANTS_KAFKA_COMMANDEVENT_TOPIC |
string | Нет | commandevents |
Название топика для отправки сообщений со статусом команд. |
TECH_CONSTANTS_KAFKA_CONSUMER_RESTART_MIN_BACKOFF |
duration string | Нет | 1 second |
Минимальная задержка перед перезапуском. |
TECH_CONSTANTS_KAFKA_CONSUMER_RESTART_MAX_BACKOFF |
duration string | Нет | 30 seconds |
Максимально возможная задержка перед перезапуском. |
TECH_CONSTANTS_KAFKA_CONSUMER_RESTART_RANDOM_FACTOR |
double | Нет | 0.2 |
Коэффициент величины дополнительной случайной задержки (jitter) относительно основной задержки (При значении 0.2 задержка может быть до 20% больше, чем при 0). Если после умножения задержки на TECH_CONSTANTS_KAFKA_CONSUMER_RESTART_RANDOM_FACTOR получится меньше 1 миллисекунды, то jitter будет приравнен к нулю. |
TECH_CONSTANTS_KAFKA_CONSUMER_RESTART_MAX_RESTARTS |
int | Нет | 5 |
Максимальное количество перезапусков в заданный период времени. После превышения этого числа сервис будет объявлен больным. Все рестарты для каждого отдельного сообщения увеличивают и общий счетчик рестартов консьюмера, поэтому при использовании TECH_CONSTANTS_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS нужно указывать TECH_CONSTANTS_KAFKA_CONSUMER_RESTART_MAX_RESTARTS > TECH_CONSTANTS_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS или не указывать TECH_CONSTANTS_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS совсем. |
TECH_CONSTANTS_KAFKA_CONSUMER_RESTART_MAX_RESTARTS_WITHIN |
duration string | Нет | 5 minutes |
Период времени для ограничения перезапусков. |
TECH_CONSTANTS_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS |
int | Нет | 2 |
Максимальное количество раз, которое консьюмер перезапустится с неизменной очередью сообщений (в пределах DATA_MODEL_KAFKA_CONSUMER_RESTART_MAX_RESTARTS_WITHIN), прежде чем проигнорировать сообщение, на котором происходит ошибка (Указано количество рестартов, а не прочтений. Если TECH_CONSTANTS_KAFKA_CONSUMER_RESTART_MAX_RESTARTS = 2, то ошибочное сообщение будет обработано 3 раза, после чего произойдет 3ий рестарт и оно будет проигнорировано). Если указать 0, то перезапуск произойдет, но сообщение будет обработано только в первый раз, когда произошла ошибка. Если указать значение меньше 0, то перезапуски все равно будут происходить, но игнорирование сообщений, вызывающих ошибку, будет отключено. |
TECH_CONSTANTS_KAFKA_CONSUMER_PER_MESSAGE_RESTART_CACHE_SIZE |
int | Нет | 100 |
Для каждого сообщения счетчик перепрочтений хранится в кэше. Максимальное количество значений в этом кэше. |
TECH_CONSTANTS_KAFKA_CONSUMER_PER_MESSAGE_RESTART_CACHE_TTL |
duration string | Нет | 5 minutes |
Для каждого сообщения счетчик перепрочтений хранится в кэше. Максимальное время жизни элемента в этом кэше. В случае отсутствия значения время жизни элемента не будет ограничено. |
TECH_CONSTANTS_KAFKA_CONSUMER_POLL_TIMEOUT |
duration string | нет | 10 milliseconds |
timeout запроса poll для kafka consumer |
TECH_CONSTANTS_KAFKA_CONSUMER_POLL_INTERVAL |
duration string | нет | 100 milliseconds |
интервал между запросами poll для kafka consumer |
TECH_CONSTANTS_KAFKA_CONSUMER_PROPS |
string | нет | "max.poll.records=500;max.partition.fetch.bytes=524288" |
дополнительные параметры для kafka consumer в формате "key1=value1;key2=value2" |
TECH_CONSTANTS_KAFKA_CONNECTION_CHECK_TEST_MESSAGES_INTERVAL |
duration string | Нет | 4 minutes |
Применяется только для producer-ов со способом аутентификации kerberos. Интервал отправки тестовых сообщений кафки в топик connectionCheck.testMessagesTopicName. Тестовые сообщения (null, service producer test) отправляются регулярно с этим интервалом. |
TECH_CONSTANTS_KAFKA_CONNECTION_CHECK_INTERVAL |
duration string | Нет | 60 seconds |
Применяется только для producer-ов со способом аутентификации kerberos. Интервал проверки того, сколько тестовых сообщений было отправлено за данный период. Если количество сообщений за этот период равно количеству сообщений за прошлый период, то начинается отсчет периода без сообщений. |
TECH_CONSTANTS_KAFKA_CONNECTION_CHECK_FAILED_AFTER_INTERVAL |
duration string | Нет | 5 minutes |
Применяется только для producer-ов со способом аутентификации kerberos. Максимальная продолжительность периода без успешно отправленных тестовых сообщений. По ее достижении сервис будет объявлен больным. |
TECH_CONSTANTS_KAFKA_AUTH_USER |
string | Нет | Название учетной записи Kafka. Если название не указано, то настройки авторизации не будут применены. | |
TECH_CONSTANTS_KAFKA_AUTH_PASSWORD |
string | Нет | Пароль учетной записи Kafka. | |
TECH_CONSTANTS_KAFKA_AUTH_PRINCIPAL |
string | Нет | Principal учетной записи Kafka в Kerberos (в случае соединения с kafka через Kerberos). | |
TECH_CONSTANTS_KAFKA_AUTH_KEYTAB_PATH |
string | Нет | Путь до keytab-файла (в случае соединения с kafka через Kerberos). | |
TECH_CONSTANTS_KAFKA_AUTH_TRUSTSTORE_LOCATION |
string | Нет | Путь до хранилища сертификатов (Java key store). Если путь не указан, то сертификат применяться не будет. | |
TECH_CONSTANTS_KAFKA_AUTH_TRUSTSTORE_PASSWORD |
string | Нет | Пароль к хранилищу сертификатов. | |
TECH_CONSTANTS_KAFKA_AUTH_MODE |
string | Нет | static |
Режим аутентификации: static - одна учетная запись на все запросы, mapping - учетная запись зависит от запроса. |
TECH_CONSTANTS_KAFKA_AUTH_CONFIG |
string | Нет | Настройки для аутентификации: если AuthMode = mapping, то необходим JSON с List[KafkaAuthConfig]. Переменная соответствует полю authConfig из KafkaAuthSettings. | |
TECH_CONSTANTS_KAFKA_AUTH_CACHE_SIZE |
int | Нет | Максимальный размер кэша для Kafka producer (количество активных соединений). | |
TECH_CONSTANTS_KAFKA_AUTH_CACHE_TTL |
duration string | Нет | Время жизни Kafka producer в кэше. | |
TECH_CONSTANTS_CONSUL_ADDR |
string | Да | http://localhost:8500 |
Адрес Сonsul. |
TECH_CONSTANTS_CONSUL_AUTH_USER |
string | Нет | Название учетной записи Сonsul. Если название не указано, то настройки авторизации не будут применены. | |
TECH_CONSTANTS_CONSUL_AUTH_PASSWORD |
string | Нет | Пароль учетной записи Сonsul. | |
TECH_CONSTANTS_TRACE_DURATION |
boolean | Нет | false |
Признак необходимости трассировки выполнения команд. |
TECH_CONSTANTS_DISCOVERABLE_ID |
string | Нет | another_tech_constants_instance |
Id сервиса в ServiceDiscovery. |
TECH_CONSTANTS_DISCOVERABLE_NAME |
string | Нет | techConstants |
Имя сервиса в ServiceDiscovery. |
TECH_CONSTANTS_DISCOVERABLE_HOST |
string | Да | localhost |
Хост, публикуемый в ServiceDiscovery. |
TECH_CONSTANTS_DISCOVERABLE_PORT |
int | Нет | ${TECH_CONSTANTS_HTTP_PORT} |
Порт, публикуемый в ServiceDiscovery. |
TECH_CONSTANTS_DISCOVERABLE_LIVETIME |
duration string | Нет | 2 minutes |
Период после отправки health check, в течение которого ServiceDiscovery считает сервис живым. |
TECH_CONSTANTS_DISCOVERABLE_HEALTHPASS |
duration string | Нет | 1 minute |
Периодичность отправки health check в ServiceDiscovery. |
TECH_CONSTANTS_AKKA_HTTP_CLIENT_MAXCON |
int | Нет | 512 |
Максимальное число одновременных исходящих HTTP-соединений. |
TECH_CONSTANTS_AKKA_HTTP_CLIENT_MAXREQ |
int | Нет | 1024 |
Максимальное число одновременных исходящих HTTP-запросов. |
TECH_CONSTANTS_AKKA_HTTP_SERVER_MAXCON |
int | Нет | 1024 |
Максимальное число одновременных входящих HTTP-соединений. |
TECH_CONSTANTS_INTERNALCMD_ALLOW |
boolean | Нет | true |
Можно ли сервису отправлять внутрисистемные команды. |
TECH_CONSTANTS_SENDERLIB_CONSIDER_ALL_COMMANDS_AS_INTERNAL |
boolean | Нет | false |
Флаг, определяющий будут ли все обращения в другие сервисы являться внутренними (т.е. не требовать авторизацию). Детальное описание механизма: Внутренние команды. |
TECH_CONSTANTS_SENDERLIB_COMMANDS_CACHE_UPDATEPERIOD |
duration string | Нет | 10 minutes |
Время кэширования данных по командам из CommandDiscovery. |
TECH_CONSTANTS_SENDERLIB_SERVICES_CACHE_UPDATEPERIOD |
duration string | Нет | 30 seconds |
Время кэширования данных по сервисам из ServiceDiscovery. |
TECH_CONSTANTS_SENDERLIB_COMMANDS_HTTP_RETRY_ATTEMPTS |
int | Нет | 5 |
Поле attempts из RetrySettings. |
TECH_CONSTANTS_SENDERLIB_COMMANDS_HTTP_RETRY_DELAY |
duration string | Нет | 5 seconds |
Поле delay из RetrySettings. |
TECH_CONSTANTS_SENDERLIB_COMMANDS_HTTP_RETRY_KIND |
string | Нет | OnSomeExceptions(ConnectException) |
CommandResultRetryConditionKind. |
TECH_CONSTANTS_SENDERLIB_CONSUL_CONNECTION_RETRY_MAX |
int | нет | 5 |
Количество попыток переподключения к Consul |
TECH_CONSTANTS_SENDERLIB_CONSUL_CONNECTION_RETRY_DELAY |
duration string | нет | 1 second |
Задержка при попытках переподключения к Consul |
TECH_CONSTANTS_DB_URL |
string | Нет | Адрес базы данных. Можно использовать вместо TECH_CONSTANTS_DB_HOST, TECH_CONSTANTS_DB_PORT и TECH_CONSTANTS_DB_NAME. |
|
TECH_CONSTANTS_DB_HOST |
string | Да | Хост сервера базы данных. | |
TECH_CONSTANTS_DB_PORT |
int | Да | Порт сервера базы данных. | |
TECH_CONSTANTS_DB_NAME |
string | Да | Название базы данных. | |
TECH_CONSTANTS_DB_USER |
string | Да | Пользователь базы данных. | |
TECH_CONSTANTS_DB_PASSWORD |
string | Да | Пароль для пользователя базы данных. | |
TECH_CONSTANTS_DB_THREADS |
int | Нет | 10 |
Количество потоков в пуле потоков для соединения с БД. |
TECH_CONSTANTS_DB_QUEUE_SIZE |
int | Нет | 300 |
Размер очереди для действий базы данных, которые не могут быть выполнены немедленно, когда все потоки заняты. За пределами этого значения новые действия немедленно завершаются неудачей. |
TECH_CONSTANTS_DB_CONN_MAX |
int | Нет | 10 |
Максимальное количество одновременных подключений к БД. |
TECH_CONSTANTS_DB_CONN_TIMEOUT |
duration string | Нет | 20 second |
Максимальное время ожидания ответа для соединения к БД. Если это время превышено, а соединение не становится доступным, будет брошено исключение SQLException. 1000 мс — минимальное значение. |
TECH_CONSTANTS_DB_ISOLATION |
string | Нет | READ_COMMITTED |
Уровень изоляции транзакций для новых подключений. Допустимые значения: NONE, READ_COMMITTED, READ_UNCOMMITTED, REPEATABLE_READ, SERIALIZABLE. |
TECH_CONSTANTS_DB_READONLY |
boolean | Нет | false |
Read-only SQL транзакция может изменять только временные таблицы. Этот параметр управляет статусом «только для чтения» по умолчанию для каждой новой транзакции. |
TECH_CONSTANTS_DB_CONN_MIN |
int | Нет | ${TECH_CONSTANTS_DB_THREADS} |
Минимальное количество одновременных подключений к БД. |
TECH_CONSTANTS_DB_VALIDATION_TIMEOUT |
duration string | Нет | 1 seconds |
Максимальное время, в течение которого соединение будет проверяться на работоспособность. 1000 мс — минимальное значение. |
TECH_CONSTANTS_DB_IDLE_TIMEOUT |
duration string | Нет | 10 minutes |
Максимальное время, в течение которого соединению разрешено простаивать в пуле. Значение 0 означает, что простаивающие соединения никогда не удаляются из пула. |
TECH_CONSTANTS_DB_MAX_LIFETIME |
duration string | Нет | 30 minutes |
Максимальное время жизни соединения в пуле. Когда простаивающее соединение достигает этого времени ожидания, даже если оно недавно использовалось, оно будет удалено из пула. Значение 0 указывает на отсутствие максимального срока службы. |
TECH_CONSTANTS_DB_INITIALIZATION_FAIL_FAST |
boolean | Нет | false |
Deprecated, начиная с версии Slick 3.3.0. Определяет, будет ли пул «быстро выходить из строя», если пул не может быть успешно заполнен начальными соединениями. Если соединения не могут быть созданы во время запуска пула, будет выдано исключение RuntimeException. Это свойство не имеет никакого эффекта, если minConnections равно 0. |
TECH_CONSTANTS_DB_LEAK_DETECTION_THRESHOLD |
int | Нет | 0 |
Время, в течение которого соединение может находиться вне пула, прежде чем будет зарегистрировано сообщение, указывающее на возможную утечку соединения. Значение 0 означает, что обнаружение утечек отключено. Наименьшее приемлемое значение для включения обнаружения утечек составляет 10 с. |
TECH_CONSTANTS_DB_CONNECTION_TEST_QUERY |
string | Нет | SELECT 1 |
Выражение, которое будет выполнено непосредственно перед получением соединения из пула для проверки того, что соединение с базой данных все еще активно. Оно зависит от базы данных и должно представлять собой запрос, требующий минимальной обработки базой данных (например, «VALUES 1»). Если этот параметр не установлен, вместо него используется метод JDBC4 Connection.isValid(). |
TECH_CONSTANTS_DB_REGISTER_MBEANS |
boolean | Нет | false |
Зарегистрированы ли JMX Management Beans («MBeans»). |
TECH_CONSTANTS_DB_AUTO_COMMIT |
boolean | Нет | true |
Это свойство определяет то, как будут вести себя по умолчанию возвращаемые соединения относительно autocommit-а. |
TECH_CONSTANTS_DB_SCHEMA |
string | Нет | public |
Устанавливает schema по умолчанию. |
TECH_CONSTANTS_DB_ISOLATE_INTERNAL_QUERIES |
boolean | Нет | false |
Определяет то, изолируются ли с помощью транзакций внутренние запросы пула (например, запрос connection alive test). Свойство применяется только если autoCommit выключен. |
TECH_CONSTANTS_DB_INITIALIZATION_FAIL_TIMEOUT |
int | Нет | 1 |
Работает, начиная с версии Slick 3.3.0. Определяет, будет ли пул «быстро выходить из строя», если пул не может быть успешно заполнен начальными соединениями. Любое положительное число считается числом миллисекунд для попытки получить начальное соединение; поток приложения будет заблокирован в течение этого периода. Если соединение не может быть получено до истечения этого времени, будет брошено исключение. Данный таймаут применяется после периода connectionTimeout. Если значение равно нулю (0), HikariCP попытается получить и проверить подключение. Если соединение получено, но проверка не пройдена, будет брошено исключение, и пул не будет запущен. Однако, если соединение не может быть получено, пул запустится, но последующие попытки получить соединение могут потерпеть неудачу. Значение меньше нуля пройдет любую первоначальную попытку подключения, и пул немедленно запустится, пытаясь получить соединения в фоновом режиме. Следовательно, последующие попытки получить соединение могут потерпеть неудачу. |
TECH_CONSTANTS_SERVER_AUTHORIZER_KIND |
string | нет | authzforce |
Вид авторизатора, который используется в сервисе. Допустимые значения: "authzforce", "oberto". При указании неизвестного значения будет использовано значение по умолчанию. |
TECH_CONSTANTS_AUTHZFORCE_ADDR |
string | нет | http://localhost:8080/authzforce-ce |
Адрес AuthZforce server (переменная должна быть непустой, если SERVER_AUTHORIZER_KIND=authzforce). |
TECH_CONSTANTS_AUTHZFORCE_DOMAIN |
string | нет | Доступный DomainID в AuthZforce server (переменная должна быть непустой, если SERVER_AUTHORIZER_KIND=authzforce). |
|
TECH_CONSTANTS_AUTHZFORCE_CONNECT_TIMEOUT |
duration string | нет | 5 seconds |
Таймаут подключения к authzforce (переменная должна быть непустой, если SERVER_AUTHORIZER_KIND=authzforce). |
Команды сервиса TechConstants
Список реализованных в сервисе команд, моделей EntityType и действий Actions, которые можно использовать при настройке
авторизации.
Не все поля EntityType доступны для использования в настройке авторизации.
Если указан прочерк "-", то данное значение не влияет на авторизацию:
- если не указан Action, то никакой Action не проверяется (= без авторизации)
- если не указан EntityType, то на авторизацию влияет только Action
| Назначение команды | Имя вызова команды | EntityType | Actions |
|---|---|---|---|
| Регистрация сервиса | techConstants_UpsertService | - | - |
| Получение списка сервисов | techConstants_ListServices | - | - |
| Удаление сервиса | techConstants_DeleteService | - | - |
| Регистрация типа констант | techConstants_UpsertConstantType | - | - |
| Получение списка типов констант | techConstants_ListConstantTypes | - | - |
| Удаление типа констант | techConstants_DeleteConstantType | - | - |
| Автоматическая регистрация константы | techConstants_UpsertAutoConstant | Constant |
UpdateConstant |
| Автоматическая регистрация константы (внутренняя) | techConstants_UpsertAutoConstant_Internal | Constant |
UpdateConstant |
| Ручная регистрация константы | techConstants_UpsertManualConstant | Constant |
UpdateConstant |
| Получение константы | techConstants_GetConstant | Constant |
GetConstant |
| Получение константы (внутренняя) | techConstants_GetConstant_Internal | - | - |
| Получение списка констант | techConstants_ListAllConstants | Constant |
ListConstants |
| Получение списка констант (внутренняя) | techConstants_ListAllConstants_Internal | - | - |
| Получение всех констант определенного типа | techConstants_ListConstantsByType | Constant |
ListConstants |
| Получение всех констант определенного типа (внутренняя) | techConstants_ListConstantsByType_Internal | - | - |
| Удаление автоматического значения константы | techConstants_DeleteAutoConstant | Constant |
DeleteConstant |
| Удаление ручного значения константы | techConstants_DeleteManualConstant | Constant |
DeleteConstant |
UpsertService (TechConstants)
На входе свойства регистрируемого или обновляемого сервиса
{
"code": "techConstants",
"name": "Технический справочник",
"description": "Сервис технического справочника"
}
На выходе Boolean (признак успешности исполнения)
true
Регистрирует или обновляет сервис, для которого будут указываться константы.
Имя вызова команды: techConstants_UpsertService.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway), не требует аутентификации.
- На входе: ServiceUpsertDTO
- На выходе: Boolean
ListServices (TechConstants)
На выходе перечень зарегистрированных сервисов
[
{
"code": "techReferences",
"name": "Технический справочник",
"description": "Сервис технического справочника"
}
]
Возвращает перечень зарегистрированных сервисов.
Имя вызова команды: techConstants_ListServices.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: -
- На выходе: List[Service]
Нет сортировки по умолчанию.
DeleteService (TechConstants)
На входе код удаляемого сервиса
"techConstants"
На выходе Boolean (признак успешности исполнения)
true
Удаляет зарегистрированный сервис.
Имя вызова команды: techConstants_DeleteService.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway), не требует аутентификации.
- На входе: String
- На выходе: Boolean
UpsertConstantType (TechConstants)
На входе свойства регистрируемого или обновляемого типа констант
{
"code": "journal",
"name": "Журнал",
"description": "Описание типов событий журнала"
}
На выходе Boolean (признак успешности исполнения)
true
Регистрирует или обновляет тип констант.
Имя вызова команды: techConstants_UpsertConstantType.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: ConstantType
- На выходе: Boolean
ListConstantTypes (TechConstants)
На выходе перечень зарегистрированных типов констант
[
{
"code": "journal",
"name": "Журнал",
"description": "Описание типов событий журнала"
}
]
Возвращает перечень зарегистрированных типов констант.
Имя вызова команды: techConstants_ListConstantTypes.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: -
- На выходе: List[ConstantType]
Нет сортировки по умолчанию.
DeleteConstantType (TechConstants)
На входе код удаляемого типа констант
"journal"
На выходе Boolean (признак успешности исполнения)
true
Удаляет зарегистрированный тип констант.
Имя вызова команды: techConstants_DeleteConstantType.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: String
- На выходе: Boolean
UpsertAutoConstant (TechConstants)
На входе свойства регистрируемой константы
{
"code": "testConstant",
"constantType": "testConstantType",
"service": "testServiceType",
"name": "Тестовая константа",
"description": "Описание тестовой константы",
"settings": {
"test": "auto"
},
"serviceVersion": 1
}
На выходе Boolean (признак успешности исполнения)
true
Регистрирует или обновляет автоматическую константу (source - Auto). Должно вызываться сервисом. Константа будет обновлена, если значение serviceVersion, указанное в запросе, не ниже значения того же поля у сохраненной в справочнике константы. При этом в ином случае все равно будет возвращено true, как признак того, что запрос отработал корректно.
Имя вызова команды: techConstants_UpsertAutoConstant.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: ConstantUpsertAutoDTO
- На выходе: Boolean
UpsertAutoConstant_Internal (TechConstants)
На входе свойства регистрируемой константы
{
"code": "testConstant",
"constantType": "testConstantType",
"service": "testServiceType",
"name": "Тестовая константа",
"description": "Описание тестовой константы",
"settings": {
"test": "auto"
},
"serviceVersion": 1
}
На выходе Boolean (признак успешности исполнения)
true
Регистрирует или обновляет автоматическую константу (source - Auto). Должно вызываться сервисом.
Константа будет обновлена, если значение serviceVersion, указанное в запросе,
не ниже значения того же поля у сохраненной в справочнике константы.
При этом в ином случае все равно будет возвращено true, как признак того, что запрос отработал корректно.
Имя вызова команды: techConstants_UpsertAutoConstant_Internal.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway), не требует аутентификации.
- На входе: ConstantUpsertAutoDTO
- На выходе: Boolean
UpsertManualConstant (TechConstants)
На входе свойства регистрируемой константы
{
"code": "testConstant",
"constantType": "testConstantType",
"service": "testServiceType",
"name": "Тестовая константа - переопределение вручную",
"description": "Описание тестовой константы - переопределение вручную",
"settings": {
"test": "manual"
}
}
На выходе Boolean (признак успешности исполнения)
true
Регистрирует или обновляет ручную константу (source - Manual). Должно вызываться человеком.
Имя вызова команды: techConstants_UpsertManualConstant.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: ConstantUpsertManualDTO
- На выходе: Boolean
GetConstant (TechConstants)
На входе код и тип константы
{
"code": "testConstant",
"constantType": "testConstantType"
}
На выходе данные константы
{
"code": "testConstant",
"constantType": "testConstantType",
"service": "testService",
"name": "Тестовая константа - переопределение вручную",
"description": "Описание тестовой константы - переопределение вручную",
"settings": {
"test": "manual"
},
"source": "Auto",
"modified": 1732515433705
}
Получает данные константы.
Если с указанным кодом и типом зарегистрирована и автоматическая, и ручная константа - будут получены данные ручной константы.
Имя вызова команды: techConstants_GetConstant.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: ConstantIdentityDTO
- На выходе: Constant
GetConstant_Internal (TechConstants)
На входе код и тип константы
{
"code": "testConstant",
"constantType": "testConstantType"
}
На выходе данные константы
{
"code": "testConstant",
"constantType": "testConstantType",
"service": "testService",
"name": "Тестовая константа - переопределение вручную",
"description": "Описание тестовой константы - переопределение вручную",
"settings": {
"test": "manual"
},
"source": "Auto",
"modified": 1732515433705
}
Получает данные константы.
Если с указанным кодом и типом зарегистрирована и автоматическая, и ручная константа - будут получены данные ручной константы.
Имя вызова команды: techConstants_GetConstant_Internal.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway), не требует аутентификации.
- На входе: ConstantIdentityDTO
- На выходе: Constant
ListAllConstants (TechConstants)
На входе поисковой запрос
{
"query": "source",
"context": {
"source": "auto"
},
"sorting": {
"fieldName": "constanttype.name",
"order": "Asc"
},
"paging": {
"page": 1,
"count": 5
}
}
На выходе страница со списком констант
{
"items": [
{
"code": "ViewDataModel",
"constantType": "uiActionType",
"service": "dataModel",
"name": "Просмотр модели данных в виде схемы",
"description": null,
"settings": null,
"source": "Auto",
"modified": 1732515433705
},
{
"code": "ViewDataModelSection",
"constantType": "uiActionType",
"service": "dataModel",
"name": "Просмотр раздела \"Модель данных\"",
"description": null,
"settings": null,
"source": "Auto",
"modified": 1732515433705
},
{
"code": "UpdateObject",
"constantType": "uiActionType",
"service": "dataModel",
"name": "Редактирование объекта",
"description": null,
"settings": null,
"source": "Auto",
"modified": 1732515433705
},
{
"code": "DocumentSearch",
"constantType": "uiActionType",
"service": "dataModel",
"name": "Работа с разделом \"Поиск с использованием документа\"",
"description": null,
"settings": null,
"source": "Auto",
"modified": 1732515433705
},
{
"code": "ViewObjectCard",
"constantType": "uiActionType",
"service": "dataModel",
"name": "Просмотр карточки объекта",
"description": null,
"settings": null,
"source": "Manual",
"modified": 1732515433705
}
],
"total": 27
}
Получает список констант по поисковому запросу. Если зарегистрирована и автоматическая, и ручная константа (с одинаковым кодом и типом) - в списке будут получены данные только ручной константы.
Имя вызова команды: techConstants_ListAllConstants.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
По умолчанию сортировка производится по полю code.
Запрос принимает параметры сортировки, фильтров и пейджинга в параметре Search.
Применяется к полям модели ConstantStoreDTO
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров |
|---|---|
| id | InSetQuery |
| code | InSetQuery, LikeQuery |
| name | InSetQuery, LikeQuery |
| constantType | InSetQuery |
| source | InSetQuery |
| service | InSetQuery |
Доступные поля для сортировки:
| Поле | Примечание |
|---|---|
| code | - |
| name | - |
| constantType.name | По человекочитаемому названию типа константы |
| source | В алфавитном порядке. Строковое представление соответствующее — "Auto", "Manual" |
ListAllConstants_Internal (TechConstants)
На входе поисковой запрос
{
"query": "source",
"context": {
"source": "auto"
},
"sorting": {
"fieldName": "constanttype.name",
"order": "Asc"
},
"paging": {
"page": 1,
"count": 5
}
}
На выходе страница со списком констант
{
"items": [
{
"code": "ViewDataModel",
"constantType": "uiActionType",
"service": "dataModel",
"name": "Просмотр модели данных в виде схемы",
"description": null,
"settings": null,
"source": "Auto",
"modified": 1732515433705
},
{
"code": "ViewDataModelSection",
"constantType": "uiActionType",
"service": "dataModel",
"name": "Просмотр раздела \"Модель данных\"",
"description": null,
"settings": null,
"source": "Auto",
"modified": 1732515433705
},
{
"code": "UpdateObject",
"constantType": "uiActionType",
"service": "dataModel",
"name": "Редактирование объекта",
"description": null,
"settings": null,
"source": "Auto",
"modified": 1732515433705
},
{
"code": "DocumentSearch",
"constantType": "uiActionType",
"service": "dataModel",
"name": "Работа с разделом \"Поиск с использованием документа\"",
"description": null,
"settings": null,
"source": "Auto",
"modified": 1732515433705
},
{
"code": "ViewObjectCard",
"constantType": "uiActionType",
"service": "dataModel",
"name": "Просмотр карточки объекта",
"description": null,
"settings": null,
"source": "Manual",
"modified": 1732515433705
}
],
"total": 27
}
Получает список констант по поисковому запросу. Если зарегистрирована и автоматическая, и ручная константа (с одинаковым кодом и типом) - в списке будут получены данные только ручной константы.
Имя вызова команды: techConstants_ListAllConstants_Internal.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway), не требует аутентификации.
По умолчанию сортировка производится по полю code.
Запрос принимает параметры сортировки, фильтров и пейджинга в параметре Search.
Применяется к полям модели ConstantStoreDTO
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров |
|---|---|
| id | InSetQuery |
| code | InSetQuery, LikeQuery |
| name | InSetQuery, LikeQuery |
| constantType | InSetQuery |
| source | InSetQuery |
| service | InSetQuery |
Доступные поля для сортировки:
| Поле | Примечание |
|---|---|
| code | - |
| name | - |
| constantType.name | По человекочитаемому названию типа константы |
| source | В алфавитном порядке. Строковое представление соответствующее — "Auto", "Manual" |
ListConstantsByType (TechConstants)
На входе коды и тип константы
{
"codes": [
"testConstant"
],
"constantType": "testConstantType"
}
На выходе данные по списку констант
[
{
"code": "testConstant",
"constantType": "testConstantType",
"service": "testService",
"name": "Тестовая константа - переопределение вручную",
"description": "Описание тестовой константы - переопределение вручную",
"settings": {
"test": "manual"
},
"source": "Auto",
"modified": 1732515433705
}
]
Получает список констант по типу констант, и, опционально, перечню кодов констант. Если зарегистрирована и автоматическая, и ручная константа (с одинаковым кодом и типом) - в списке будут получены данные только ручной константы.
Имя вызова команды: techConstants_ListConstantsByType.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: ConstantListByTypeDTO
- На выходе: List[Constant]
ListConstantsByType_Internal (TechConstants)
На входе коды и тип константы
{
"codes": [
"testConstant"
],
"constantType": "testConstantType"
}
На выходе данные по списку констант
[
{
"code": "testConstant",
"constantType": "testConstantType",
"service": "testService",
"name": "Тестовая константа - переопределение вручную",
"description": "Описание тестовой константы - переопределение вручную",
"settings": {
"test": "manual"
},
"source": "Auto",
"modified": 1732515433705
}
]
Получает список констант по типу констант, и, опционально, перечню кодов констант. Если зарегистрирована и автоматическая, и ручная константа (с одинаковым кодом и типом) - в списке будут получены данные только ручной константы.
Имя вызова команды: techConstants_ListConstantsByType_Internal.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
Команда только внутренняя (нельзя вызвать через Api Gateway), не требует аутентификации.
- На входе: ConstantListByTypeDTO
- На выходе: List[Constant]
DeleteAutoConstant (TechConstants)
На входе код и тип константы
{
"code": "testConstant",
"constantType": "testConstantType"
}
На выходе Boolean (признак успешности исполнения)
true
Удаляет автоматическую константу. Если зарегистрирована и автоматическая, и ручная константа (с одинаковым кодом и типом) - ручная не удаляется.
Имя вызова команды: techConstants_DeleteAutoConstant.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: ConstantIdentityDTO
- На выходе: Boolean
DeleteManualConstant (TechConstants)
На входе код и тип константы
{
"code": "testConstant",
"constantType": "testConstantType"
}
На выходе Boolean (признак успешности исполнения)
true
Удаляет ручную константу. Если зарегистрирована и автоматическая, и ручная константа (с одинаковым кодом и типом) - автоматическая не удаляется.
Имя вызова команды: techConstants_DeleteManualConstant.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: ConstantIdentityDTO
- На выходе: Boolean
Модели сервиса TechConstants
Service (ServiceUpsertDTO)
Модель зарегистрированного (регистрируемого) сервиса.
| Поле | Тип | Обязательное | Значение по умолчанию | Описание | Ограничения |
|---|---|---|---|---|---|
code |
string | Да | Код сервиса | Длина не более 32. Уникальное значение. |
|
name |
string | Да | Наименование сервиса | Длина не более 128. | |
description |
string | Нет | Описание сервиса |
ConstantType (ConstantTypeUpsertDTO)
Модель зарегистрированного (регистрируемого) типа констант.
| Поле | Тип | Обязательное | Значение по умолчанию | Описание | Ограничения |
|---|---|---|---|---|---|
code |
string | Да | Код типа констант | Длина не более 32. Уникальное значение. |
|
name |
string | Да | Наименование типа констант | Длина не более 128. | |
description |
string | Нет | Описание типа констант |
Constant
Данные зарегистрированной константы.
| Поле | Тип | Обязательное | Значение по умолчанию | Описание | Ограничения |
|---|---|---|---|---|---|
code |
string | Да | Код константы | Длина не более 64. Уникальное значение. |
|
constantType |
string | Да | Код типа константы | Длина не более 32. Существующий код типа констант. |
|
service |
string | Да | Код сервиса константы | Длина не более 32. Существующий код сервиса. |
|
name |
string | Да | Наименование константы | Длина не более 128. | |
description |
string | Нет | Описание константы | ||
settings |
json | Нет | Дополнительные произвольные настройки константы | ||
source |
string | Да | Источник константы: Auto или Manual (автоматическая или ручная константа) |
Длина не более 32. | |
modified |
TimeStamp | Да | Дата последнего обновления константы в миллисекундах (UTC from 1970) |
ConstantStoreDTO
Хранимая модель зарегистрированных констант.
| Поле | Тип | Обязательное | Значение по умолчанию | Описание | Ограничения |
|---|---|---|---|---|---|
id |
uuid | Нет | UUID.randomUUID |
Идентификатор константы | |
code |
string | Да | Код константы | Длина не более 64. Уникальное значение. |
|
constantType |
string | Да | Код типа константы | Длина не более 32. Существующий код типа констант. |
|
service |
string | Да | Код сервиса константы | Длина не более 32. Существующий код сервиса. |
|
name |
string | Да | Наименование константы | Длина не более 128. | |
description |
string | Нет | Описание константы | ||
settings |
json | Нет | Дополнительные произвольные настройки константы | ||
source |
string | Да | Источник константы: Auto или Manual (автоматическая или ручная константа) |
Длина не более 32. | |
modified |
TimeStamp | Да | TimeStamp.now |
Дата последнего изменения константы | |
serviceVersion |
string | Нет | Версия константы внутри сервиса |
ConstantIdentityDTO
Данные для работы с одной константой (получение или удаление константы).
Поскольку несколько констант могут иметь один и тот же код, но разный тип, требуется указать оба соответствующих поля.
| Поле | Тип | Обязательное | Значение по умолчанию | Описание | Ограничения |
|---|---|---|---|---|---|
code |
string | Да | Код константы | Длина не более 64. | |
constantType |
string | Да | Код типа константы | Длина не более 32. Существующий тип константы. |
ConstantUpsertAutoDTO
Данные для регистрации или обновления автоматической константы.
| Поле | Тип | Обязательное | Значение по умолчанию | Описание | Ограничения |
|---|---|---|---|---|---|
code |
string | Да | Код константы. Константы разного типа могут иметь одинаковый код. | Длина не более 64. | |
constantType |
string | Да | Код типа константы | Длина не более 32. Существующий код типа константы. |
|
service |
string | Да | Код сервиса константы | Длина не более 32. Существующий код сервиса. |
|
name |
string | Да | Наименование типа констант | Длина не более 128. | |
description |
string | Нет | Описание типа констант | ||
settings |
json | Нет | Дополнительные произвольные настройки константы | ||
serviceVersion |
integer | Да | Версия константы внутри сервиса |
ConstantUpsertManualDTO
Данные для регистрации или обновления ручной константы.
| Поле | Тип | Обязательное | Значение по умолчанию | Описание | Ограничения |
|---|---|---|---|---|---|
code |
string | Да | Код константы. Константы разного типа могут иметь одинаковый код. | Длина не более 64. | |
constantType |
string | Да | Код типа константы | Длина не более 32. Существующий код типа константы. |
|
service |
string | Да | Код сервиса константы | Длина не более 32. Существующий код сервиса. |
|
name |
string | Да | Наименование типа констант | Длина не более 128. | |
description |
string | Нет | Описание типа констант | ||
settings |
json | Нет | Дополнительные произвольные настройки константы |
ConstantListByTypeDTO
Данные для получения списка констант определенного типа.
| Поле | Тип | Обязательное | Значение по умолчанию | Описание | Ограничения |
|---|---|---|---|---|---|
constantType |
string | Да | Код типа константы | Длина не более 32. Существующий код типа констант. |
|
codes |
array[string] | Нет | Перечень кодов констант, которые надо получить. Если не указано - получит все константы указанного типа. |
Tech-constants-client: клиент для сервиса Tech-constants
Библиотека предоставляет интерфейс и реализацию клиента для сервиса Tech-constants.
Пример создания Tech-constants-client
Для того чтобы использовать библиотеку techconstantsclient, нужно добавить зависимость
"com.embedika.verdi" %% "techconstantsclient" % verdiVersion.
Все классы находятся в пакете com.embedika.verdi.techConstants.client.
Основной интерфейс для взаимодействия TechConstantsClient[F[_]].
Реализация интерфейса LiveTechConstantsClientTF[F[_]: Monad: FromFuture], deprecated имплементация LiveTechConstantsClient
Пример для DI (izumi)
import com.embedika.verdi.techConstants.client.{LiveTechConstantsClientTF, TechConstantsClient}
make[TechConstantsClient[Future]].from {
(dispatcher: Dispatcher, ec: ExecutionContext @Id("ec-system"), fromFuture: FromFuture[Future]) =>
implicit val ffImpl: FromFuture[Future] = fromFuture
implicit val ecImpl: ExecutionContext = ec
new LiveTechConstantsClientTF[Future](dispatcher)
}
Предоставляемый функционал Tech-constants-client
Tech-constants-client предоставляет методы вызова соответствующих команд сервиса Tech-constants. Формат входных и выходных данных методов Tech-constants-client аналогичен формату входных и выходных данных команд сервиса Tech-constants.
Регистрация данных
Получение констант
- getConstant
- getConstantInternal
- listAllConstants
- listAllConstantsInternal
- listConstantsByType
- listConstantsByTypeInternal
Удаление данных
Детали регистрации данных в сервисе технического справочника
Сервис технического справочника позволяет другим сервисам регистрировать различные технические константы,
такие как, например, человекочитаемое название вида события в журнале или описание события в разделе уведомлений.
После регистрации, константы могут быть использованы на фронтенде для отображения необходимой информации.
Предполагается, что (пере)регистрация будет происходить при каждом старте инстанса сервиса,
примерно там же, где, например, происходит регистрация команд в консуле.
Константа, по сути, является маппингом из "код константы + код типа константы" в "наименование + описание + дополнительные произвольные настройки". Константы разного типа могут иметь одинаковый собственный код.
Типы констант, на текущем этапе, являются предзаданными в сервисе техсправочника значениями
и перечислены в объекте com.embedika.verdi.models.techConstant;
однако сервис допускает регистрацию иных типов вызовом соответствующего апи.
Ниже будет описан процесс использования клиента для регистрации констант. Более подробную информацию, описание моделей данных и пр. можно найти в документации сервиса технического справочника.
Процесс регистрации констант
Предварительно, перед регистрацией, в проекте необходимо описать перечень его констант.
Пример инициализации перечня констант
import com.embedika.verdi.models.techConstant.TechConstant
import com.embedika.verdi.models.techConstant.CommonConstantTypes._
object TechConstants {
object Journal {
val createForm: TechConstant = TechConstant(
code = ConstantCode("createForm"),
constantType = JournalEventType,
name = "Создана новая форма",
description = None,
settings = None,
serviceVersion = 1
)
val updateForm: TechConstant = TechConstant(
code = ConstantCode("updateForm"),
constantType = NotificationType,
name = "Создана новая форма",
description = None,
settings = None,
serviceVersion = 1
)
val all: Seq[TechConstant] = Seq(createForm, updateForm)
}
object Notifications {
//...
val all: Seq[TechConstant] = Seq(???)
}
val all = Journal.all + Notifications.all
}
Основной процесс регистрации
Пример процесса регистрации
// Нужен для вызова techConstantsClient::registerService
private implicit def rc: RequestContext = RequestContext.builder().build()
val serviceName = ServiceName(config.getString("name"))
techConstantsClient
.registerService(
serviceName = serviceName,
readableName = "Хранение UI",
description = Some("...описание сервиса")
)
.flatMap {
case Left(err) =>
// Обработать ошибку (логи, остальные обработки если нужны)
case Right(_) =>
// Зарегистрировать все константы, например через Future.traverse или иным способом:
Future.traverse(TechConstants.all)(techConstantsClient.registerConstantInternal(serviceName, _)).flatMap { results =>
// Обработать ошибки если нужны
}
}
Имея клиент, можно начать сам процесс регистрации. Ожидается, что она будет происходить при рестарте сервиса, где-то на одном этапе с регистрацией команд.
Первым этапом должна вызываться регистрация текущего сервиса. В случае успешной регистрации сервиса, можно зарегистрировать его константы.
UI-storage: сервис хранения UI
Сервис принимает команды и хранит состояние в PostgreSQL.
Команды могут приходить как по HTTP, так и через Kafka в топик ui_storage_commands.
Сервис разбит на несколько модулей, в виде sbt проектов:
domain, в котором содержатся все доменные модели и их различные представления.infrastructure, в котором содержатся базовые компоненты для взаимодействия с инфраструктурой.store, содержит сервисы для сохранения и чтения их разных хранилищ доменных моделей.service, содержит сервисы бизнес логии, которые определяют правила взаимодействия компонентов между собой.route, содержит HTTP роуты.boot, содержит зависимости и описание для сборки и запуска сервиса.
В сервисе реализованы следующие команды:
- Получить список типов форм
- Создать форму
- Получить форму по ID
- Удалить форму
- Обновить форму
- Получить список форм (V1)
- Получить список форм (V2)
- Получить форму по типу объекта
- Получить формы по типу форм
- Получить список ключей глобальных настроек
- Получить значение глобальной настройки
- Создать глобальную настройку
- Обновить ключ глобальной настройки
- Обновить значение глобальной настройки
- Удалить глобальную настройку
- Сохранить файлы для глобальных настроек
Локальный запуск сервиса хранения UI
При запуске сервиса ожидается, что уже развернута необходимая инфраструктура:
- PostgreSQL база по адресу
localhost:5432/UIStorage_db - Kafka по адресу
localhost:9092 - Minio по адресу
localhost:9000 - Consul по адресу
localhost:8500 Добавлены необходимые переменные окружения:
- UI_STORAGE_DB_HOST
- UI_STORAGE_DB_PORT
- UI_STORAGE_DB_NAME
- UI_STORAGE_DB_USER
- UI_STORAGE_DB_PASSWORD
Запуск сервиса хранения UI из консоли с помощью SBT
UI_STORAGE_DB_HOST=localhost UI_STORAGE_DB_PORT=5432 UI_STORAGE_DB_NAME=UIStorage_db UI_STORAGE_DB_USER=$UI_STORAGE_DB_USER UI_STORAGE_DB_PASSWORD=$UI_STORAGE_DB_PASSWORD sbt boot/run
Список переменных окружения сервиса хранения UI
| Переменная | Тип | Обязательная | Значение по умолчанию | Описание |
|---|---|---|---|---|
UI_STORAGE_HTTP_HOST |
string | нет | "0.0.0.0" | Хост для HttpListener |
UI_STORAGE_HTTP_PORT |
int | нет | 8192 | Порт для HttpListener |
UI_STORAGE_KAFKA_SERVERS |
string | нет | "localhost:9092" | Адрес Kafka |
UI_STORAGE_KAFKA_TOPIC |
string | нет | "ui_storage_commands" | Название топика для команд |
UI_STORAGE_KAFKA_CONSUMER_GROUP |
string | нет | "ui_storage_consumer_group" | Название consumer-группы для чтения команд |
UI_STORAGE_KAFKA_COMMANDEVENT_TOPIC |
string | нет | "commandevents" | Название топика для отправки сообщений со статусом команд |
UI_STORAGE_KAFKA_PARTITIONS |
int | нет | 10 | Количество партиций в топике команд. |
UI_STORAGE_KAFKA_CONSUMER_RESTART_MIN_BACKOFF |
duration string | нет | 1 second | Минимальная задержка перед перезапуском. |
UI_STORAGE_KAFKA_CONSUMER_RESTART_MAX_BACKOFF |
duration string | нет | 30 seconds | Максимально возможная задержка перед перезапуском. |
UI_STORAGE_KAFKA_CONSUMER_RESTART_RANDOM_FACTOR |
float | нет | 0.2 | Коэффициент величины дополнительной случайной задержки(jitter) относительно основной задержки: 0.0 - без случайной задержки, 1.0 - до 100% задержки. Если после умножения задержки на UI_STORAGE_KAFKA_CONSUMER_RESTART_RANDOM_FACTOR получится меньше 1 миллисекунды, то jitter будет приравнен к нулю. |
UI_STORAGE_KAFKA_CONSUMER_RESTART_MAX_RESTARTS |
int | нет | 5 | Максимальное количество перезапусков в заданный период времени. После превышения этого числа сервис будет объявлен больным. Все рестарты для каждого отдельного сообщения увеличивают и общий счетчик рестартов консьюмера, поэтому при использовании UI_STORAGE_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS нужно указывать UI_STORAGE_KAFKA_CONSUMER_RESTART_MAX_RESTARTS > UI_STORAGE_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS или не указывать UI_STORAGE_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS совсем. |
UI_STORAGE_KAFKA_CONSUMER_PER_MESSAGE_RESTART_MAX_RESTARTS |
int | нет | 2 | Максимальное количество раз, которое консьюмер перезапустится с неизменной очередью сообщений(в пределах DATA_MODEL_KAFKA_CONSUMER_RESTART_MAX_RESTARTS_WITHIN), прежде чем проигнорировать сообщение, на котором происходит ошибка (Указано количество рестартов, а не прочтений. Если UI_STORAGE_KAFKA_CONSUMER_RESTART_MAX_RESTARTS = 2, то ошибочное сообщение будет обработано 3 раза, после чего произойдет 3ий рестарт и оно будет проигнорировано). Если указать 0, то перезапуск произойдет, но сообщение будет обработано только в первый раз, когда произошла ошибка. Если указать значение меньше 0, то перезапуски все равно будут происходить, но игнорирование сообщений, вызывающих ошибку, будет отключено. |
UI_STORAGE_KAFKA_CONSUMER_PER_MESSAGE_RESTART_CACHE_SIZE |
int | нет | 100 | Для каждого сообщения счетчик перепрочтений хранится в кэше. Максимальное количество значений в этом кэше. |
UI_STORAGE_KAFKA_CONSUMER_PER_MESSAGE_RESTART_CACHE_TTL |
duration string | нет | 5 minutes | Для каждого сообщения счетчик перепрочтений хранится в кэше.Максимальное время жизни элемента в этом кэше. В случае отсутствия значения время жизни элемента не будет ограничено. |
UI_STORAGE_KAFKA_CONSUMER_RESTART_MAX_RESTARTS_WITHIN |
duration string | нет | 5 minutes | Период времени для ограничения перезапусков. |
UI_STORAGE_KAFKA_CONSUMER_POLL_TIMEOUT |
duration string | нет | 10 milliseconds | timeout запроса poll для kafka consumer |
UI_STORAGE_KAFKA_CONSUMER_POLL_INTERVAL |
duration string | нет | 100 milliseconds | интервал между запросами poll для kafka consumer |
UI_STORAGE_KAFKA_CONSUMER_PROPS |
string | нет | "max.poll.records=500;max.partition.fetch.bytes=524288" | дополнительные параметры для kafka consumer в формате "key1=value1;key2=value2" |
UI_STORAGE_KAFKA_AUTH_USER |
string | нет | "" | Название учетной записи Kafka. Если название не указано, то настройки авторизации не будут применены. |
UI_STORAGE_KAFKA_AUTH_PASSWORD |
string | нет | "" | Пароль учетной записи Kafka. |
UI_STORAGE_KAFKA_AUTH_PRINCIPAL |
string | нет | "" | Principal учетной записи Kafka в Kerberos(в случае соединения с kafka через Kerberos). |
UI_STORAGE_KAFKA_AUTH_KEYTAB_PATH |
string | нет | "" | Путь до keytab-файла(в случае соединения с kafka через Kerberos). |
UI_STORAGE_KAFKA_AUTH_TRUSTSTORE_LOCATION |
string | нет | "" | Путь до хранилища сертификатов (Java key store). Если путь не указан, то сертификат применяться не будет. |
UI_STORAGE_KAFKA_AUTH_TRUSTSTORE_PASSWORD |
string | нет | "" | Пароль к хранилищу сертификатов. |
UI_STORAGE_KAFKA_AUTH_MODE |
string | нет | "static" | Режим аутентификации: static - одна учетная запись на все запросы, mapping - учетная запись зависит от запроса |
UI_STORAGE_KAFKA_AUTH_CONFIG |
string | нет | "" | Настройки для аутентификации: если AuthMode = mapping, то необходим JSON с List[KafkaAuthConfig]. Переменная соответствует полю authConfig из KafkaAuthSettings. |
UI_STORAGE_KAFKA_AUTH_CACHE_SIZE |
int | нет | Максимальный размер кеша для Kafka producer (количество активных соединений). | |
UI_STORAGE_KAFKA_AUTH_CACHE_TTL |
duration string | нет | Время жизни Kafka producer в кеше. | |
UI_STORAGE_KAFKA_CONNECTION_CHECK_TEST_MESSAGES_INTERVAL |
duration string | нет | 4 minutes | Применяется только для producer-ов со способом аутентификации kerberos. Интервал отправки тестовых сообщений кафки в топик connectionCheck.testMessagesTopicName. Тестовые сообщения (null, service producer test) отправляются регулярно с этим интервалом. |
UI_STORAGE_KAFKA_CONNECTION_CHECK_INTERVAL |
duration string | нет | 60 seconds | Применяется только для producer-ов со способом аутентификации kerberos. Интервал проверки того, сколько тестовых сообщений было отправлено за данный период. Если количество сообщений за этот период равно количеству сообщений за прошлый период, то начинается отсчет периода без сообщений. |
UI_STORAGE_KAFKA_CONNECTION_CHECK_FAILED_AFTER_INTERVAL |
duration string | нет | 5 minutes | Применяется только для producer-ов со способом аутентификации kerberos. Максимальная продолжительность периода без успешно отправленных тестовых сообщений. По ее достижении сервис будет объявлен больным. |
UI_STORAGE_CONSUL_ADDR |
string | нет | "http://localhost:8500" | Адрес Сonsul |
UI_STORAGE_TRACE_DURATION |
bool | нет | false | Признак необходимости трассировки выполнения команд |
UI_STORAGE_DISCOVERABLE_ID |
string | нет | "ui_storage_instance" | Id сервиса в ServiceDiscovery |
UI_STORAGE_DISCOVERABLE_NAME |
string | нет | "UIStorage" | Имя сервиса в ServiceDiscovery |
UI_STORAGE_DISCOVERABLE_HOST |
string | нет | "localhost" | Хост, публикуемый в ServiceDiscovery |
UI_STORAGE_DISCOVERABLE_PORT |
int | нет | Порт, публикуемый в ServiceDiscovery | |
UI_STORAGE_DISCOVERABLE_LIVETIME |
duration string | нет | 2 minutes | Период после отправки health check, в течение которого ServiceDiscovery считает сервис живым |
UI_STORAGE_DISCOVERABLE_HEALTHPASS |
duration string | нет | 1 minute | Периодичность отправки health check в ServiceDiscovery |
UI_STORAGE_AKKA_HTTP_CLIENT_MAXCON |
int | нет | 512 | Максимальное число одновременных исходящих HTTP-соединений |
UI_STORAGE_AKKA_HTTP_CLIENT_MAXREQ |
int | нет | 1024 | Максимальное число одновременных исходящих HTTP-запросов |
UI_STORAGE_AKKA_HTTP_SERVER_MAXCON |
int | нет | 1024 | Максимальное число одновременных входящих HTTP-соединений |
UI_STORAGE_INTERNALCMD_ALLOW |
bool | нет | false | Можно ли сервису отправлять внутрисистемные команды |
UI_STORAGE_SENDERLIB_CONSIDER_ALL_COMMANDS_AS_INTERNAL |
boolean | Нет | false | Флаг, определяющий будут ли все обращения в другие сервисы являться внутренними (т.е. не требовать авторизацию). Детальное описание механизма: Внутренние команды. |
UI_STORAGE_SENDERLIB_COMMANDS_CACHE_UPDATEPERIOD |
duration string | нет | 10 minutes | Время кэширования данных по командам из CommandDiscovery |
UI_STORAGE_SENDERLIB_SERVICES_CACHE_UPDATEPERIOD |
duration string | нет | 30 seconds | Время кэширования данных по сервисам из ServiceDiscovery |
UI_STORAGE_DB_URL |
string | если не указаны DB_HOST, DB_PORT и DB_NAME | Адрес базы данных. Можно использовать вместо DB_HOST, DB_PORT и DB_NAME | |
UI_STORAGE_DB_HOST |
string | если не указана DB_URL | Хост сервера базы данных | |
UI_STORAGE_DB_PORT |
int | если не указана DB_URL | Порт сервера базы данных | |
UI_STORAGE_DB_NAME |
string | если не указана DB_URL | Название базы данных | |
UI_STORAGE_DB_USER |
string | да | Пользователь базы данных | |
UI_STORAGE_DB_PASSWORD |
string | да | Пароль для пользователя базы данных | |
UI_STORAGE_DB_THREADS |
int | нет | 10 | Количество потоков в пуле потоков для соединения с БД |
UI_STORAGE_DB_QUEUE_SIZE |
int | нет | 300 | Размер очереди для действий базы данных, которые не могут быть выполнены немедленно, когда все потоки заняты. За пределами этого значения новые действия немедленно завершаются неудачей |
UI_STORAGE_DB_CONN_MAX |
int | нет | 10 | Максимальное количество одновременных подключений к БД |
UI_STORAGE_DB_CONN_TIMEOUT |
duration string | нет | 20 second | Максимальное время ожидания ответа для соединения к БД. Если это время превышено, а соединение не становится доступным, будет брошено исключение SQLException. 1000 мс — минимальное значение. |
UI_STORAGE_DB_ISOLATION |
string | нет | "READ_COMMITTED" | Уровень изоляции транзакций для новых подключений. Допустимые значения: NONE, READ_COMMITTED, READ_UNCOMMITTED, REPEATABLE_READ, SERIALIZABLE. |
UI_STORAGE_DB_READONLY |
boolean | нет | false | Read-only SQL транзакция может изменять только временные таблицы. Этот параметр управляет статусом «только для чтения» по умолчанию для каждой новой транзакции. |
UI_STORAGE_DB_CONN_MIN |
int | нет | = DB_THREADS | Минимальное количество одновременных подключений к БД |
UI_STORAGE_DB_VALIDATION_TIMEOUT |
duration string | нет | 1 seconds | Максимальное время, в течение которого соединение будет проверяться на работоспособность. 1000 мс — минимальное значение. |
UI_STORAGE_DB_IDLE_TIMEOUT |
duration string | нет | 10 minutes | Максимальное время, в течение которого соединению разрешено простаивать в пуле. Значение 0 означает, что простаивающие соединения никогда не удаляются из пула. |
UI_STORAGE_DB_MAX_LIFETIME |
duration string | нет | 30 minutes | Максимальное время жизни соединения в пуле. Когда простаивающее соединение достигает этого времени ожидания, даже если оно недавно использовалось, оно будет удалено из пула. Значение 0 указывает на отсутствие максимального срока службы. |
UI_STORAGE_DB_INITIALIZATION_FAIL_FAST |
string | нет | false | Deprecated, начиная с версии Slick 3.3.0. Определяет, будет ли пул «быстро выходить из строя», если пул не может быть успешно заполнен начальными соединениями. Если соединения не могут быть созданы во время запуска пула, будет выдано исключение RuntimeException. Это свойство не имеет никакого эффекта, если minConnections равно 0. |
UI_STORAGE_DB_LEAK_DETECTION_THRESHOLD |
int | нет | 0 | Время, в течение которого соединение может находиться вне пула, прежде чем будет зарегистрировано сообщение, указывающее на возможную утечку соединения. Значение 0 означает, что обнаружение утечек отключено. Наименьшее приемлемое значение для включения обнаружения утечек составляет 10 с. |
UI_STORAGE_DB_CONNECTION_TEST_QUERY |
string | нет | "SELECT 1" | Выражение, которое будет выполнено непосредственно перед получением соединения из пула для проверки того, что соединение с базой данных все еще активно. Оно зависит от базы данных и должно представлять собой запрос, требующий минимальной обработки базой данных (например, «VALUES 1»). Если этот параметр не установлен, вместо него используется метод JDBC4 Connection.isValid(). |
UI_STORAGE_DB_AUTO_COMMIT |
boolean | нет | true | Это свойство определяет то, как будут вести себя по умолчанию возвращаемые соединения относительно autocommit-а. |
UI_STORAGE_DB_SCHEMA |
string | нет | "public" | Устанавливает schema по умолчанию |
UI_STORAGE_DB_ISOLATE_INTERNAL_QUERIES |
boolean | нет | false | Определяет то, изолируются ли с помощью транзакций внутренние запросы пула(например запрос connection alive test). Свойство применяется только если autoCommit выключен. |
UI_STORAGE_DB_INITIALIZATION_FAIL_TIMEOUT |
int | нет | 1 | Работает, начиная с версии Slick 3.3.0. Определяет, будет ли пул «быстро выходить из строя», если пул не может быть успешно заполнен начальными соединениями. Любое положительное число считается числом миллисекунд для попытки получить начальное соединение;поток приложения будет заблокирован в течение этого периода. Если соединение не может быть получено до истечения этого времени,будет брошено исключение. Данный таймаут применяется после периода connectionTimeout. Если значение равно нулю (0),HikariCP попытается получить и проверить подключение. Если соединение получено,но проверка не пройдена, будет брошено исключение, и пул не будет запущен. Однако,если соединение не может быть получено, пул запустится,но последующие попытки получить соединение могут потерпеть неудачу.Значение меньше нуля пройдет любую первоначальную попытку подключения, и пул немедленно запустится,пытаясь получить соединения в фоновом режиме.Следовательно, последующие попытки получить соединение могут потерпеть неудачу. |
UI_STORAGE_DB_REGISTER_MBEANS |
boolean | нет | false | Зарегистрированы ли JMX Management Beans («MBeans») |
UI_STORAGE_FS_URI |
string | нет | "http://localhost:9000" | Адрес файлового хранилища |
UI_STORAGE_FS_ACCESS_KEY_ID |
string | нет | "minioadmin" | Идентификатор пользователя файлового хранилища |
UI_STORAGE_FS_SECRET_ACCESS_KEY |
string | нет | "minioadmin" | Пароль для пользователя файлового хранилища |
UI_STORAGE_FS_UPLOAD_PARALLELISM |
int | нет | 4 | Параллелизм для загрузки файлов |
UI_STORAGE_FS_AUTH_MODE |
string | нет | "static" | Режим аутентификации: static - одна учетная запись на все запросы, mapping - учетная запись зависит от запроса |
UI_STORAGE_FS_AUTH_CONFIG |
string | нет | "" | Настройки для аутентификации: если AuthMode = mapping, то необходим JSON с List[FSBucketConfig] соответствует полю authConfig FSConfigRep |
UI_STORAGE_FS_CACHE_SIZE |
int | нет | 1 | Максимальный размер кеша клиентов для хранилища файлов (количество активных соединений). |
UI_STORAGE_FS_CACHE_TTL |
duration string | нет | Время жизни клиента в кеше | |
UI_STORAGE_FS_RETRY_ATTEMPTS |
int | нет | 5 | Количество ретраев, которое будет произведено в случае Exception-а в операции FSClient-а и при вычитывании стрима в get операциях FSClient-а. |
UI_STORAGE_FS_RETRY_DELAY |
duration string | нет | 10 millis | Задержка между ретраями операций FSClient-а. |
UI_STORAGE_FS_BUCKET_TEMP |
string | нет | "temp" | Название бакета для временных файлов |
UI_STORAGE_FS_BUCKET_PERMANENT |
string | нет | "uisettings" | Название бакета для постоянных файлов |
UI_STORAGE_FS_ZIO_SHORT_MESSAGE_MODE |
boolean | нет | false | Флаг включения режима сохранения ошибок работы с файловым хранилищем в сервисе журналирования nestor. При включении режима ошибки в логах будут отображаться в сокращенном формате: Short zio message mode. ExceptionType: ТИП ОШИБКИ, Exception id: 'СГЕНЕРИРОВАННЫЙ UUID' added to journal. Указанный id будет фиксироваться в event записи nestor'а в поле data.id |
UI_STORAGE_AUTHZFORCE_ADDR |
string | нет | "http://localhost:8080/authzforce-ce" | Адрес сервиса authzforce |
UI_STORAGE_AUTHZFORCE_DOMAIN |
string | нет | "not defined" | Доступный DomainID в Authzforce server |
UI_STORAGE_AUTHORIZER_KIND |
string | нет | "authzforce" | Вид авторизатора, который используется в сервисе. Допустимые значения: "authzforce", "oberto". При указании неизвестного значения будет использовано значение по-умолчанию. |
UI_STORAGE_SENDERLIB_COMMANDS_HTTP_RETRY_ATTEMPTS |
int | нет | 5 | Поле attempts из RetrySettings |
UI_STORAGE_SENDERLIB_COMMANDS_HTTP_RETRY_DELAY |
duration string | нет | "5 seconds" | Поле delay из RetrySettings |
UI_STORAGE_SENDERLIB_COMMANDS_HTTP_RETRY_KIND |
string | нет | "OnSomeExceptions(ConnectException)" | CommandResultRetryConditionKind |
UI_STORAGE_SENDERLIB_CONSUL_CONNECTION_RETRY_MAX |
int | нет | 5 | Количество попыток переподключения к Consul |
UI_STORAGE_SENDERLIB_CONSUL_CONNECTION_RETRY_DELAY |
duration string | нет | "1 second" | Задержка при попытках переподключения к Consul |
UI_STORAGE_ADDITIONAL_FORM_TYPES |
string | нет | "" | Строка со списком дополнительных FormType, которые будут добавлены в БД при старте приложения, в формате "code1,title1;code2,title2,description2". Каждый добавляемый FormType описывается подстрокой вида "<значение поля code>,<значение поля title>[,<значение поля description>]". Значение поля description при этом указывается опционально. Подстроки с описанием FormType отделяются друг от друга ";". |
UI_STORAGE_ADDITIONAL_FORM_TYPES_MODE |
string | нет | "add" | Режим добавления дополнительных FormType, которые будут добавлены в БД при старте приложения. Есть два валидных значения: "add" - если при добавлении у двух FormType совпадает поле code, но отличаются другие поля, то сервис падает на старте с ошибкой; "override" - если при добавлении у двух FormType совпадает поле code, но отличаются другие поля, то FormType-ы из переменной перезапишут FormType-ы из БД. Если конфликты будут внутри самой переменной, то сервис упадет на старте в любом из режимов. |
UI_STORAGE_JOURNAL_MODE |
string | нет | WriteToJournal |
Режим журналирования Nestor. Допустимые значения: WriteToJournal (Отправка в сервис журналирования), WriteToTopic (Отправка события в очередь) |
UI_STORAGE_JOURNAL_TOPIC |
string | да, если переменная UI_STORAGE_JOURNAL_MODE = WriteToTopic |
"" | Название очереди журналирования. Для режима WriteToJournal значение игнорируется. |
Команды сервиса хранения UI
Список реализованных в сервисе команд, моделей EntityType и действий Actions, которые можно использовать при настройке
авторизации.
Не все поля EntityType доступны для использования в настройке авторизации.
| Название команды | EntityType | Actions |
|---|---|---|
| ListFormTypes | FormType | UIStorage_ViewList |
| CreateForm | - | - |
| GetForm | EntityFormSettings | UIStorage_View |
| DeleteForm | - | - |
| UpdateForm | - | - |
| ListForms | EntityFormSettingsDTO | UIStorage_ViewList |
| ListFormsV2 | EntityFormSettingsFullDTO | UIStorage_ViewList |
| GetEntityForm | EntityFormSettings | UIStorage_View |
| GetFormsByType | EntityFormSettings | UIStorage_ViewList |
| ListKeys | GlobalSetting | UIStorage_ViewList |
| GetValue | GlobalSetting | UIStorage_View |
| CreateKey | GlobalSetting | UIStorage_CRUD |
| UpdateKey | GlobalSetting | UIStorage_CRUD |
| UpdateValue | GlobalSetting | UIStorage_UpdateValue |
| DeleteKey | GlobalSetting | UIStorage_CRUD |
| PersistFile | GlobalSetting | UIStorage_UpdateValue |
Доступные для авторизации поля моделей сервиса хранения UI
EntityFormSettings (AuthzDTO, UI Storage)
| Поле | Тип | Actions | Описание |
|---|---|---|---|
| id | EntityFormSettingsId | UIStorage_View, UIStorage_ViewList | ID формы |
| entityType | String | UIStorage_View, UIStorage_ViewList | Тип сущности (127 символов) |
| formData | Json | UIStorage_ViewList | Данные формы |
| formType | FormTypeCode | UIStorage_View | Code типа формы |
EntityFormSettingsDTO (AuthzDTO, UI Storage)
| Поле | Тип | Actions | Описание |
|---|---|---|---|
| id | EntityFormSettingsId | UIStorage_View, UIStorage_ViewList | ID формы |
| entityType | String | UIStorage_View, UIStorage_ViewList | Тип сущности |
| formType | FormType | UIStorage_View, UIStorage_ViewList | Тип формы |
FormType (AuthzDTO, UI Storage)
| Поле | Тип | Actions | Описание |
|---|---|---|---|
| code | FormTypeCode | UIStorage_View, UIStorage_ViewList | Код типа формы |
| title | String | UIStorage_View, UIStorage_ViewList | Заголовок типа формы |
GlobalSettings (AuthzDTO, UI Storage)
| Поле | Тип | Actions | Описание |
|---|---|---|---|
| key | GlobalSettingKey | UIStorage_View, UIStorage_ViewList, UIStorage_CRUD, UIStorage_UpdateValue | Ключ для идентификации настроек |
| title | String | UIStorage_ViewList | Название настроек |
| value | Json | UIStorage_ViewList | Данные описывающие настройки |
ListFormTypes (UI Storage)
Получаем JSON со списком всех существующих типов форм
[
{
"code": "card",
"title": "Карточка объекта",
"description": "Карточка объекта"
},
{
"code": "createForm",
"title": "Форма создания",
"description": "Форма создания"
}
]
Возвращает список всех существующих типов форм.
Имя команды для вызова: UIStorage_http_ListFormTypes.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: Команда не принимает параметров
- На выходе: List[FormType]
CreateForm (UI Storage)
Передаем JSON с данными формы
{
"entityType": "document",
"formType": "card",
"formData": {
"field1": "value1"
}
}
Получаем Id формы
"0ccd05ac-50c0-4e7e-906b-6893eaa8d9de"
Создать новую форму из данных EntityFormSettingsCreateDTO.
Гарантируется уникальность для набора полей: entityType, formType.
Имя команды для вызова: UIStorage_kafka_CreateForm.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
- На входе: EntityFormSettingsCreateDTO
- На выходе: EntityFormSettingsId
GetForm (UI Storage)
Передаем Id формы
"63680617-1cda-40db-bd99-303fbfcbb736"
Получаем JSON с данными формы
{
"id": "63680617-1cda-40db-bd99-303fbfcbb736",
"entityType": "organization",
"formType": "card",
"formData": {
"field1": "value1"
},
"version": 1
}
Возвращает форму EntityFormSettings по её Id.
Имя команды для вызова: UIStorage_http_GetForm.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: EntityFormSettingsId
- На выходе: EntityFormSettings
DeleteForm (UI Storage)
Передаем Id формы
"0ccd05ac-50c0-4e7e-906b-6893eaa8d9de"
Получаем результат
1
Удалить существующую форму по её Id.
Имя команды для вызова: UIStorage_kafka_DeleteForm.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
- На входе: EntityFormSettingsId
- На выходе: Int (1 - в случае успеха, 0 - при неудаче)
UpdateForm (UI Storage)
Передаем JSON данные для обновления
{
"id": "0ccd05ac-50c0-4e7e-906b-6893eaa8d9de",
"formData": {
"field1": "newValue"
},
"version": "1"
}
Получаем результат
1
Обновить существующую форму данными из EntityFormSettingsForUpdate. При
успешном обновлении version формы увеличивается на единицу.
Имя команды для вызова: UIStorage_kafka_UpdateForm.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
- На входе: EntityFormSettingsForUpdate
- На выходе: Int (1 - в случае успеха, 0 - при неудаче)
ListForms (UI Storage)
Получаем JSON со списком всех форм с типом
[
{
"id": "b13971a2-5d00-4455-bd48-4e4256157353",
"entityType": "document",
"formType": {
"code": "card",
"title": "Карточка объекта",
"description": "Карточка объекта"
},
"version": 1
},
{
"id": "fd460be0-99f6-4cfc-95eb-2e3f6a847efe",
"entityType": "employee",
"formType": {
"code": "list",
"title": "Список",
"description": "Список"
},
"version": 1
}
]
Возвращает список всех форм с типом, отсортированный по entityType.
Имя команды для вызова: UIStorage_http_ListForms.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: Команда не принимает параметров
- На выходе: List[EntityFormSettingsDTO]
ListFormsV2 (UI Storage)
Передаем параметры поиска
{
"query": "",
"context": {}
}
Получаем JSON со списком форм с типом и с данными
{
"items": [
{
"id": "b13971a2-5d00-4455-bd48-4e4256157353",
"entityType": "document",
"formType": {
"code": "card",
"title": "Карточка объекта",
"description": "Карточка объекта"
},
"formData": {
"key": "value"
},
"version": 1
},
{
"id": "fd460be0-99f6-4cfc-95eb-2e3f6a847efe",
"entityType": "employee",
"formType": {
"code": "list",
"title": "Список",
"description": "Список"
},
"formData": {
"key": "value"
},
"version": 1
}
],
"total": 10
}
Возвращает пагинированный список всех форм с типом и с данными. Пагинация по-умолчанию не производится.
Сортировка и фильтрация применяется к полям модели EntityFormSettingsFullDTO.
Доступные поля для фильтрации и виды фильтров по ним:
| Поле | Виды фильтров |
|---|---|
| id | InSetQuery, LikeQuery |
| entityType | InSetQuery, LikeQuery |
| formType.code | InSetQuery, LikeQuery |
| formType.title | InSetQuery, LikeQuery, TsQuery |
| formType.description | InSetQuery, LikeQuery, TsQuery |
| version | InSetQuery, LikeQuery, RangeQuery |
| formData | InSetQuery, LikeQuery |
При фильтрации по formData можно указать путь до внутреннего json,
например formData.someObject.someValue
Доступные поля для сортировки:
| Поле |
|---|
| id |
| formType |
| version |
| formType.title |
| formType.description |
| entityType |
По умолчанию сортировка производится по полю entityType.
Имя команды для вызова: UIStorage_http_ListFormsV2.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: Search
- На выходе: Page[EntityFormSettingsFullDTO]
GetEntityForm (UI Storage)
Передаем JSON
{
"entityType": "document",
"formType": "card"
}
Получаем JSON с данными формы
{
"id": "5fe0c0fc-f79a-4a0f-b741-7717c03ad5ed",
"entityType": "document",
"formType": "card",
"formData": {
"field1": "value1"
},
"version": 1
}
Возвращает форму EntityFormSettings по коду типа объекта entityType
из EntityFormSettings и коду типа формы code из FormType из
справочника.
Имя команды для вызова: UIStorage_http_GetEntityForm.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: EntityTypeWithFormType
- На выходе: EntityFormSettings
GetFormsByType (UI Storage)
Передаем JSON со списком типов форм
[
"textSearchSnippet",
"card"
]
Получаем JSON со списком форм
[
{
"id": "bb02daf9-5386-471e-93c0-04344c74272c",
"entityType": "document",
"formType": "card",
"formData": {
"field1": "value1"
},
"version": 1
},
{
"id": "f755bbcd-7a67-4ad4-bcab-839323d54398",
"entityType": "organization",
"formType": "textSearchSnippet",
"formData": {
"field1": "value1"
},
"version": 1
}
]
Возвращает список форм на основе списка их типов. Если список типов форм пустой, то возвращается список всех форм.
Имя команды для вызова: UIStorage_http_GetFormsByType.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: List[String]
- На выходе: List[EntityFormSettings]
ListKeys (UI Storage)
Получаем список всех существующих глобальных настроек
[
{
"key": "logo",
"value": "<svg><circle cx=\"10\" cy=\"10\" r=\"10\"/></svg>",
"title": "Логотип",
"created": 1634644383273,
"modified": 1634644383273,
"lastUser": "d3f7d9c4-43aa-49ae-9d66-1d500f53cf3d",
"version": 1
},
{
"key": "color",
"value": "#fcbe03",
"title": "Цвет",
"created": 1634644887499,
"modified": 1634644887499,
"lastUser": "d3f7d9c4-43aa-49ae-9d66-1d500f53cf3d",
"version": 2
}
]
Возвращает список всех существующих глобальных настроек.
Имя команды для вызова: UIStorage_http_ListKeys.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: Команда не принимает параметров
- На выходе: List[GlobalSetting]
GetValue (UI Storage)
Передаем ключ глобальной настройки
"color"
Получаем значение глобальной настройки
"#fcbe03"
Возвращает JSON-значение глобальной настройки по ключу key.
Имя команды для вызова: UIStorage_http_GetValue.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: GlobalSettingKey
- На выходе: Json
CreateKey (UI Storage)
Передаем данные глобальной настройки
{
"key": "color",
"value": "#fcbe03",
"title": "Цвет"
}
Получаем признак успешности
true
Создать новую глобальную настройку из данных CreateKeyDTO.
Гарантируется уникальность для поля key.
Имя команды для вызова: UIStorage_kafka_CreateKey.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
- На входе: CreateKeyDTO
- На выходе: Boolean (приходит признак успешности выполнения команды)
UpdateKey (UI Storage)
Передаем данные глобальной настройки для обновления
{
"key": "color",
"value": "#fcbe04",
"title": "Цвет фона",
"version": 1
}
Получаем признак успешности
true
Обновить существующую глобальную настройку данными из UpdateKeyDTO.
При успешном обновлении version настройки увеличивается на единицу.
Имя команды для вызова: UIStorage_kafka_UpdateKey.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
- На входе: UpdateKeyDTO
- На выходе: Boolean
UpdateValue (UI Storage)
Передаем данные глобальной настройки для обновления
{
"key": "color",
"value": "#fcbe05",
"version": 1
}
Получаем признак успешности
true
Обновить значение существующей глобальной настройки из UpdateValueDTO.
При успешном обновлении version настройки увеличивается на единицу.
Имя команды для вызова: UIStorage_kafka_UpdateValue.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
- На входе: UpdateValueDTO
- На выходе: Boolean
DeleteKey (UI Storage)
Передаем ключ глобальной настройки
"color"
Получаем признак успешности
true
Удалить существующую глобальную настройку по её ключу key.
Имя команды для вызова: UIStorage_kafka_DeleteKey.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды журналируется.
- На входе: GlobalSettingKey
- На выходе: Boolean
PersistFile (UI Storage)
Передаем список файлов и связанных ключей глобальных настроек
[
{
"path": "logo/background",
"tempFileId": "ec476b5d-7cea-4138-b537-8f3032f33ac4"
},
{
"path": "theme-color",
"tempFileId": "f0e1f19a-c386-48aa-874f-d58ff9a147e3"
}
]
Получаем список url для сохраненных файлов
[
{
"path": "logo/background",
"fileUrl": "uisettings/logo/background/ec476b5d-7cea-4138-b537-8f3032f33ac4"
},
{
"path": "theme-color",
"fileUrl": "uisettings/theme-color/f0e1f19a-c386-48aa-874f-d58ff9a147e3"
}
]
Сохранить файлы для указанных глобальных настроек по пути path.
Имя команды для вызова: UIStorage_kafka_PersistFile.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: List[PersistFileDTO]
- На выходе: List[GlobalSettingFile]
Модели сервиса хранения UI
В сервисе использованы следующие модели:
- FormTypeId
- FormType
- EntityFormSettingsId
- EntityFormSettingsCreateDTO
- EntityFormSettings
- EntityFormSettingsForUpdate
- EntityTypeWithFormType
- EntityFormSettingsDTO
- FormTypeDTO
- GlobalSettingKey
- GlobalSetting
- CreateKeyDTO
- UpdateKeyDTO
- UpdateValueDTO
- PersistFileDTO
- GlobalSettingFile
FormTypeCode (UI Storage)
Соответствует типу String.
FormType (UI Storage)
Описание типа форм.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| code | FormTypeCode | Да | Код типа формы |
| title | String | Да | Заголовок типа формы |
| description | String | Нет | Описание типа формы |
Встроенный справочник:
| code | title | description |
|---|---|---|
| card | Карточка объекта | Карточка объекта |
| createForm | Форма создания | Форма создания |
| editForm | Форма редактирования | Форма редактирования |
| list | Список | Элемент списка в реестре объектов |
| filterPanel | Панель фильтров | Панель фильтров |
EntityFormSettingsId (UI Storage)
Соответствует типу UUID.
EntityFormSettingsCreateDTO (UI Storage)
Модель для создания формы.
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
| entityType | EntityTypeId | Да | Тип сущности | - Не пустое - Не длиннее 127 символов |
| formType | FormTypeCode | Да | Код типа формы | - Уникальное - Не длиннее 127 символов |
| formData | Json | Да | Данные формы |
EntityFormSettings (UI Storage)
Модель формы.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | EntityFormSettingsId | Да | ID формы |
| entityType | EntityTypeId | Да | Тип сущности |
| formType | FormTypeCode | Да | Код типа формы |
| formData | Json | Да | Данные формы |
| version | Int | Да | Версия |
EntityFormSettingsForUpdate (UI Storage)
Модель для обновления формы.
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
| id | EntityFormSettingsId | Да | ID формы | |
| formData | Json | Да | Данные формы | |
| version | Int | Да | Версия |
EntityTypeWithFormType (UI Storage)
Идентификатор конкретной формы конкретного типа объектов.
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
| entityType | EntityTypeId | Да | Код типа объекта | |
| formType | FormTypeCode | Да | Код типа формы |
EntityFormSettingsDTO (UI Storage)
Сокращенная модель формы (используется для списков).
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | EntityFormSettingsId | Да | ID формы |
| entityType | EntityTypeId | Да | Тип сущности |
| formType | FormType | Да | Тип формы |
| version | Int | Да | Версия |
EntityFormSettingsFullDTO (UI Storage)
Развернутая модель формы с информацией о типе
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | EntityFormSettingsId | Да | ID формы |
| entityType | EntityTypeId | Да | Тип сущности |
| formType | FormType | Да | Тип формы |
| formData | Json | Да | Данные формы |
| version | Int | Да | Версия |
GlobalSettingKey (UI Storage)
Соответствует типу String.
GlobalSetting (UI Storage)
Модель глобальной настройки.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| key | GlobalSettingKey | Да | Ключ глобальной настройки |
| value | Json | Да | Значение глобальной настройки |
| title | String | Да | Название глобальной настройки |
| created | TimeStamp | Да | Дата создания |
| modified | TimeStamp | Да | Дата обновления |
| lastUser | UUID | Нет | Пользователь, выполнивший последнее обновление |
| version | Int | Да | Версия (optimistic lock) |
CreateKeyDTO (UI Storage)
Модель для создания глобальной настройки.
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
| key | GlobalSettingKey | Да | Ключ глобальной настройки | - Не пустое - Не длиннее 64 символов |
| value | Json | Да | Значение глобальной настройки | |
| title | String | Да | Название глобальной настройки | Не длиннее 127 символов |
UpdateKeyDTO (UI Storage)
Модель для обновления ключа глобальной настройки.
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
| key | GlobalSettingKey | Да | Ключ глобальной настройки | - Не пустое - Не длиннее 64 символов |
| value | Json | Да | Значение глобальной настройки | |
| title | String | Да | Название глобальной настройки | Не длиннее 127 символов |
| version | Int | Да | Версия (optimistic lock) |
UpdateValueDTO (UI Storage)
Модель для обновления значения глобальной настройки.
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
| key | GlobalSettingKey | Да | Ключ глобальной настройки | - Не пустое - Не длиннее 64 символов |
| value | Json | Да | Значение глобальной настройки | |
| version | Int | Да | Версия (optimistic lock) |
PersistFileDTO (UI Storage)
Модель для сохранения файлов глобальной настройки.
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
| path | String | Да | Полный путь, по которому надо сохранить временный файл | - Не пустое - Не длиннее 64 символов |
| tempFileId | UUID | Да | ID временного файла |
GlobalSettingFile (UI Storage)
Файл глобальной настройки.
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| path | String | Да | Полный путь, по которому сохранен файл |
| fileUrl | String | Да | URL к сохраненному файлу |
User-profile: сервис профилей пользователей
Сервис профилей пользователей выступает в роли прокси к модели данных. Предоставляет более удобный интерфейс для работы конкретно с профилями пользователей, чем модель данных.
В сервисе реализованы следующие команды (все команды начинаются с префикса "userProfile_"):
- Создать секцию в профиле
- Удалить секцию в профиле
- Изменить секцию в профиле
- Получить список секций
- Добавить поле в секцию
- Удалить поле из секции
- Изменить поле в секции
- Список полей в секции
- Получить профиль пользователя
- Обновить поле в профиле пользователя
Также сервис слушает события из авторизации и создает профили при регистрации.
Конфигурирование сервиса профилей пользователей
Для работы сервису нужно стандартное окружение Verdi, а также сервис модели данных, работающий в этом окружении.
Список переменных окружения сервиса профилей пользователей
| Переменная | Тип | Обяза-тельная | Значение по умолчанию | Описание |
|---|---|---|---|---|
SERVER_PORT |
int | нет | 8080 | Порт сервера |
USER_PROFILE_CONSUMER_GROUP |
string | нет | user-profile-service | Имя consumer-группы для чтения из кафка-топика команд. Не должна меняться и не должна быть пустой, иначе сервис перечитает свои команды при перезапуске. |
USER_PROFILE_CONSUMER_TOPIC |
string | нет | user-profile-service-commands | Имя кафка-топика с командами для этого сервиса |
USER_PROFILE_COMMANDS_CONSUMER_PARALLELISM |
int | нет | 16 | Параллелизм при обработке команд |
USER_PROFILE_CONSUMER_POLL_TIMEOUT |
duration string | нет | 10 milliseconds | timeout запроса poll для kafka consumer |
USER_PROFILE_CONSUMER_POLL_INTERVAL |
duration string | нет | 100 milliseconds | интервал между запросами poll для kafka consumer |
USER_PROFILE_CONSUMER_PROPS |
string | нет | "max.poll.records=500;max.partition.fetch.bytes=524288" | дополнительные параметры для kafka consumer в формате "key1=value1;key2=value2" |
VERDI_CONSUL |
string | нет | http://localhost:8500 | Адрес сервера consul |
VERDI_CONSUL_AUTH_USER |
string | нет | нет | Название учетной записи Сonsul. Если название не указано, то настройки авторизации не будут применены. |
VERDI_CONSUL_AUTH_PASSWORD |
string | нет | нет | Пароль учетной записи Сonsul. |
VERDI_KAFKA_ADDRESS |
string | нет | localhost:9092 | Адрес брокера Kafka. |
VERDI_KAFKA_TOPIC |
string | нет | commandevents | Название кафка-топика для отправки сообщений со статусами выполняемых команд. ОБЯЗАТЕЛЬНО должно соответствовать названию этого топика в сервисе статуса команд. |
VERDI_KAFKA_AUTH_USER |
string | нет | нет | Название учетной записи Kafka. Если название не указано, то настройки авторизации не будут применены. |
VERDI_KAFKA_AUTH_PASSWORD |
string | нет | нет | Пароль учетной записи Kafka. |
VERDI_KAFKA_AUTH_TRUSTSTORE_LOCATION |
string | нет | нет | Путь до хранилища сертификатов (Java key store). Если путь не указан, то сертификат применяться не будет. |
VERDI_KAFKA_AUTH_TRUSTSTORE_PASSWORD |
string | нет | нет | Пароль к хранилищу сертификатов. |
VERDI_KAFKA_AUTH_MODE |
string | нет | "" | Режим аутентификации: static - одна учетная запись на все запросы, mapping - учетная запись зависит от запроса |
VERDI_KAFKA_AUTH_CONFIG |
string | нет | "" | Настройки для аутентификации: если AuthMode = mapping, то необходим JSON с List[KafkaAuthConfig]. Переменная соответствует полю authConfig из KafkaAuthSettings. |
VERDI_KAFKA_AUTH_PRINCIPAL |
string | нет | "" | Principal учетной записи Kafka в Kerberos(в случае соединения с kafka через Kerberos). |
VERDI_KAFKA_AUTH_KEYTAB_PATH |
string | нет | "" | Путь до keytab-файла(в случае соединения с kafka через Kerberos). |
VERDI_KAFKA_AUTH_CACHE_SIZE |
int | нет | Максимальный размер кеша для Kafka producer (количество активных соединений). | |
VERDI_KAFKA_AUTH_CACHE_TTL |
duration string | нет | Время жизни Kafka producer в кеше. | |
VERDI_KAFKA_CONNECTION_CHECK_TEST_MESSAGES_INTERVAL |
duration string | нет | 4 minutes | Применяется только для producer-ов со способом аутентификации kerberos. Интервал отправки тестовых сообщений кафки в топик connectionCheck.testMessagesTopicName. Тестовые сообщения (null, service producer test) отправляются регулярно с этим интервалом. |
VERDI_KAFKA_CONNECTION_CHECK_INTERVAL |
duration string | нет | 60 seconds | Применяется только для producer-ов со способом аутентификации kerberos. Интервал проверки того, сколько тестовых сообщений было отправлено за данный период. Если количество сообщений за этот период равно количеству сообщений за прошлый период, то начинается отсчет периода без сообщений. |
VERDI_KAFKA_CONNECTION_CHECK_FAILED_AFTER_INTERVAL |
duration string | нет | 5 minutes | Применяется только для producer-ов со способом аутентификации kerberos. Максимальная продолжительность периода без успешно отправленных тестовых сообщений. По ее достижении сервис будет объявлен больным. |
VERDI_HOST |
string | нет | localhost | Адрес service discovery для Verdi |
VERDI_TTL |
duration string |
нет | 30 seconds | Период после последней отправки health check, в течение которого ServiceDiscovery считает данный сервис живым. |
VERDI_HEALTH_CHECK |
duration string |
нет | 10 seconds | Периодичность отправки health check в ServiceDiscovery |
VERDI_COMMAND_STORAGE_UPDATE_PERIOD |
duration string |
нет | 1 minutes | Время кэширования данных по командам из CommandDiscovery |
VERDI_SERVICE_DISCOVERY_UPDATE_PERIOD |
duration string |
нет | 30 seconds | Время кэширования данных по сервисам из ServiceDiscovery |
VERDI_ALLOW_INTERNAL_COMMANDS |
bool | нет | true | Можно ли сервису отправлять внутрисистемные команды |
VERDI_CONSIDER_ALL_COMMANDS_AS_INTERNAL |
boolean | Нет | false | Флаг, определяющий будут ли все обращения в другие сервисы являться внутренними (т.е. не требовать авторизацию). Детальное описание механизма: Внутренние команды. |
VERDI_CONSUL_CONNECTION_MAX_RETRY |
int | нет | 5 | Максимальное количество попыток подключений к Consul |
VERDI_CONSUL_CONNECTION_RETRY_DELAY |
duration string |
нет | 1 seconds | Таймаут между неудачными попытками подключения к Consul |
VERDI_KAFKA_SYNC_POLLING_PERIOD |
duration string |
нет | 1 seconds | |
VERDI_KAFKA_SYNC_POLLING_TIMEOUT |
duration string |
нет | 1 seconds | |
VERDI_NON_BLOCKING_PARALLELISM |
int | нет | 2 | Количество потоков в асинхронном пуле для senderlib |
USER_PROFILE_DATA_MODEL_COMMANDS_PREFIX |
string | нет | commands/userProfile | Префикс по которому модель данных принимает команды |
USER_PROFILE_USER_EVENTS_TOPIC |
string | нет | userEvents | Топик с событиями из авторизации о регистрации пользователей |
USER_PROFILE_USER_EVENTS_HANDLING_PARALLELISM |
int | нет | 16 | Параллелизм при обработке событий о регистрациях пользователей |
USER_PROFILE_DB_JDBC_URL |
string | нет | jdbc:postgresql://127.0.0.1:5432/userprofile | Адрес Postgres |
USER_PROFILE_DB_USER |
string | нет | postgres | Имя пользователя в базе данных |
USER_PROFILE_DB_PASSWORD |
string | нет | postgres | Пароль к базе данных |
USER_PROFILE_DB_THREADS |
int | нет | 10 | Количество потоков в пуле потоков для соединения с БД |
USER_PROFILE_DB_QUEUE_SIZE |
int | нет | 300 | Размер очереди для действий базы данных, которые не могут быть выполнены немедленно, когда все потоки заняты. За пределами этого значения новые действия немедленно завершаются неудачей |
USER_PROFILE_DB_CONN_MAX |
int | нет | 10 | Максимальное количество одновременных подключений к БД |
USER_PROFILE_DB_CONN_TIMEOUT |
duration string | нет | 20 second | Максимальное время ожидания ответа для соединения к БД. Если это время превышено, а соединение не становится доступным, будет брошено исключение SQLException. 1000 мс — минимальное значение. |
USER_PROFILE_DB_ISOLATION |
string | нет | "READ_COMMITTED" | Уровень изоляции транзакций для новых подключений. Допустимые значения: NONE, READ_COMMITTED, READ_UNCOMMITTED, REPEATABLE_READ, SERIALIZABLE. |
USER_PROFILE_DB_READONLY |
boolean | нет | false | Read-only SQL транзакция может изменять только временные таблицы. Этот параметр управляет статусом «только для чтения» по умолчанию для каждой новой транзакции. |
USER_PROFILE_DB_CONN_MIN |
int | нет | = DB_THREADS | Минимальное количество одновременных подключений к БД |
USER_PROFILE_DB_VALIDATION_TIMEOUT |
duration string | нет | 1 seconds | Максимальное время, в течение которого соединение будет проверяться на работоспособность. 1000 мс — минимальное значение. |
USER_PROFILE_DB_IDLE_TIMEOUT |
duration string | нет | 10 minutes | Максимальное время, в течение которого соединению разрешено простаивать в пуле. Значение 0 означает, что простаивающие соединения никогда не удаляются из пула. |
USER_PROFILE_DB_MAX_LIFETIME |
duration string | нет | 30 minutes | Максимальное время жизни соединения в пуле. Когда простаивающее соединение достигает этого времени ожидания, даже если оно недавно использовалось, оно будет удалено из пула. Значение 0 указывает на отсутствие максимального срока службы. |
USER_PROFILE_DB_INITIALIZATION_FAIL_FAST |
string | нет | false | Deprecated, начиная с версии Slick 3.3.0. Определяет, будет ли пул «быстро выходить из строя», если пул не может быть успешно заполнен начальными соединениями. Если соединения не могут быть созданы во время запуска пула, будет выдано исключение RuntimeException. Это свойство не имеет никакого эффекта, если minConnections равно 0. |
USER_PROFILE_DB_LEAK_DETECTION_THRESHOLD |
int | нет | 0 | Время, в течение которого соединение может находиться вне пула, прежде чем будет зарегистрировано сообщение, указывающее на возможную утечку соединения. Значение 0 означает, что обнаружение утечек отключено. Наименьшее приемлемое значение для включения обнаружения утечек составляет 10 с. |
USER_PROFILE_DB_CONNECTION_TEST_QUERY |
string | нет | "SELECT 1" | Выражение, которое будет выполнено непосредственно перед получением соединения из пула для проверки того, что соединение с базой данных все еще активно. Оно зависит от базы данных и должно представлять собой запрос, требующий минимальной обработки базой данных (например, «VALUES 1»). Если этот параметр не установлен, вместо него используется метод JDBC4 Connection.isValid(). |
USER_PROFILE_DB_AUTO_COMMIT |
boolean | нет | true | Это свойство определяет то, как будут вести себя по умолчанию возвращаемые соединения относительно autocommit-а. |
USER_PROFILE_DB_SCHEMA |
string | нет | "public" | Устанавливает schema по умолчанию |
USER_PROFILE_DB_ISOLATE_INTERNAL_QUERIES |
boolean | нет | false | Определяет то, изолируются ли с помощью транзакций внутренние запросы пула(например запрос connection alive test). Свойство применяется только если autoCommit выключен. |
USER_PROFILE_DB_INITIALIZATION_FAIL_TIMEOUT |
int | нет | 1 | Работает, начиная с версии Slick 3.3.0. Определяет, будет ли пул «быстро выходить из строя», если пул не может быть успешно заполнен начальными соединениями. Любое положительное число считается числом миллисекунд для попытки получить начальное соединение;поток приложения будет заблокирован в течение этого периода. Если соединение не может быть получено до истечения этого времени,будет брошено исключение. Данный таймаут применяется после периода connectionTimeout. Если значение равно нулю (0),HikariCP попытается получить и проверить подключение. Если соединение получено,но проверка не пройдена, будет брошено исключение, и пул не будет запущен. Однако,если соединение не может быть получено, пул запустится,но последующие попытки получить соединение могут потерпеть неудачу.Значение меньше нуля пройдет любую первоначальную попытку подключения, и пул немедленно запустится,пытаясь получить соединения в фоновом режиме.Следовательно, последующие попытки получить соединение могут потерпеть неудачу. |
USER_PROFILE_DB_REGISTER_MBEANS |
boolean | нет | false | Зарегистрированы ли JMX Management Beans («MBeans») |
VERDI_COMMANDS_HTTP_RETRY_ATTEMPTS |
int | нет | 5 | Поле attempts из RetrySettings |
VERDI_COMMANDS_HTTP_RETRY_DELAY |
duration string | нет | "5 seconds" | Поле delay из RetrySettings |
VERDI_COMMANDS_HTTP_RETRY_KIND |
string | нет | "OnSomeExceptions(ConnectException)" | CommandResultRetryConditionKind |
Команды сервиса профилей пользователей
createProfileSection (User-profile)
На входе объект с секцией
{
"title": "test section"
}
На выходе Id созданной секции
"test_section"
Создает секцию в профиле пользователя. Если явный Id не указан, генерирует его автоматически, заменяя " " на "_" и транслитерируя символы кириллицы в латиницу.
Имя команды для вызова: userProfile_createProfileSection.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: CreateSection
- На выходе: String
deleteProfileSection (User-profile)
На входе Id секции
"test_section"
На выходе ничего
{}
Удаляет секцию в профиле пользователя по ее Id.
Имя команды для вызова: userProfile_deleteProfileSection.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: String
- На выходе: Json (пустой объект)
updateProfileSection (User-profile)
Объект для изменения секции
{
"id": "test_section",
"title": "new test title",
"description": "test description"
}
На выходе ничего
{}
Меняет название и описание секции.
Имя команды для вызова: userProfile_updateProfileSection.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: Section
- На выходе: Json (пустой объект)
getProfileSections (User-profile)
На входе ничего
{}
На выходе список информаций о секции
[
{
"title": "Профиль пользователя",
"id": "userProfile",
"description": ""
},
{
"title": "Основные данные",
"id": "basicData",
"description": ""
},
{
"title": "Test title",
"id": "test_title",
"description": "Test title"
}
]
Возвращает список секций в структуре профиля.
Имя команды для вызова: userProfile_getProfileSections.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: Команда не принимает параметров
- На выходе: List[Section]
addProfileField (User-profile)
На входе объект с информацией о поле
{
"sectionId": "test_section",
"title": "Тестовое поле",
"type": "string",
"multiple": false,
"settings": {
"maxLength": 100
}
}
На выходе Id нового поля
"Testovoye_pole"
Создает поле в секции профиля. Если явный Id поля не указан, генерирует его автоматически, заменяя " " на "_" и транслитерируя символы кириллицы в латиницу.
Имя команды для вызова: userProfile_addProfileField.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: AddSectionField
- На выходе: String
deleteProfileField (User-profile)
На входе Id секции и Id поля
{
"sectionId": "test_section",
"fieldId": "Testovoye_pole"
}
На выходе ничего
{}
Удаляет поле в секции.
Имя команды для вызова: userProfile_deleteProfileField.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: DeleteSectionField
- На выходе: Json (пустой объект)
updateProfileField (User-profile)
На входе новые параметры поля
{
"sectionId": "test_section",
"fieldId": "Testovoye_pole",
"title": "new test title",
"description": "updated description",
"settings": {
"maxLength": 150
}
}
На выходе ничего
{}
Изменяет некоторые параметры поля.
Имя команды для вызова: userProfile_updateProfileField.
Поддерживается асинхронный и синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: UpdateSectionField
- На выходе: Json (пустой объект)
getProfileSectionFields (User-profile)
На входе Id секции
"basicData"
На выходе список полей в секции
[
{
"sectionId": "basicData",
"fieldId": "secondName",
"type": "string",
"title": "Фамилия",
"description": "",
"multiple": false,
"nullable": false,
"settings": {
"maxLength": 64
}
},
{
"sectionId": "basicData",
"fieldId": "name",
"type": "string",
"title": "Имя",
"description": "",
"multiple": false,
"nullable": false,
"settings": {
"maxLength": 64
}
},
{
"sectionId": "basicData",
"fieldId": "email",
"type": "string",
"title": "Email",
"description": "",
"multiple": false,
"nullable": false,
"settings": {
"maxLength": 64
}
},
{
"sectionId": "basicData",
"fieldId": "middleName",
"type": "string",
"title": "Отчество",
"description": "",
"multiple": false,
"nullable": true,
"settings": {
"maxLength": 64
}
}
]
Возвращает список полей в секции.
Имя команды для вызова: userProfile_getProfileSectionFields.
Поддерживается только синхронный вызов.
Результат выполнения команды не журналируется.
- На входе: String
- На выходе: List[SectionField]
getUserProfile (User-profile)
На входе Id пользователя и список секций, которые нужно получить
{
"userId": "5dfbbda7-b340-4a04-aae2-da4379f89eb9",
"sections": [
"basicData"
]
}
На выходе полная информация о пользователя
{
"id": "5dfbbda7-b340-4a04-aae2-da4379f89eb9",
"created": 1654608945300,
"modified": 1654609126388,
"version": 1,
"sections": {
"basicData": {
"name": "John",
"email": "emailname@mail.io9",
"middleName": "Jovonovich",
"secondName": "Week"
}
}
}
Возвращает информацию о пользователе. Если передать список секций, то возвращает не всю информацию, а только запрошенные секции.
Имя команды для вызова: userProfile_getUserProfile.
Поддерживается синхронный и асинхронный вызов.
Результат выполнения команды не журналируется.
- На входе: GetUserProfileDTO
- На выходе: UserProfileDTO
setUserProfileField (User-profile)
На входе информация для обновления поля профиля
{
"userId": "5dfbbda7-b340-4a04-aae2-da4379f89eb9",
"section": "basicData",
"field": "name",
"value": "JohnJohn",
"version": 3
}
На выходе новая версия
4
Меняет указанное поле в профиле пользователя, если совпадает версия.
Имя команды для вызова: userProfile_setUserProfileField.
Поддерживается синхронный и асинхронный вызов.
Результат выполнения команды не журналируется.
- На входе: SetProfileFieldDTO
- На выходе: Int
Обрабатываемые события сервиса профилей пользователей
События слушаются в USER_PROFILE_USER_EVENTS_TOPIC
| Источник событий | eventType | payloadType | Описание |
|---|---|---|---|
| mon | registration | user | Создает профиль пользователя при авторизации |
Объекты сервиса профилей пользователей
Типы данных, которые принимают или возвращают команды сервиса.
AddSectionField (User-profile)
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
| sectionId | String | Да | Id секции, в которую поместить поле | - Не пустое - Не больше 64 символов |
| fieldId | String | Нет | Id поля | - Не больше 64 символов |
| title | String | Да | Название поля | - Не больше 256 символов |
| type | String | Да | Тип поля доступный для сущностей модели данных | |
| description | String | Нет | Описание поля | |
| multiple | Boolean | Да | Множественное ли поле | |
| settings | Json | Нет | Дополнительные настройки для указанного типа поля |
CreateSection (User-profile)
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
| title | String | Да | Название секции | - Не больше 256 символов |
| id | String | Нет | Id секции | - Не пустое - Не больше 64 символов |
| description | String | Нет | Описание секции |
DeleteSectionField (User-profile)
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
| sectionId | String | Да | Id секции с полем | |
| fieldId | String | Да | Id поля |
Section (User-profile)
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
| title | String | Да | Название секции | - Не больше 256 символов |
| id | String | Да | Id секции | |
| description | String | Нет | Описание секции |
SectionField (User-profile)
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| sectionId | String | Да | Id секции с полем |
| fieldId | String | Да | Id поля в секции |
| title | String | Да | Название поля |
| type | String | Да | Тип поля доступный для сущностей модели данных |
| description | String | Да | Описание поля |
| multiple | Boolean | Да | Множественное ли поле |
| nullable | Boolean | Да | Обязательное ли поле |
| settings | Json | Да | Дополнительные настройки для указанного типа поля |
UpdateSectionField (User-profile)
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
| sectionId | String | Да | Id секции с полем | |
| fieldId | String | Да | Id поля | |
| title | String | Да | Новое название поля | |
| description | String | Нет | Новое описание поля | |
| settings | Json | Да | Новые дополнительные настройки для указанного типа поля |
UserProfileDTO (User-profile)
| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
| id | String | Да | Id пользователя |
| created | Long | Да | Время создания |
| modified | Long | Да | Время последнего изменения |
| version | Int | Да | Версия для борьбы с потерями обновлений |
| sections | Map[String, Json] | Да | Данные из секций профиля |
GetUserProfileDTO (User-profile)
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
| userId | UUID | Да | Id пользователя | |
| sections | List[String] | Нет | Список секций, которые нужно вернуть |
SetProfileFieldDTO (User-profile)
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
| userId | UUID | Да | Id пользователя | |
| section | String | Да | Секция, в которой находится поле для изменения | |
| field | String | Да | Название поля, которое нужно поменять | |
| value | Json | Да | Новое значение для этого поля | |
| version | Int | Да | Версия, полученная в составе UserProfile |
Verdi-cache: библиотека для кэширования
Предоставляет интерфейс и реализацию кеша.
Loggers config
<logger name="com.embedika.verdi.cache.CacheApi" level="INFO"/>
<logger name="scalacache.caffeine.CaffeineCache" level="INFO"/>
Структуры Verdi-cache
VerdiCacheConfig (Verdi-cache)
Настройки кеширования.
| Поле | Тип | Обязательное | Описание | Ограничения |
|---|---|---|---|---|
| maxSize | int | Нет | Максимальное количество элементов в кеше, при превышении которого элементы начнут удаляться (LRU). | |
| elementTTL | duration string | Нет | Максимальное время жизни элемента. |
Xacmldsl: библиотека для работы с XACML
Библиотека предоставляет DSL для создания и разбора XACML формата (XML).
Ключевые сущности: - TBD