Перейти к содержимому

Службы

Каталог встроенных фоновых служб портала (Админка → Службы): назначение, расписание, ручной запуск, настройки и поведение при выключении.

Для разработчиков расширений см. также Service Framework и Hot deploy.

Платформа управляет фоновыми службами портала. Каждая служба — строка в portal_services: тумблер включения, опциональное расписание и конфиг. Задания (кроме резервного копирования) идут в очередь portal_jobs и выполняются процессом Portal.Worker.

Событие (API) → EventDispatch → Event Receivers → portal_jobs → Worker
CronScheduler → portal_jobs (или portal_backups) → Worker / backup-runner

Админка → Службы — таблица встроенных служб.

ЭлементПоведение
Меню Действия строки: Вкл/Выкл, Запустить / Полный обход, Очистить индекс, ⚙ Настройки, Расписание
РасписаниеОткрывает модальное окно (не раскрытие строки). Сохранение → cronExpression + cronEnabled
Колонка расписанияТекст расписания показывается и при выключенном cron: … (выкл)
Последнийlast_run_at из заданий/журнала или cron_last_run_at
? у названияСправка о службе (popover) со ссылкой на этот каталог (/docs/admin/services#…)
Runner onlineНет в таблице Служб — только на /services/portal-backup и в Обзор → Обслуживание

Если служба выключена, Worker не выполняет задания с её service_key (статус failed: «Служба отключена или не найдена»). Cron тоже не ставит новые задания для выключенной службы.

КомпонентНазначение
portal_servicesРеестр служб (ключ, title, is_enabled, cron, config)
portal_jobsОчередь заданий большинства служб
portal_backupsОчередь validate / backup / restore (служба portal-backup)
event_receiversПодписчики на события списков и др.
WorkerОпрос portal_jobs, cron, hot-load пакетов
backup-runnerОтдельный процесс/контейнер для бэкапов
МетодПутьОписание
GET/admin/dashboardОбзор: статистика, аудит, блок обслуживания
POST/admin/search/clearОчистить поисковый индекс без обхода
GET/servicesСписок служб
PATCH/services/{key}{ "isEnabled", "cronEnabled", "cronExpression", … }
POST/services/{key}/runРучной запуск (где поддерживается)
GET/jobsОчередь / журнал заданий
POST/jobs/{id}/retryПовторить задание
GET/PUT/jobs/settings/retentionСрок хранения журнала (jobs-cleanup)
GET/POST/PATCH/DELETE/event-receiversПодписчики событий

Планировщик — CronSchedulerService в Portal.Worker. В админке расписание задаётся в понятном виде; в API/БД хранится как cron (5 полей: мин час день месяц день_недели).

ПолеОписание
cron_enabledВключить автозапуск
cron_expressionВыражение cron
cron_job_typeТип задания (платформа; в UI не редактируется)
cron_last_run_atВремя последнего запуска по расписанию

Пример: 0 3 * * * — каждый день в 03:00. В UI: Службы → ⋮ → Расписание (модальное окно).

Переменная CRON_RELOAD_INTERVAL_MS (по умолчанию 60000) — как часто Worker перечитывает расписание из БД.

После seed / миграций обслуживания (если расписание ещё не меняли):

СлужбаCronВкл. по умолчанию
portal-backup0 2 * * *расписание выкл (нужны путь и runner)
search-crawler0 3 * * *да
list-export (purge файлов)0 3 * * *да (в БД; в UI расписания нет)
recycle-bin0 4 * * *да
jobs-cleanup0 5 * * *да

Состояние индекса и корзины — Админка → Обзор → Обслуживание. Срок хранения журнала заданий — Админка → Задания.

Порядок как в реестре платформы (BuiltinServices) и в таблице Службы.

#КлючНазваниеВкл. по умолчанию*Расписание в UIРучной запуск в UIСтраница настроек
1auditАудитданетнет
2notificationsУведомлениянетнетда (тест e-mail)SMTP в Настройки
3ad-syncСинхронизация ADнетдада/services/ad-sync
4search-crawlerПоисковый индексда + cronдада (полный обход)
5recycle-binКорзинада + cronдада
6event-extensionsEvent Receiversданетнетвкладка Event Receivers
7timer-extensionsTimer Jobsданет**нетвкладка Timer Jobs
8list-exportЭкспорт списковданет***нет
9portal-backupРезервное копированиедаданет****/services/portal-backup
10jobs-cleanupЖурнал заданийда + cronдадаretention на вкладке Задания

* Фактический seed новой инсталляции; EnabledByDefault в коде и флаги после миграций могут отличаться для отдельных служб — ориентируйтесь на таблицу выше и разделы ниже.
** Расписание задаётся у экземпляров Timer Job, не у строки службы.
*** Cron purge в БД есть; пункта «Расписание» в меню нет.
**** Копия/проверка/восстановление — со страницы настроек и API, не через «Запустить» у строки службы.


Ключ: audit
Описание в UI: Журналирование событий портала.

Пишет события в audit_logs (и показывает их на Обзоре админки). Основной путь — не cron и не кнопка «Запустить», а Event Receivers с типом задания audit.logEvent.

  • Служба включена.
  • Расписания нет (и в UI кнопка «Расписание» недоступна).
job_typeКогда
audit.logEventПодписчик Event Receiver сработал на событие

При установке создаются подписчики (если ещё нет), например:

  • listItem.created / updated / deleted → аудит элементов списка
  • в seed также могут быть шаблоны для page.* / file.uploaded — фактически эмитятся платформой прежде всего события элементов списка (listItem.*)

Подписчики: Админка → Event Receivers (или API /event-receivers).

ДействиеЕсть?
Вкл/выклда
Расписаниенет
Запуститьнет (API POST /services/audit/run формально есть, без осмысленного payload почти бесполезен)
Отдельные настройкинет

Новые и ожидающие jobs с service_key=audit не выполнятся — записи в журнал аудита через этот канал перестанут появляться. Сама таблица audit_logs и UI обзора остаются.


Ключ: notifications
Описание в UI: Отправка почты через SMTP (задания и Event Receivers).

Шлюз исходящей почты портала, а не «ночная» пакетная служба. Пока служба выключена, портал не отправляет письма через этот канал (API, Event Receivers, ручной тест из Служб).

  • Служба выключена.
  • Расписания в UI нет (почта идёт по событиям и API).
  1. Админка → Настройки → SMTP / Почта — host, порт, учётные данные, From, опционально allowAuthenticatedSend.
  2. Админка → Службы → УведомленияВключить.

Тест SMTP в настройках проверяет сервер без требования, чтобы служба была включена. Реальная отправка через портал — только при включённой службе.

Настройки SMTP хранятся в portal_services.config ключа notifications. Fallback: переменные SMTP_* в окружении.

ИсточникПоведение
Event Receiver notifications.sendEventEmailНа событие ставится job → Worker шлёт письмо по шаблону
POST /api/v1/mail/sendОчередь (async: true) или сразу (только admin, async: false)
⋮ → Запустить у службыPrompt e-mail → тестовое письмо

Цепочка: событие / APIportal_jobs → Worker → SMTP (MailKit).

job_typeНазначение
notifications.sendEmailПрямая отправка: to, subject, text/html
notifications.sendEventEmailПисьмо из Event Receiver (шаблоны с {{eventName}}, {{userLogin}}, …)
ДействиеЕсть?
Вкл/выклда, через
Расписаниенет
Запуститьда (, prompt e-mail)
НастройкиНастройки → SMTP, не /services/notifications
Справка ?popover + ссылка на этот раздел
  • /mail/send и ручной Запустить — ошибка;
  • jobs с service_key=notifications падают;
  • SMTP-настройки и тест SMTP остаются;
  • подписчики ER могут создавать jobs, но отправка не пройдёт.

Не путать с пакетными обработчиками модулей (свой serviceKey в манифесте) и с реестром пакетов event-extensions.


Ключ: ad-sync
Описание в UI: Импорт и обновление доменных пользователей и групп из LDAP/AD.

Периодический или ручной импорт пользователей (и опционально групп) из LDAP/Active Directory в Portal: создание/обновление учёток auth_source=domain, поля профиля, состав групп.

  • Служба выключена, cron выкл.
  • Без настроенного LDAP строка в UI помечается недоступной (нельзя включить / запустить / задать расписание).
  1. Службы → Синхронизация AD → ⚙ Настройки (/services/ad-sync) — оба аккордеона открыты по умолчанию:
    • Подключение — URL, Base DN, Bind DN/пароль, фильтры входа/поиска, атрибут логина; badge статуса;
    • Настройка синхронизации:
      • фильтры и лимиты sync пользователей / групп;
      • поля профиля — чекбоксы встроенного каталога (givenName, sn, department, …) + «Выбрать все / Снять все»;
      • дополнительные поля — ручной маппинг: подпись, атрибут LDAP, ключ (например отчество → middleName);
      • флаги групп и деактивации (у каждого — значок с подсказкой).
  2. На вкладке Службы⋮ → Включить, при необходимости Расписание, Запустить.

Карточка пользователя с импортированными полями: Админка → Пользователи → /users/{id}.

Разделы UI: Группы и Пользователи (это разные настройки).

Флаг (UI)ConfigСмысл
Синхронизировать группы ADsyncGroupsИмпорт групп и состава участников. Если выкл — только пользователи
Удалять участников, которых нет в AD-группеremoveMissingGroupMembersИсключение из группы Portal; на учётки не влияет
Удалять группы Portal, пропавшие из ADremoveMissingGroupsУдаление ранее импортированных групп вне фильтра; локальные группы не трогает
Деактивировать пользователей, отсутствующих в ADcronDeactivateMissingis_active=false для domain-пользователей вне выборки sync; ручной запуск и cron. Не связано с составом групп

Отчество в стандартном каталоге AD/Portal нет — добавьте в «Дополнительные поля» (LDAP middleName или свой атрибут).

job_typeНазначение
adSync.runПолный прогон синхронизации

Ответ job (пример структуры): { users: { synced, created, updated, reactivated, deactivated }, groups: { … } }.

ДействиеЕсть?
Вкл/выклда (если LDAP настроен), через
Расписаниеда, модальное окно ⋮ → Расписание
Запуститьда (без confirm и без prompt; флаги из сохранённых настроек; результат — тост / вкладка Задания)
Настройки/services/ad-sync
Справка ?popover + ссылка на этот раздел

Синхронизация по cron и ручной запуск недоступны. Уже импортированные пользователи/группы остаются; вход через AD (если настроен отдельно) не обязательно зависит от этой службы.


Ключ: search-crawler
Описание в UI: Полная переиндексация (сверка). Повседневные изменения индексируются сразу при сохранении.

  • Инкремент: при CRUD узлов, списков, страниц, документов индекс обновляется сразу (не через эту службу).
  • Полный обход (searchCrawler.run): очистка/пересборка и сверка индекса — для ночной проверки или после «Очистить индекс».
  • Служба включена, cron 0 3 * * * (ежедневно 03:00).
job_typeНазначение
searchCrawler.runПолный обход индекса
ДействиеЕсть?
Вкл/выклда
Расписаниеда
Запуститьда («Полный обход»)
Очистить индексPOST /admin/search/clear или кнопка у службы (без постановки crawl)
Настройкинет; статус — Обзор → Обслуживание

Полный обход и его cron jobs падают. Инкрементальная индексация при сохранении контента обычно продолжает работать (она не идёт через portal_jobs этой службы).

Списки/библиотеки с отключённым поиском (SearchEnabled=false) в индекс не попадают.


Ключ: recycle-bin
Описание в UI: Автоочистка корзины удалённых элементов узлов (старше 30 дней).

Окончательно удаляет из корзины объекты старше срока хранения. Срок зашит в код: 30 дней (RetentionDays), не редактируется в portal_services.config.

Типы объектов корзины (среди прочих): элемент списка, страница, файл библиотеки, список, библиотека.

Мягкое удаление и UI корзины узла работают независимо от того, включена ли эта служба — служба отвечает только за автоpurge.

  • Служба включена, cron 0 4 * * *.
job_typeНазначение
recycleBin.purgeExpiredУдалить просроченные записи корзины
ДействиеЕсть?
Вкл/выклда
Расписаниеда
Запуститьда (немедленный purge)
Настройкинет; счётчик — Обзор → Обслуживание

Автоочистка и ручной purge через службу останавливаются; объекты могут копиться в корзине дольше 30 дней, пока службу не включат или не запустят вручную.


Ключ: event-extensions
Описание в UI: Пользовательские обработчики событий из пакетов .portalevent.

Реестр / gate для пакетных Event Receivers. Сама служба не «бегает по cron»: при установке пакета и привязке подписчика события ставят jobs с service_key (обычно event-extensions), Worker загружает DLL пакета и вызывает обработчик.

Рекомендуемый serviceKey в манифесте пакета: "event-extensions". Если указать другой ключ, в portal_services должна существовать и быть включена строка с этим ключом — иначе jobs упадут. Платформа не создаёт произвольные ключи автоматически (кроме upsert самой event-extensions при install).

  • Служба включена.
  • Расписания и ручного запуска у строки службы нет.
ДействиеЕсть?
Вкл/выклда (глобальный рубильник пакетных ER на этом ключе)
Расписаниенет
Запуститьнет
Управлениевкладки Event Receivers (пакеты, привязки к спискам/событиям)

Jobs с service_key=event-extensions не выполняются. Встроенные audit / notifications живут на своих ключах и этим тумблером не гасятся.


Ключ: timer-extensions
Описание в UI: Пользовательские задания по расписанию из пакетов .portaltimer.

Gate для пакетных Timer Jobs. Расписание задаётся у каждого экземпляра Timer Job (вкладка Timer Jobs), а не кнопкой «Расписание» у строки службы в списке Служб.

Планировщик: CronSchedulerService → постановка в portal_jobs → Worker → DLL пакета.

Рекомендуемый serviceKey в манифесте: "timer-extensions".

  • Служба включена.
  • У строки службы cron/run в UI нет.
ДействиеЕсть?
Вкл/выклда
Расписание службынет (расписание у экземпляров TJ)
Запустить службунет (запуск экземпляра — на вкладке Timer Jobs)
Управлениевкладка Timer Jobs

Пакетные timer-jobs с этим service_key не ставятся/не выполняются.


Ключ: list-export
Описание в UI: Фоновый экспорт элементов списка в XLSX через worker.

Два режима:

  1. listExport.run — пользователь запускает экспорт из UI списка → файл XLSX в object storage, срок жизни файла 24 часа (RetentionHours).
  2. listExport.purgeExpired — по cron (в БД) удаляет просроченные файлы экспорта.
  • Служба включена.
  • В БД: cron 0 3 * * *, job type listExport.purgeExpired.
  • В UI Службы: кнопок «Расписание» и «Запустить» нет (purge идёт фоном по данным из БД; экспорт — из списка).
job_typeНазначение
listExport.runСобрать XLSX по exportId (+ фильтр q)
listExport.purgeExpiredУдалить файлы старше 24 часов
ДействиеГде
Заказать экспортUI списка (не строка службы)
Вкл/выкл службыСлужбы — при выкл. и export, и purge падают
Расписание purgeтолько БД/API (PATCH /services/list-export), не кнопка в UI

Новые экспорты и очистка временных файлов через Worker не выполнятся.


9. portal-backup — Резервное копирование {#portal-backup}

Заголовок раздела «9. portal-backup — Резервное копирование {#portal-backup}»

Ключ: portal-backup
Описание в UI: Архивы PostgreSQL + S3 + portal_data в каталог на хосте.

Разрешает очередь бэкапов и расписание в портале. Сама служба не пишет архив — это делает отдельный backup-runner (контейнер / systemd / CLI), который забирает задания из portal_backups.

Состав типичного архива: PostgreSQL, файлы (S3), данные установки (portal_data). Подробности установки и томов: Резервное копирование и восстановление.

  • Служба включена.
  • Предложенное выражение cron 0 2 * * *, но cron_enabled=false, пока не настроены путь и проверка.

Не portal_jobs, а portal_backups: виды validate, backup, restore.
Тип backup.enqueueCron в cron — метка для планировщика; Worker job processor его не «крутит» как обычный job.

  1. Поднять backup-runner, смонтировать каталог (PORTAL_BACKUP_HOST_DIR / PORTAL_BACKUP_MOUNT_PATH для Docker).
  2. Службы → Резервное копирование → Настройки (/services/portal-backup):
    • аккордеон Резервное копирование — путь (в Docker — mount path), retention, validate, создание копии, журнал, Runner online;
    • аккордеон Восстановление — выбор копии из restorable, confirm, очередь restore.
  3. Расписание — Службы → ⋮ → Расписание (после validate + runner online).

Включение cron требует: служба вкл, путь проверен (lastValidatedOk), runner online.

ДействиеЕсть?
Вкл/выклда, через
Расписаниеда (после validate + runner), модальное окно
Запустить у строки службынет (POST /services/portal-backup/run отвергается)
Копия / validate / restore/services/portal-backup и backup API
Runner onlineстраница настроек + Обзор → Обслуживание (не таблица Служб)

Новые задания бэкапа/расписание из портала не ставятся. Уже лежащие архивы на диске не удаляются. CLI portal-cli backup может использоваться отдельно от UI-очереди — см. install-доку.


Ключ: jobs-cleanup
Описание в UI: Автоудаление записей журнала заданий старше срока хранения.

Чистит таблицу portal_jobs (журнал/очередь заданий), а не бизнес-данные портала. Удаляются завершённые записи (completed / failed / dismissed) старше retentionDays. Строки pending и running не трогает.

  • Служба включена, cron 0 5 * * *.
  • config.retentionDays = 30 (допустимо 1…3650).
job_typeНазначение
jobs.purgeOlderУдалить старые записи журнала
ДействиеЕсть?
Вкл/выклда
Расписаниеда
Запуститьда (немедленный purge)
Срок храненияАдминка → Задания → retention (GET/PUT /api/v1/jobs/settings/retention)

Журнал заданий перестанет автоматически сокращаться; ручной purge через службу тоже недоступен.


Встроенные службы из таблицы выше — фиксированный набор платформы.

Пакеты .portalevent / .portaltimer и модули (module.json) регистрируют обработчики и привязки. Обычно они используют serviceKey: "event-extensions" или "timer-extensions".

Если в манифесте указан собственный ключ (например korport.helpdesk.ticket-notifications):

  • подписчик/job ссылается на этот ключ;
  • в portal_services должна быть включённая строка с тем же service_key (иначе Worker откажет);
  • отдельная строка в списке «Службы» для кастомного ключа не создаётся сама при install пакета — за исключением upsert event-extensions / timer-extensions.

Управление пакетами: вкладки Event Receivers и Timer Jobs, не дублирующие строки в списке встроенных служб.


Добавление обработчика задания (разработка)

Заголовок раздела «Добавление обработчика задания (разработка)»
  1. Реализуйте обработчик в Worker (IJobHandler) или соберите пакет .portalevent / .portaltimer.
  2. Для платформенного типа — регистрация в BuiltinServices / JobProcessor.
  3. Для пакета — манифест + install; подписчик или экземпляр Timer Job через админку / API / module.json.

См. Job-модули, SDK Event Receiver, SDK Timer Job.

  • WORKER_POLL_INTERVAL_MS — интервал опроса очереди (по умолчанию 5000)
  • WORKER_BATCH_SIZE — размер пакета (по умолчанию 10)
  • CRON_RELOAD_INTERVAL_MS — перезагрузка расписания из БД (по умолчанию 60000)

Для почты и бэкапа дополнительно см. SMTP_*, PORTAL_BACKUP_* в установке и backup-restore.