# Фоновая служба

`GsForegroundService` выполняет периодическую работу с отдельной `GsSession` и постоянным системным уведомлением
Она не создаёт `StateManager`, состояние, контроллер представления или навигатор
Жизненный цикл службы не зависит от окна приложения

## Ответственность базового класса

- Вызывает `startForeground` до чтения настроек и сетевых запросов, в том числе при повторном запуске
- При повторном запуске не создаёт второй рабочий поток и сессию
- При восстановлении с `intent == null` заново начинает работу
- Создаёт собственную сессию на выделенном потоке, реестр зависимостей получает из `GsRegistryBootstrap`
- Последовательно вызывает `doWork(session)` и `awaitNextIteration(session)`
- После успешного прохода вызывает `commit()`, при ошибке или отмене - `rollback()`
- Отменяет работу через `InterruptingLock` и закрывает сессию на её рабочем потоке
- В `onDestroy` и `onTimeout` останавливается без ожидания рабочего потока на главном

## Прикладная служба

Наследник задаёт системное уведомление, его тип и интервал проверки
Хранилище настроек предоставляет через `provideDataStore()`, работу описывает в `doWork(session)`
Возврат `false` завершает службу, `true` продолжает цикл

По умолчанию `awaitNextIteration` ждёт `intervalMillis`
Наследник может переопределить ожидание, например чтобы изменение интервала в настройках сразу вступало в силу

В EAM `PushService` проверяет настройку `serviceState` в начале прохода
Для получения уведомлений использует `EamPushTransportPkg` из собственной сессии
После системного показа передаёт данные экрану через [внешнее событие](055_Внешние_события.md)

## Сессия и потоки

`doWork` допускает приостановку выполнения для работы с хранилищем настроек
Базовый класс вызывает его через `runBlocking` на выделенном потоке
После приостановки продолжение возвращается на этот же поток, сессия и её транзакции не меняют владельца

Нельзя запускать параллельные задачи с доступом к этой сессии
Нельзя подставлять сессию окна приложения или основного `StateManager`
Доступ к контроллерам экранов и навигации из службы не предоставляется
В EAM показ системных уведомлений выполняется на главном потоке

## Доступ к БД

По умолчанию БД не подключена к сессии службы
`provideDatabase()` нужен только службам с собственным сценарием работы с БД

Служба уведомлений EAM не записывает историю в БД и не подключает Room к своей сессии
Она отдельно читает зафиксированные отметки прочтения через `EamNotificationDao`, чтобы не показывать прочитанное повторно
Сохранение уведомлений выполняется задачей состояния через его сессию

Общая `RoomDatabase` сама по себе не согласует транзакции службы и основного `StateManager`
Совместная работа с БД и `FileManager` требует отдельного согласования транзакций и файловых операций

## Остановка и отмена запросов

Остановку отправляют через `Context.stopService`, а не через `startForegroundService` с командой остановки

При отмене `BaseRestGate` отменяет сетевой запрос `OkHttp Call` и закрывает ответ, пришедший после отмены
Подписка на отмену сохраняется до закрытия тела ответа
При получении ответа `Response` напрямую вызывающий код обязан закрыть его через `use`

См также: [сессия](060_Сессия.md), [хранение данных](070_Хранение_данных.md)
