Видалення застарілих бізнес-процесів

1. Проблематика

Застарілі бізнес-процеси (abandoned business processes) — це процеси, що були розпочаті, але не завершені. Причиною можуть бути помилки, виключення або інші перешкоди, через які процес припинився.

Існує кілька варіантів розв’язання цієї проблеми:

  1. Уникати застарілих процесів. Це можливо завдяки коректному моделюванню процесів, наприклад, використовуючи таймери завершення процесу (Timer Boundary Event) типу Duration для кожного завдання користувача (User Task).

    platform prod deploy abandoned bp
    Зображення 1. Бізнес-процес із таймером завершення
    Рекомендується встановлювати таймер на понад 14 днів, оскільки логи бізнес-процесів зберігаються в Elastic Search протягом цього часу. Після видалення логів неможливо ідентифікувати причину помилки.
  2. Якщо деякі процеси все ж залишилися незавершеними, можна скористатися інструментом Business Process Administration Portal (Camunda Cockpit), щоб видалити їх вручну.

    Детальніше дивіться на сторінці Адміністрування бізнес-процесів у Camunda Cockpit.
  3. Якщо кількість застарілих процесів велика, їх видалення вручну стає незручним або майже неможливим. У такому випадку варто використовувати скрипти для масового видалення (див. нижче).

2. Завершення великої кількості застарілих бізнес-процесів

Для завершення великої кількості застарілих процесів можна використовувати скрипти.

Усі SQL-запити виконуються на поді operational-instance.

2.1. Запити для отримання списку застарілих бізнес-процесів

Запит №1 (БД camunda)

Отримання списку ідентифікаторів процесів, які не виконували операції внесення даних в реєстр і перебувають на початкових задачах користувача. Результат виконання запита можна переглянути у вкладенні process_instance_ids.csv.

Цей запит є безпечним, за умови коректної конфігурації реєстру. Для test-registry використовуйте Запит №3.
SQL-сценарій
COPY
(
    select e.id_ -- running process instance id
    from act_ru_execution e
        join act_ru_task t ON e.id_ = t.proc_inst_id_
        join act_re_procdef p on e.proc_def_id_ = p.id_
        join act_hi_procinst h on e.proc_inst_id_ = h.proc_inst_id_
    where e.parent_id_ is null -- тільки верхньорівневі процеси
        and h.start_time_ < '2022-09-26 00:00:00.000' -- часова рамка для безпечного завершення процесів
        and (
            (p.key_ like 'test-registry-vpo-to-address-registration-bp' and task_def_key_ in ('searchUserForm', 'officerConnectVpoToAddress')) or
            (p.key_ like 'test-registry-housing-registration-bp' and task_def_key_ in ('searchUserForm', 'officerHousingRegistration')) or
            (p.key_ like 'test-registry-compensation-application-bp' and task_def_key_ in ('searchUserForm', 'sharedSearchPropertyForm')) or
            (p.key_ like 'test-registry-user-registration-bp' and task_def_key_ in ('userRegistrationForm')) or
            (p.key_ like 'create-vpo' and task_def_key_ in ('createVpoForm')) or
            (p.key_ like 'test-registry-reimbursement-costs-bp' and task_def_key_ in ('filterForm', 'reimbursementGridForm')) or
            (p.key_ like 'test-registry-housing-edit-bp' and task_def_key_ in ('housingEditForm', 'officerEditHousingForm')) or
            (p.key_ like 'test-registry-set-vpo-date-finish-bp' and task_def_key_ in ('officerSetVpoDateFinishSelectDateForm', 'officerSetVpoDateFinishGridForm')) or
            (p.key_ like 'test-registry-edit-user-registration-bp' and task_def_key_ in ('searchUserForm', 'editUserForm')) or
            (p.key_ like 'test-registry-completion-data-processing-bp' and task_def_key_ in ('completionDataProcessingFirstForm', 'completionDataProcessingReportForm')) or
            (p.key_ like 'link-test-registry-owner' and task_def_key_ in ('lsoSearchPropertyForm')) or
            (p.key_ like 'test-registry-compensation-sum-bp' and task_def_key_ in ('changeCompensationSumForm'))
        )
) TO '/var/tmp/process_instance_ids.csv' csv header;
  • test-registry — назва вашого реєстру.

Запит №2 (БД audit)

Отримання списку процесів, які виконали операції внесення даних в реєстр, але не завершилися через технічні причини. Результат виконання запита можна переглянути у вкладенні stuck_processes.csv.

SQL-сценарій
create extension dblink;

select distinct ae.source_business_process_instance_id
    from audit_event ae
    where context::json ->>'action'='INSERT INTO TABLE'
        and context::json ->>'step' = 'AFTER'
        and ae.source_business_process_instance_id in (select proc_inst_id_ from dblink('dbname=camunda','SELECT proc_inst_id_ FROM act_ru_execution') as arec(proc_inst_id_ text) )
        and source_business_process not in('test-registry-vpo-to-address-registration-bp','test-registry-compensation-application-bp')
union all
select ae.source_business_process_instance_id
    from audit_event ae
    where context::json ->>'action'='INSERT INTO TABLE'
        and context::json ->>'step' = 'AFTER'
        and ae.source_business_process_instance_id in (select proc_inst_id_ from dblink('dbname=camunda','SELECT proc_inst_id_ FROM act_ru_execution') as arec(proc_inst_id_ text) )
        and source_business_process  in('test-registry-compensation-application-bp')
    group by ae.source_business_process_instance_id
    having max (context::json ->>'tablename')<> min (context::json ->>'tablename');

drop extension dblink;
Запит №3 (БД camunda)

