# Сервис SysProcesses

Сервис для асинхронного выполнения фоновых процессов бизнес-логики. Процессы могут быть инициированы через API или автоматически путём вставки записей в служебную таблицу `sysprocesses.sysprocesses`. 

**Конфигурация:**
`SysProcesses.disableCheck` – если `true`, автоматическая проверка очереди процессов отключается (полезно для отладки).

**Основные возможности:**

- Автоматический запуск процессов, ожидающих выполнения в таблице `sysprocesses.sysprocesses`.
- Поддержка очередей (`QUEUE`): внутри одной очереди процессы выполняются строго последовательно.
- Отложенный запуск по полю `START_AT`.
- Ограничение количества одновременно выполняющихся процессов (`maxProcessses`, по умолчанию `1`).
- Сохранение результатов или ошибок в БД.
- API для добавления, удаления и просмотра процессов.
- Оповещение о завершении/ошибке через события `onProcessCompleted` и `onProcessError`.

Сервис поддерживает три типа процессов: 
- `csp` - вызов сервисов
- `db` - выполнение хранимых процедур в БД с транзакцией ()
- `sql` - выполнение произвольного SQL-кода ()


### Методы

#### `addProcess`

Добавляет новый процесс в очередь.

**Параметры:**
- `session` – объект сессии пользователя (обязательно, для записи `user_id`).
- `type` – тип процесса (`'csp'`, `'db'`, `'sql'`).
- `name` – имя процесса:
  - для `csp` – строка вида `'ServiceName.requestName'`.
  - для `db` – полное имя хранимой функции (например, `'PKG_VOCAB.INSERT_VALUE'`).
  - для `sql` – произвольное описание (сам код передаётся в `sourceCode`).
- `params` – объект с параметрами (для `csp` и `db`). При вызове сервиса (`csp`) параметры будут переданы в запрос, а также будет добавлено поле `session` с `userId`.
- `sourceCode` – SQL-код для типа `sql`.
- `queue` – имя очереди (строковый идентификатор). Процессы в одной очереди выполняются последовательно.
- `startAt` – время отложенного запуска в формате ISO.
- `keep` – если `true`, запись о процессе не удаляется автоматически после завершения. Полезно для отслеживания выполнения процесса.

**Возвращает:** идентификатор созданного процесса (`id`).

**Пример:**
```js
const id = await gsvc.sendRequest('addProcess', {
  session: { userId: 123, isAdmin: true },
  type: 'csp',
  name: 'ReportService.generate',
  params: { date: '2026-01-01' },
  queue: 'reports',
  keep: true
}, log);
```

#### `delProcess`

Удаляет процесс по идентификатору. Запрещено удалять выполняющийся в данный момент процесс.

Нужно только для процессов соданых с `keep: true`

**Параметры:**
- `session` – сессия (обязательно).
- `id` – ID процесса.

**Права доступа:** администратор или владелец процесса (совпадение `user_id`).

**Ошибки:**
- `NOT_AUTHORIZED` – отсутствует сессия.
- `PROCESS_IS_RUNNING` – процесс выполняется.
- `PROCESS_NOT_FOUND` – процесс не найден.
- `FORBIDDEN` – недостаточно прав.

**Пример:**
```js
await gsvc.sendRequest('delProcess', {
  session: { userId: 123 },
  id: 42
}, log);
```

#### `list`

Возвращает список процессов с информацией о статусе.

**Параметры:**
- `session` – обязателен.

**Права:** администратор видит все процессы, обычный пользователь – только свои (`user_id` совпадает с `session.userId`).

**Возвращаемый формат:**
```json
[
  {
    "ID": 1,
    "TYPE": "csp",
    "NAME": "ReportService.generate",
    "USER_ID": 123,
    "QUEUE": "reports",
    "START_AT": null,
    "STARTED": "2026-06-22T10:00:00",
    "COMPLETED": null,
    "ERROR_TEXT": null,
    "STATUS": "running",
    "INFO": { ... }
  }
]
```

Поле `STATUS` может принимать значения:
- `'waiting'` – ожидает запуска.
- `'running'` – выполняется в данный момент.
- `'completed'` – успешно завершён.
- `'failed'` – завершён с ошибкой.

Для выполняющихся процессов в `INFO` попадают данные, возвращаемые методом `getInfo()` конкретного обработчика (например, идентификатор транзакции).

#### `checkList`

Инструмент отладки. Принудительно проверяет таблицу процессов и запускает все ожидающие (с учётом очередей и лимитов). 

**Требует прав администратора.**

**Пример:**
```js
await gsvc.sendRequest('checkList', {}, log);
```

### События

- `onProcessCompleted` – возникает при успешном завершении процесса. Параметры обработчика: `{ process, result }`.
- `onProcessError` – возникает при ошибке. Параметры: `{ process, errorText }`.

### Внутреннее устройство

Сервис использует два механизма для обнаружения новых процессов:

1. **Таймер `checkTimer`** – периодически (каждые 60 секунд) вызывает `checkList()`.
2. **Подписка на уведомления PostgreSQL** через клиент `PgNotify`. При вставке новой записи в таблицу `sysprocesses.sysprocesses` (через триггер в БД) отправляется уведомление `new_sysprocess`, которое мгновенно активирует проверку очереди.

При запуске сервиса (`start()`) выполняется первоначальная проверка очереди, затем запускается таймер и оформляется подписка на канал `new_sysprocess`. При остановке (`stop()`) подписка снимается.


## Примечания

- Максимальное число одновременно выполняющихся процессов задаётся жёстко (`maxProcessses = 1`). При необходимости изменения можно унаследовать сервис и переопределить это свойство.
- Автоматическое удаление записи после завершения можно отключить флагом `keep: true` при добавлении процесса.