'rest' capability для WebSocket User API

Обзор

Предоставляет интерфейс для проведения CRUD операций с сущностями статических и динамических классов. Для работы требует наличия у пользователя роли, разрешающей доступ к маршруту /ws#rest с методом WEBSOCKET.

При запросах осуществляет дополнительную ролевую авторизацию на доступ к конкретным endpoint REST-API на конкретную операцию. Различаются endpoint коллекции, конкретных элементов коллекции, а также свойств для доступа к вложениям. Так, если пользователю маршрутами в ролях разрешен лишь метод GET к коллекции класса, то он сможет читать коллекцию, но не сможет читать конкретную сущность и изменять и создавать сущности.

Каждое непустое изменение завершается генерацией уведомлений подписчикам.

Никаких событий этот rest-capability не генерирует.

Среди классов, к которым возможно обращение:

Построение запросов

Общий вид запроса:
[
  "rest",
  {
    "qid":"16066361-dfc0-49f6-b734-9b3dda09db22",
    "operation": "...",
    "classpath": "/rest/v1/...",
    ...
  }
]

Обязательные поля запроса:

  • operation - тип операции над классом (read, create, replace, update, delete, clear, lookup).

  • classpath - полный путь к коллекции класса в REST-API: "/rest/v1/model/builder/packages/Packages",

Специфические поля запроса:

  • interval - список из двух дат (начало и конец периода). Необходим к указанию в операциях выборки из коллекций динамических классов, имеющих storage_mode = history или transactionlog.

  • id - идентификатор конкретной сущности. При проведении операций с коллекцией (выборка элементов, поиск, очистка коллекции) необходимо исключать поле из запроса.

  • content - содержимое запроса. Необходимо при создании, замене, изменении сущности (json-объект), а также в случае поиска по ключу (значение подлежащее поиску - строка или число).

  • hrkey - устанавливает ключ для hashring-выбора процесса-обработчика операций модификации. По умолчанию используется идентификатор сущности. Применяется для организации распараллеливания обработки операций модификации и чтения конкретной сущности (для классов с integrity_mode: async, sync_fast_read, sync_fast_notify). Привязка к конкретному процессу-обработчику позволяет сохранять важную для системы-клиента последовательность операций при обработке и в уведомлениях. Отдельный ключ может использоваться для сохранения гарантированного сохранения последовательности операций с несколькими различными сущностями класса в рамках одной супер-операции, известной системе-клиенту.

  • timeout - время ожидания ответа в миллисекундах. Для коллекций динамических классов (dms) - таймаут исполнения запроса чтения коллекции (по умолчанию 60000), по истечении которого DMS не приступит к выполнению запроса, если тот еще ожидает в очереди. Для коллекций статических классов (dc) - время, в течение которого веб-сервер ожидает ответа и доступности доменного центра (по умолчанию значение параметра 'rest_reattempts_sec', не более 120000). По его истечении отправляется ответ об ошибке, но запрос, уже переданный в доменный центр, им не отменяется: результат операции изменения в этом случае неизвестен. См. Переповторы вместо 5хх.

Поля условий выборки - все опциональны:

  • filter - условие фильтра. См. функции общего назначения.

  • order - порядок сортировки.

  • mask - поля выдачи.

  • offset - смещение в выборке.

  • limit - ограничение количества элементов в выборке.

  • aggr - поля агрегации. Объект, содержащий ключами возвращаемые поля, а значениями - функции агрегации. В качестве аргумента допускает применение суперпозиции функций, построение которой аналогично функциям фильтра. См. (функции агрегации).

  • groupby - база агрегации. Объект, содержащий ключами возвращаемые поля, а значениями - названия полей объекта или список, представляющий собой суперпозицию функций. Построение функций аналогично функциям фильтра. См. (функции общего назначения).

Поддерживаются операции:

  • read - выборка из коллекции, в том числе агрегирующая.

  • read - если указано поле id, то в ответ на запрос возвращаются данные конкретной сущности, имеющей указанный идентификатор. Опционально допускается маскировка (mask).

  • lookup - поиск идентификаторов элементов коллекции по ключевым полям. Значение для поиска передается в поле content.

  • clear - очистка коллекции. Поддерживается только в коллекциях динамических классов.

  • create - создание сущности в коллекции с автогенерацией идентификатора.

  • replace - создание или полная замена сущности с указанным идентификатором. Поддерживается только в коллекциях динамических классов.

  • update - изменение существующей сущности с указанным идентификатором. Неуказанные поля остаются неизменными. В коллекциях динамических классов (dms) производится замещение значений полей целиком. В коллекциях статических классов (dc) композитные поля допускают частичное обновление на 1 уровень в глубину.

  • delete - удаление существующей сущности с указанным идентификатором.

  • setup - рантайм настройка коллекции (например, временная приостановка рассылки уведомлений подписчикам об изменениях, чтение и удаление партиций). Тип операции и ее возможные параметры передаются в виде объекта в поле content.

