ADR-014. Фоновая очередь обработки пакетов и шесть состояний
Обработку пакета (нормализация orthocover + опознание вида) запускает не оператор кнопкой, а фоновый воркер — автоматически при постановке пакета в очередь. Очередь — процессная, in-memory (канал идентификаторов + hosted-воркер с ограничением параллелизма); персистентность обеспечивает состояние пакета в БД, а не сам канал. К четырём состояниям ADR-008 добавляются два машинных: «обрабатывается» и «готов к проверке» — они снимают двойную роль «в очереди». Ручной повтор и восстановление недоделанных пакетов при рестарте сохраняются.
1. Контекст
ADR-008 «Четыре состояния пакета и две вкладки проверки» зафиксировал у пакета четыре хранимых состояния и упразднил пять подтверждаемых этапов. Но машинную половину жизненного цикла он оставил неявной, и по мере реализации это стало мешать.
Обработка запускается вручную. По ADR_SRV_005_ImageNormalizationOrthocover нормализация кадров (и, вместе с ней, опознание вида — ADR-015 «Опознание формы и страницы кадра») выполняется синхронно по кнопке «Обработать заново». Оператор обязан помнить, что после сдачи пакета его надо ещё и запустить; до нажатия пакет лежит нетронутым.
Состояние «в очереди» перегружено. Одним значением обозначены и «ждёт, пока его возьмут в обработку», и «обработан, ждёт, пока его возьмёт оператор». Отличить их можно только по наличию нормализованных кадров — скрытый признак, из-за которого индикатор очереди (FR-009 «Очередь обработки», «чья очередь ходить») неоднозначен.
После рестарта ничего не возобновляется. Синхронная обработка живёт в рамках запроса; прерванный пакет остаётся полуобработанным без механизма подхвата.
Родственный сервис оцифровки biblioservice-dispatcher решает это иначе: пакет после отправки автоматически ставится в фоновую очередь (in-memory семафор + фоновые задачи), воркер его обрабатывает под ограничением параллелизма, а при старте приложения недоделанные пакеты (в статусах «в очереди» / «обрабатывается») переочередиваются. Переносим этот подход, адаптировав под .NET-конвейер ICD.
2. Решение
Обработка запускается автоматически. При постановке пакета в очередь (отправка из ввода) он попадает в фоновую очередь и обрабатывается воркером без действия оператора. Оператор вступает в работу уже с готовым результатом. Ручной повтор («Обработать заново») сохраняется как явная команда — для пересъёмки, правки состава кадров и отклонения вида ИК; в этих случаях пакет возвращается в очередь по команде пользователя (как требует FR-009 «Очередь обработки»), а не автоматически на каждое движение кадра.
Очередь — процессная, in-memory. Канал идентификаторов пакетов + hosted-воркер, ограниченный параллелизмом (настройка, по умолчанию 1). Сам канал не персистентен — источник истины о том, что пакет ждёт обработки, это его состояние в БД; канал лишь будит воркер. Постановка в канал выполняется после фиксации пакета в БД; воркер обрабатывает пакет в собственной единице работы, а не в контексте запроса-отправителя.
Состояний становится шесть. К прежним — в очереди, проверка, завершён, ошибка — добавляются два машинных:
| Состояние | Когда наступает |
|---|---|
| Обрабатывается | воркер прогоняет нормализацию и опознание вида |
| Готов к проверке | система закончила обработку, пакет ждёт оператора |
Это снимает двойную роль «в очереди»: теперь «в очереди» = «ждёт воркера», «готов к проверке» = «ждёт оператора». Оба новых состояния машинные — пользователь их не подтверждает, переход происходит сам. Поэтому тезис ADR-008 «Четыре состояния пакета и две вкладки проверки» — «нет пяти подтверждаемых этапов» — сохраняется: мы делаем наблюдаемой системную половину жизненного цикла, а не возвращаем подтверждения.
Машина состояний:
в очереди ──► обрабатывается ──┬─(успех)─► готов к проверке ──► проверка ──► завершён
▲ └─(вид не опознан)─► ошибка │
└──── ручной повтор / отклонение вида / правка состава ◄────────┘
Восстановление при старте. Пакеты в состояниях «в очереди» и «обрабатывается» переочередиваются (ставятся в канал заново); «готов к проверке» не трогаются — они уже обработаны. Управляется настройкой (локально можно отключить, чтобы не перезапускать зависшие пакеты при отладке).
3. Обоснование
Автоматический запуск убирает лишний шаг и класс ошибок «забыл обработать»: сдача пакета и есть запрос на обработку. Ручной повтор остаётся не как основной путь, а как явное действие там, где исходные данные изменились и прежний разбор недействителен, — это ровно тот случай, для которого FR-009 требует постановки в очередь командой пользователя.
Отдельные машинные состояния стоят одного дополнительного перечислимого значения на каждое, зато делают очередь честной: индикатор «чья очередь ходить» отвечает однозначно, а скрытый признак «есть ли нормализованные кадры» перестаёт нести смысл состояния. Цена — та же, что принял ADR-008: состояний по-прежнему наперечёт, переходы явные.
Очередь в памяти процесса выбрана намеренно простой. biblioservice-dispatcher показывает, что для одного инстанса связки «канал + воркер + семафор + восстановление при старте» достаточно; вводить брокер или таблицу-очередь означало бы платить за мультиинстанс, которого пока нет.
4. Следствия
Перечисление состояний расширяется до шести (PacketState): добавляются «обрабатывается» и «готов к проверке». Обновляются доменная сущность InputPacket (таблица состояний, инварианты переходов) и требование FR-009 «Очередь обработки» (индикатор и отбор — по шести состояниям).
Запуск нормализации по ADR_SRV_005_ImageNormalizationOrthocover
уточняется: основной запуск — автоматический (воркер при постановке в очередь), ручной остаётся
повтором. Абстракция IImageNormalizer не меняется.
Появляется инфраструктурный артефакт очереди — канал + hosted-воркер + ограничение параллелизма и хук восстановления при старте (backend-спека / инфраструктура). Хендлер отправки пакета после фиксации ставит идентификатор в канал; воркер работает в собственной единице работы.
UI очереди (FR-009 «Очередь обработки» / страница очереди) показывает новые состояния и не требует от оператора ручного запуска обработки для штатного пути.
Компромисс — один процесс. Очередь в памяти не переживает мультиинстанс: у каждого инстанса своя. Как и локальный кэш контекста в ADR_011_AbacAuthorization, вынос в общий брокер/таблицу оставлен точкой расширения на случай горизонтального масштабирования.
5. Рассмотренные альтернативы
Оставить запуск ручным (ничего не менять). Отвергнуто: сохраняется шаг «не забудь обработать» и перегруженное «в очереди»; наблюдаемости и восстановления нет.
Не вводить машинные состояния, отличать по наличию нормализованных кадров. Одно «в очереди» на оба смысла. Отвергнуто: состояние очереди становится скрытым и выводимым, а индикатор «чья очередь ходить» — неоднозначным; оператор не видит, обрабатывается пакет или уже готов.
Брокер (Redis/RabbitMQ) или таблица-очередь в БД. Отвергнуто на текущем этапе: один инстанс, in-memory + восстановление при старте достаточно (подтверждено biblioservice-dispatcher). Оставлено точкой расширения при мультиинстансе — аддитивно, без слома модели состояний.
Автозапуск без ручного повтора. Отвергнуто: пересъёмка, правка состава и отклонение вида требуют явной команды пользователя (FR-009, «Повторная обработка») — иначе каждое движение кадра запускало бы обработку заново.
Структурные связи
Используется
- Handler Handler: ClassifyFrame
Связанные артефакты
Документы
- Доменная сущность Пакет ввода
- ADR ADR-007. Ввод без плана: вид ИК определяет Сервис
- ADR ADR-008. Четыре состояния пакета вместо пяти этапов
- ADR ADR-009. Обращение к модели распознавания
- ADR ADR-011. Разграничение доступа по модели ABAC (claims → функции → группы)
- ADR ADR-015. Опознание формы и страницы кадра
- ADR ADR-SRV-005. Нормализация изображений (orthocover)
- FR FR-009. Очередь обработки пакетов
Перечисления
- Перечисление PacketState