Group Actions

Note

Available in the Enterprise version only.

Group actions allow processing a large number of items on the server.

Examples of group actions:

  1. Export to Excel

  2. Downloading a Zip archive with all selected items

License

The group actions feature is available if the features section of the license content contains the group-actions entry:

features:
  group-actions: {}

Describing New Group Actions in a Microservice

To enable describing group actions in a microservice, add the following dependency to pom.xml:

<!-- Подходящая версия подтянется из родительского pom файла -->
<dependency>
    <groupId>ru.citeck.ecos.ent.groupactions</groupId>
    <artifactId>ecos-group-actions</artifactId>
</dependency>

After that, you can implement the following interface as a Spring component (it will be registered automatically):

interface GroupActionExecutionFactory<in T : Any, in C : Any> {

    fun createExecution(config: C): GroupActionExecution<T>

    fun getType(): String
}

The getType method must return the type by which the implemented action can be invoked.

The createExecution method is called each time a new action is started.

The GroupActionExecution interface looks as follows:

interface GroupActionExecution<in T : Any> {

    fun getRequiredAttributes(): Map<String, *> {
        return emptyMap<String, String>()
    }

    @Throws(Exception::class)
    fun execute(context: GroupActionContext<T>): ActionResult

    @Throws(Exception::class)
    fun dispose()
}

The getRequiredAttributes method returns a map of attributes required for action execution. Attributes can also be requested during execution, but it is more efficient to return the list upfront to avoid unnecessary requests.

The dispose method is called when the action completes with any result. That is, in case of an error, the dispose method will also be called.

The execute method is called when the action starts. All main data manipulations are performed in this method.

The execute method receives an action context with the getValues(): Iterable<T> and getBatchedValues(batchSize: Int): Iterable<List<T>> methods. Either of these methods can be called to iterate over all values in a loop or manually.

If processing should not be interrupted on error, the action executor must handle this itself. If an exception is thrown from the execute method, the action execution terminates immediately.

Possible group action result types:

Class

ID

Data

Description

ActionResultLink

LINK

url: String

Return a link to something for download.
The link must be relative (without protocol, host, or port).
For example:
/gateway/emodel/api/ecos/webapp/content?ref=temp-file@1c1bf32d-07ad-422c-85e4-4789058e0fb1
To get a download link for a record’s content, use the getDownloadUrl method in the EcosContentApi service.
The same service also provides an API for creating a temporary file.

ActionResultMessage

MESSAGE

message: String

Return a message

ActionResultOk

OK

Return a simple result indicating that the action completed successfully

ActionResultResults

RESULTS

results: List<Result>

Типы:

Result:
message: String,
status: ResultStatus,
recordRef: EntityRef

enum ResultStatus {
OK,
ERROR,
PERMISSION_DENIED,
SKIPPED
}

Return a list of results for each processed record

Execution Threads

All group actions are executed within a pre-configured thread pool.

Configuring the number of execution threads via Spring properties:

ecos:
  webapp:
    task:
      executors:
        group-actions:
          corePoolSize: 5 # по умолчанию действия выполняют пять потоков

The action is executed in the context of the user who initiated it (access rights, time zone, locale, etc.)

Running a Group Action

To run a group action, prepare the following parameters:

GroupActionParams(
    values: GroupActionValuesParams, # параметры формирования списка значений для обработки
    execution: GroupActionExecutionParams # параметры обработки
)

GroupActionValuesParams(
    type: String, # тип источника значений для обработки
    config: ObjectData, # конфигурация для формирования списка значений для обработки
    limit: Long = -1 # ограничение на количество элементов в списке значений. -1 - без ограничений
)

GroupActionExecutionParams(
    type: String, # тип действия
    config: ObjectData = ObjectData.create(), # конфигурация действия
    timeout: Duration = Duration.ofHours(5) # ограничение на время выполнения
)

Value sources:

Type

Configuration

Description

records-list

records: List<EntityRef>

A list of specific entities

records-query

query: RecordsQuery
pageSize: Int

A list of specific entities

Solution Architecture

The general principle of group actions is as follows:

When the ecos-group-actions dependency is added, Spring Boot autoconfiguration registers:

  1. Group actions service

  2. Group actions registrar

  3. RecordsDAO for group actions with ID “group-action”

To run a group action, a record mutation is performed:

{appName_микросервиса}/group-action@

The attribute fields for GroupActionParams are filled in (i.e. values and execution)

RecordsDao launches the group operation via the service and immediately (without waiting for it to complete) returns a reference to the created action in the following format:

{appName_микросервиса}:{appInstance_микросервиса}/group-action@{actionId}

For example:

transformations:nrfdsvbocapo/group-action@7c269f9c-262b-4426-8865-7309dec07f2c

The action initiator can then load attributes using the returned ref to get information about the action status:

status: GroupActionStatus
initiator: EntityRef
processedCount: Long
totalCount: Long
result: GroupActionResult? # результат выполнения. В статусах WAITING и RUNNING всегда возвращает null. В остальных случаях всегда возвращается не-null значение.

Типы:

enum GroupActionStatus = {
    WAITING, // действие ожидает пока освободится поток для его выполнения
    RUNNING, // действие выполняется
    COMPLETED, // действие завершено успешно
    ERROR // ошибка при выполнении действия
}

GroupActionResult(
    type: String, # Тип результата. Может быть одним из штатных типов результата (LINK, OK, и т.д.) или ошибочным - "ERROR"
    data: ObjectData # Данные по результату. Например, для LINK здесь будет ссылка, для OK пустой объект.
)

The action initiator can periodically check the action status by loading the required attributes and can take action as soon as a status other than WAITING/RUNNING or a non-null result is received.

UI Action

Action type — server-group-action-v2

Action configuration:

targetApp: String # целевое приложение где описана реализация групповой операции
valuesParams:
  limit: Number # Лимит обрабатываемых элементов
executionParams:
  type: String # Тип действия
  timeout: Duration # Максимальное время, которое действие может выполняться
  config: Map<String, *> # Конфигурация действия. Содержимое зависит от типа действия
outputParams:
  type: String # Тип способа возвращения результата действия
  config: Map<String, *> # Конфигурация, описывающая дополнительные свойства для возвращения результата действия

outputParams is an optional parameter and is specified only when the default action response behavior needs to be overridden.

Configuration example:

id: group-action-export-csv
type: server-group-action-v2
name:
  ru: Скачать CSV-файл
  en: Download Excel-file

config:
  targetApp: transformations
  valuesParams:
    limit: 1000000
  executionParams:
    type: export-xlsx
    timeout: T1H
    config:
      fileName: "report"
      columns: [{name: Column, attribute: "?disp"}]

features:
  execForRecords: true
  execForQuery: true
  execForRecord: false

While the group operation is running, a progress window (% completion) is displayed:

../../_images/0112.png

Configuration example with outputParams:

id: group-action-export-xlsx
type: server-group-action-v2
name:
  ru: Скачать Excel-файл
  en: Download Excel-file

config:
  targetApp: transformations
  valuesParams:
    limit: 1000000
  executionParams:
    type: export-xlsx
    timeout: T1H
    config:
      fileName: "${$context.journalName}_${$now|fmt('yyyy-MM-dd_HH-mm-ss')}"
      columns: "${$context.reportColumns[]?json}"
  outputParams:
    type: EMAIL
    config:
      notificationRef: notifications/template@default-link-for-export-file-notification

features:
  execForQuery: true
  execForRecord: false
  execForRecords: true

After the export completes, a message is displayed:

../../_images/0211.png