Примеры запросов к статическим и динамическим коллекциям

Выборка элементов из коллекции:
[
  "rest",
  {
    "qid": "16066361-dfc0-49f6-b734-9b3dda09db22",
    "operation": "read",
    "classpath": "/rest/v1/model/builder/packages/Packages",
    "filter": ["or",["like",["property","pstr"],"asdf*"],["==",["property","pint"],8640000]],
    "order": ["pstr",{"pint","desc"},{"id","asc"}],
    "mask": ["id","pstr"],
    "offset": 0,
    "limit": 2
  }
]
Агрегирующая выборка из коллекции:
[
  "rest",
  {
    "qid": "16066361-dfc0-49f6-b734-9b3dda09db22",
    "operation": "read",
    "classpath": "/rest/v1/model/builder/packages/Packages",
    "filter": ["like",["property","pstr"],"a*"],
    "groupby":{"a":["%",["property","pint"],10]},
    "aggr":{"cnt":["sum",["-",["property","pint"],1]]}
    "offset": 0,
    "limit": 2
  }
]
Поиск элементов в коллекции по ключевым полям:
[
  "rest",
  {
    "qid": "16066361-dfc0-49f6-b734-9b3dda09db22",
    "operation": "lookup",
    "classpath": "/rest/v1/model/builder/packages/Packages",
    "content": "abc"
  }
]
Очистка коллекции:
[
  "rest",
  {
    "qid": "16066361-dfc0-49f6-b734-9b3dda09db22",
    "operation": "clear",
    "classpath": "/rest/v1/model/builder/packages/Packages"
  }
]
Чтение сущности:
[
  "rest",
  {
    "qid": "16066361-dfc0-49f6-b734-9b3dda09db22",
    "operation": "read",
    "classpath": "/rest/v1/model/builder/packages/Packages",
    "id": "c87a8ca6-0f08-91b7-9d19-2fa86f019916"
  }
]
Создание сущности:
[
  "rest",
  {
    "qid": "16066361-dfc0-49f6-b734-9b3dda09db22",
    "operation": "create",
    "classpath": "/rest/v1/model/builder/packages/Packages",
    "content": { ... }
  }
]
Замена сущности:
[
  "rest",
  {
    "qid": "16066361-dfc0-49f6-b734-9b3dda09db22",
    "operation": "replace",
    "classpath": "/rest/v1/model/builder/packages/Packages",
    "id": "c87a8ca6-0f08-91b7-9d19-2fa86f019916",
    "content": { ... }
  }
]
Изменение сущности:
[
  "rest",
  {
    "qid": "16066361-dfc0-49f6-b734-9b3dda09db22",
    "operation": "update",
    "classpath": "/rest/v1/model/builder/packages/Packages",
    "id": "c87a8ca6-0f08-91b7-9d19-2fa86f019916",
    "content": { ... }
  }
]
Удаление сущности:
[
  "rest",
  {
    "qid": "16066361-dfc0-49f6-b734-9b3dda09db22",
    "operation": "delete",
    "classpath": "/rest/v1/model/builder/packages/Packages",
    "id": "c87a8ca6-0f08-91b7-9d19-2fa86f019916"
  }
]
Поиск сущности по ключу:
[
  "rest",
  {
    "qid": "16066361-dfc0-49f6-b734-9b3dda09db22",
    "operation": "lookup",
    "classpath": "/rest/v1/model/builder/packages/Packages",
    "content": "asdfasdf"
  }
]
Рантайм настройка коллекции:
[
  "rest",
  {
    "qid": "16066361-dfc0-49f6-b734-9b3dda09db22",
    "operation": "setup",
    "classpath": "/rest/v1/model/builder/packages/Packages",
    "content": {
      "cmd": "suspend_notification"
    }
  }
]

Специальные коллекции

/rest/v1/domain/nservices

Выполнение запросов к наносервисам продуктового слоя.

Получение списка активных наносервисов:
[
  "rest",
  {
    "qid": "16066361-dfc0-49f6-b734-9b3dda0915f7",
    "operation": "read",
    "classpath": "/rest/v1/domain/nservices"
  }
]
Ответ:
[
  "rest",
  {
    "qid": "16066361-dfc0-49f6-b734-9b3dda0915f7",
    "data": [
      {"name":"builder.DataService"},
      {"name":"builder.GeneratorService"}
    ]
  }
]
Выполнение запроса к наносервису:
[
  "rest",
  {
    "qid": "16066361-dfc0-49f6-b734-9b3dda09472e",
    "operation": "create",
    "classpath": "/rest/v1/domain/nservices",
    "name": "platform.PerfmonService",
    "method": "test",
    "request": {"a":1,"b":"2","cc":[{"d":100,"e":"200"},{"f":300}]}
  }
]
Ответ на запрос:
[
  "rest_result",
  {
    "qid": "16066361-dfc0-49f6-b734-9b3dda09472e",
    "data": {
      "result": "ok",
      "code": "success",
      "response": {"a":"zxcvzxcvzxcv"}
    }
  }
]