Отримання списку процесів, які були запущені до певної дати та залишилися незавершеними (Camunda).

SQL-сценарій
COPY
(
select e.id_ from act_ru_execution e join act_hi_procinst h on e.proc_inst_id_ = h.proc_inst_id_
where e.parent_id_ is null
  and h.start_time_ < '<дата_до_якої_видалити_процеси формат рік-місяц-число> 00:00:00.000'
) TO '/tmp/process_instance_ids.csv' csv header;

2.2. Запити для перевірки

Також існують запити для перевірки стану процесів:

  1. Щоб отримати список усіх процесів, виконайте наступний скрипт:

    psql
    \c camunda
    
    COPY
    (
    select e.id_ from act_ru_execution e join act_hi_procinst h on e.proc_inst_id_ = h.proc_inst_id_
    where e.parent_id_ is null
    ) TO '/var/tmp/process_instance_ids.csv' csv header;
  2. Якщо потрібно дізнатися кількість усіх процесів, виконайте наступний запит:

    select count (e.id_) from act_ru_execution e join act_hi_procinst h on e.proc_inst_id_ = h.proc_inst_id_
    where e.parent_id_ is null;
  3. Запит №3 дозволяє отримати список усіх процесів, які не були завершені та обмежені за датою.

  4. Щоб отримати кількість усіх процесів, які не були завершені й обмежені за датою, виконайте наступний запит:

    select count (e.id_) from act_ru_execution e join act_hi_procinst h on e.proc_inst_id_ = h.proc_inst_id_
    where e.parent_id_ is null
      and h.start_time_ < '<дата_до_якої_видалити_процеси формат рік-місяц-число>';

2.3. Bash-скрипт для масового видалення

Цей скрипт використовує CSV-файл з ідентифікаторами процесів, щоб завершити їх адміністративним шляхом.

Bash-сценарій
#!/bin/bash

file_location=$1

bpms_api_url="http://bpms:8080/api/process-instance/delete"
bpms_auth_token=$2

batch_partitioning_factor=150

process_instances_array=()
echo "Початок обробки CSV-файлу..."
while IFS= read -r process_instance_id
do
  process_instances_array+=("\"$process_instance_id\"")
done < $file_location
echo "Завершено обробку CSV-файлу. Усього записів: ${#process_instances_array[@]}"

for((i=0; i < ${#process_instances_array[@]}; i+=batch_partitioning_factor))
do
  partitioned_array=("${process_instances_array[@]:i:batch_partitioning_factor}" )
  echo "Відправка POST-запиту для завершення партії процесів..."
  curl -H "Content-Type: application/json" \
       -H "X-Access-Token: ${bpms_auth_token}" \
       -d "{\
              \"deleteReason\": \"Завершення застарілих процесів\",\
              \"processInstanceIds\": [$(IFS=, ; echo "${partitioned_array[*]}")],\
              \"skipCustomListeners\" : false,\
              \"skipSubprocesses\" : false,\
              \"failIfNotExists\" : false\
           }" \
       $bpms_api_url
  sleep 1
  echo "Завершено партію процесів"
done

3. Інструкція з практичного застосування

Спочатку виконайте Запити для перевірки, щоб отримати загальну кількість процесів, а також кількість процесів до зазначеної дати, які потрібно видалити. Це допоможе визначити, скільки процесів має залишитися після видалення.

Перевірити кількість процесів в інтерфейсі OpenShift можна за роутом bp-process-administration реєстру.

  1. Виконайте Запит №3 на поді operational-instance, щоб сформувати CSV-файл, та завантажте його локально:

    oc cp operational-instance-pod:/tmp/file ./file
    Це шаблон, необхідно підставити відповідні значення.
  2. Застосуйте тимчасовий Deployment rk-curl:

    Приклад Deployment для встановлення rk-curl
    kind: Deployment
    apiVersion: apps/v1
    metadata:
      name: rk-curl
      namespace: <назва реєстру>
      labels:
        app: rk-curl
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: rk-curl
      template:
        metadata:
          labels:
            app: rk-curl
        spec:
          containers:
            - name: curl
              image: ellerbrock/alpine-bash-curl-ssl
              command:
                - sleep
                - '36000'
              imagePullPolicy: IfNotPresent
          restartPolicy: Always
  3. Перевірте, що у NetworkPolicy bpms-policy дозволено трафік від “app: rk-curl”:

    - podSelector:
        matchLabels:
          app: rk-curl
  4. Скопіюйте CSV-файл та bash-скрипт у теку /tmp поду rk-curl:

    oc cp ./file rk-curl-pod:/tmp/file
    Це шаблон, необхідно підставити відповідні значення.
  5. Отримайте авторизаційний токен доступу до bpms для системного користувача jenkins-deployer, клієнта відповідного реалму <registry>-admin, у Keycloak за секретом, де <registry> — назва вашого реєстру.

    Приклад запита дивіться у Postman-колекції. Врахуйте, що TTL токена становить 5 хвилин. Якщо цього часу недостатньо, змініть параметр Access Token Lifespan в налаштуваннях Keycloak для реалму <registry>-admin, збільшивши його до 1 години.

    • <registry> — назва вашого реєстру.

  6. Запустіть bash-скрипт, зробивши його виконуваним (+x), та передайте необхідні параметри.

    Приклад
    ./script.sh file.csv "$(cat file.txt з токеном)"
  7. Виконайте Запити для перевірки, щоб переконатися, що всі застарілі процеси видалені та порівняйте, скільки файлів було і скільки лишилося після очищення.

Після завершення чистки незавершених бізнес-процесів, також потрібно виконати очищення S3-бакетів і Redis відповідно до інструкції Видалення документів з S3 Ceph-бакетів і Redis.