Настройка подключения для выполнения REST-запросов

  1. Общий вид запроса:

[
  "setup_rest",
  {
    "qid": 0.1234,
    "skip_response_entity": true,
    ...
  }
]

Возможные опции - поля запроса:

  • skip_response_entity - позволяет для конкретного вебсокет-подключения установить запрет на отправку полной сущности в ответ на операции create, replace, update. При этом create все же отправляет обратно сущность с единственным полем "id", другие запросы возвращают просто 'ok'.

Переповторы вместо 5хх

Запросы, которые не могут быть обработаны (переезд микросервисов, таймауты, перегрузка очередей и др.) отвечаются ошибкой с кодом 5хх, эквивалентно кодам HTTP.

Конфигурационный параметр веб-сервера 'rest_reattempts_sec' позволяет управлять режимом переповтора. Пока установленный интервал не истек, веб-сервер делает периодические попытки переотправить запрос целевому микросервису. Работает только для websocket-подключений, в направлении DMS и доменного центра (DC). Это позволяет продуктовым микросервисам, взаимодействующим с моделью данных платформы, не переинициализироваться, а находиться в ожидании.

Направление DMS

Повторы осуществляются не чаще чем 1 раз в 5 секунд. В течение 5 секунд после отправки запроса ожидается получение отчета о доставке. В течение 30 секунд после отправки запроса ожидается получение ответа.

Побочные эффекты:

  • За время переотправки может сработать ряд таймаутов в логике инициатора запроса.

  • Если запрос доставлен, но за 30 секунд не обработался (в целевом микросервисе имеется непустая очередь к БД, где запрос ожидал исполнения), то:

    • в случае, когда запрос еще не поступил на исполнение из очереди, он будет отменен.

    • в случае, когда запрос уже исполняется, повторные обращения а) спровоцируют дополнительную нагрузку на БД, отчего очередь вырастет еще сильнее, б) запросы create и delete в ходе повторных выполнений будут завершены ошибкой 404.

Направление DC

Запросы к коллекциям статических классов ожидают ответа и доступности доменного центра в течение времени timeout запроса (по умолчанию - значение параметра 'rest_reattempts_sec', не более 120 секунд; значение 0 - одна попытка без повторов). Ответ отправляется не позже истечения этого времени, но не ранее чем через 5 секунд ожидания попытки. В отличие от DMS, доменный центр не отменяет запрос по истечении timeout: время ограничивает только ожидание веб-сервера. Если за это время ответ на операцию изменения не получен, возвращается ошибка 503 с сообщением о неизвестном результате; состояние сущности следует перечитать. Ответ отправляется, как только доменный центр ответил.

Доменный центр считается недоступным, если он не найден (перезагрузка, переключение на резервный экземпляр), не загружен или не имеет соединения с БД. В этих случаях запрос повторяется с растущей паузой от 0,25 до 3 секунд. Если процесс доменного центра завершился во время ожидания ответа (перезапуск), повторяются только операции чтения (read, lookup, hc). Операции модификации не повторяются, чтобы не выполнить их дважды, и отвечаются ошибкой 503. Если доменный центр не ответил за время ожидания вызова, запрос не повторяется и отвечается ошибкой 503: центр перегружен и, вероятно, еще исполняет запрос. Ошибки, которые вернул доменный центр, возвращаются сразу, без повторов.

Количество одновременно исполняемых запросов к доменному центру домена от одного экземпляра веб-сервера ограничено параметром 'dc_rest_limit' (по умолчанию 10). Остальные запросы ожидают в очереди. Запрос, который не дождался своей очереди за время ожидания (но не менее 5 секунд), отвечается ошибкой 503 без отправки в доменный центр.

Количество одновременно исполняемых запросов к доменному центру от одного websocket-подключения дополнительно ограничено параметром 'dc_rest_conn_limit' (по умолчанию 5). Остальные запросы подключения ожидают в его собственной очереди и не задерживают запросы других подключений. Время ожидания в очереди подключения входит во время ожидания запроса. Запросы одного подключения к одной сущности (с указанием id) исполняются строго по очереди: следующий отправляется в доменный центр после ответа на предыдущий. Порядок запросов из разных подключений не гарантируется.

При недоступности доменного центра очередь приостанавливается: доступность проверяет единственный служебный запрос с интервалом до 3 секунд, а ожидающие запросы в доменный центр не отправляются. Как только доменный центр снова доступен, очередь возобновляется.

Побочные эффекты:

  • За время ожидания может сработать ряд таймаутов в логике инициатора запроса.

  • Запрос, уже отправленный в доменный центр, исполняется им даже после закрытия websocket-подключения.

  • Значение timeout = 0 отключает повторы, но запрос может ожидать очереди до 5 секунд.