Кнопка «Остановить» исчезла, индикатор погас, пользователь закрыл вкладку. Через несколько минут на сервере всё ещё крутится обработка документов, работают дочерние задания и растёт счёт за вычисления. В интерфейсе задача закончилась. В системе она продолжает жить.
Представим такой учебный сценарий: ИИ-сотруднику поручили сравнить несколько сотен технических описаний и подготовить сводку. Затем выяснилось, что выбрана неправильная папка. Пользователь отменил поручение, но каждый запущенный обработчик уже получил собственный список файлов. Простое прекращение ответа в чате до них не дошло.
Для длительных агентных сценариев отмена должна быть самостоятельной возможностью системы. Ей нужны адресат, правила распространения, подтверждение и понятный результат. Разберём, как устроить такую остановку без обещания мгновенно вернуть всё в исходное состояние.
Определите смысл остановки
У слова «стоп» несколько технических смыслов. Можно прекратить показывать текст, перестать ждать ответ, запретить запуск следующих шагов или завершить уже работающие вычисления. Это разные действия, и пользователь не обязан знать их устройство.
Полезно разделить обычную отмену и аварийную остановку. Обычная позволяет исполнителям освободить ресурсы и завершить короткие служебные операции. Аварийная ограничивает выполнение жёстче, когда продолжение опаснее потери промежуточного результата. Для неё нужны отдельные права и последствия, понятные дежурному инженеру.
Закрытие вкладки также не обязательно означает отмену: длительный отчёт часто специально запускают в фоне. Это решение продукта, а не неизбежное свойство соединения.
Дайте поручению устойчивый адрес
Команда отмены должна относиться к конкретному запуску. У запроса на подготовку отчёта есть идентификатор, владелец, текущая стадия и список дочерних работ. Формулировка «останови последний анализ» недостаточна, если одновременно работают несколько вкладок или несколько сотрудников.
Сохраняйте состояние запуска вне памяти отдельного процесса. Иначе перезапуск сервера уничтожит сведения об отмене, а восстановившийся обработчик продолжит работу. Для небольшой системы достаточно существующей базы задач с полями «отмена запрошена», «причина», «кто запросил» и «время запроса».
Право отмены проверяется сервером. Знание номера задания не должно позволять остановить чужую работу. Администратору можно дать более широкие полномочия, но его действие следует отличать от решения владельца поручения.
Если задача уже завершена, интерфейс возвращает её фактический результат. Поздняя команда отмены не превращает успешное выполнение в отменённое: иначе журнал перестанет объяснять, что происходило на самом деле.
Сначала закройте выдачу новой работы
После фиксации отмены планировщик должен перестать выдавать следующие шаги. Обработчик проверяет это состояние при получении задания и непосредственно перед запуском нового дочернего процесса. Задание в очереди может оставаться физически записанным, но получать статус «пропущено из-за отмены» при попытке исполнения.
Между проверкой и фактическим запуском есть короткое окно гонки. Для критичных операций решение о запуске и проверку состояния поручения нужно согласовать через общий механизм управления заданиями. Одной проверки переменной в начале длинного цикла недостаточно.
Для уже начавшихся операций действует следующий уровень: распространение сигнала и кооперативное завершение. Поэтому корректная гарантия звучит как конкретное правило выдачи работы, а не обещание, что после нажатия кнопки нигде не выполнится ни одной инструкции.
Распространяйте отмену по дереву исполнения
У основного задания могут быть параллельный поиск, распознавание файлов, обращения к модели и сборка результата. Если известен только главный процесс, его остановка оставит остальных без присмотра.
Передавайте дочерним работам идентификатор родителя и контекст отмены. Контекст объясняет, разрешено ли продолжение и какой срок остался. Дочерний исполнитель проверяет его сам; родитель собирает подтверждения завершения. Задача считается остановленной в управляемой части системы, когда не осталось активных работ, которые должны были подчиниться команде.
Это согласуется с документацией gRPC: библиотека не может произвольно прервать прикладной обработчик, а длительная серверная работа должна замечать отмену и прекращаться. Распространение отмены на исходящие вызовы зависит от реализации и языка, его нельзя предполагать автоматически.
Отдельно решите судьбу общей работы. Если один поиск используется двумя независимыми отчётами, отмена первого не должна разрушить второй. Общий ресурс имеет собственный жизненный цикл, а отменённое поручение отказывается от своей подписки на результат.
![]()
Источник изображения: AIHUMMER
Выберите безопасные точки остановки
Кооперативная отмена означает, что исполнитель регулярно проверяет просьбу завершиться. Для обработки документов удобные точки находятся между файлами, страницами или пакетами. Для длительного вычисления нужны проверки внутри цикла, иначе реакция наступит только после его окончания.
Размер пакета влияет на скорость остановки. Если один пакет обрабатывается несколько минут, обещать реакцию за секунду нельзя. Уменьшение пакетов ускоряет отмену, но может увеличить накладные расходы. Выбирайте размер по измерениям и последствиям продолжения ненужной работы.
Проверка требуется и перед дорогим внешним вызовом. Когда результат уже никому не нужен, запускать ещё один анализ бессмысленно. При этом начатый удалённый запрос прекращается только способами, которые поддерживает соответствующий сервис.
В Python механизм asyncio доставляет CancelledError при ближайшей возможности. Документация рекомендует освобождать ресурсы через try/finally, а перехваченную отмену обычно передавать дальше после очистки. Это конкретный механизм одного рантайма, а не универсальная гарантия остановки всех подключённых систем.
Не превращайте обработку ошибок в запрет отмены
Распространённая архитектурная ошибка – общий обработчик, который любой неуспех считает поводом продолжить. Для отменённого задания он снова запускает вычисление, выбирает другой инструмент или отправляет запрос запасной модели. Пользователь нажимает «стоп», а система становится ещё настойчивее.
В собственной модели состояния различайте ошибку выполнения и намеренное прекращение. Ошибка может требовать восстановления. Отмена означает, что прежняя цель больше не должна преследоваться в разрешённой части сценария.
Проверьте обёртки инструментов, фоновые исполнители и служебные функции. Команда должна доходить через все уровни, а не теряться в адаптере библиотеки. Особенно внимательно изучите блокирующие операции и отдельные процессы: отмена ожидающей корутины сама по себе не означает завершения работы, которую она поручила другому исполнителю.
Не записывайте каждую добровольную остановку в аварийную статистику. Иначе инженеры начнут расследовать штатное действие пользователя, а реальные сбои потеряются среди предупреждений.
Ограничьте жизнь задания даже без команды пользователя
Пользователь может уйти, забыть об отчёте или потерять связь. Поэтому длительному заданию полезен общий предел времени. Лимит отдельного вызова и срок всего поручения решают разные задачи.
Предположим, обработке отвели десять минут. После восьми минут дочерний шаг не должен получать новый независимый десятиминутный бюджет. Ему достаётся оставшееся время с резервом на завершение. Для каждого этапа можно установить более короткий предел, но он не расширяет общий срок.
Документация gRPC отдельно рекомендует явно задавать реалистичные сроки вызовов. Она также объясняет передачу оставшегося бюджета времени между сервисами и ответственность приложения за прекращение запущенной работы.
В распределённой системе учитывайте различие часов. Используйте возможности выбранного протокола или заранее определённый способ передачи оставшегося времени. Не смешивайте без объяснения абсолютную дату одного сервера с локальным таймером другого.
Завершайте работу аккуратно и с ограничением времени
После сигнала отмены остаются временные файлы, открытые соединения, занятые слоты и незавершённые записи прогресса. Их нужно привести в понятное состояние. Но служебное завершение тоже не должно продолжаться бесконечно.
Если исполнитель не остановился, система переводит задачу в состояние, требующее вмешательства, и применяет предусмотренный способ принудительного завершения. Уничтожение отдельного рабочего процесса может быть допустимо; остановка общего сервиса с чужими заданиями требует другого решения.
Промежуточный результат маркируйте явно. «Обработано 37 документов из 200, итоговые выводы не сформированы» полезнее аккуратного отчёта без предупреждения о неполноте. Черновые выводы не должны попадать в канал публикации как окончательные.
Пауза требует точки восстановления
Пауза и отмена создают разные ожидания. После паузы пользователь рассчитывает продолжить с того же места. После отмены он может запустить новое поручение с другими исходными данными. Смешение этих действий приводит к странным результатам: новый анализ использует половину старой выборки, хотя пользователь уже сменил папку.
Если нужен режим паузы, заранее определите сохраняемое состояние. Для анализа документов это может быть список завершённых файлов, параметры задания и версия исходной выборки. Перед продолжением система проверяет, не изменились ли документы и доступ к ним. При несовместимых изменениях она предлагает новый запуск, а не незаметно склеивает разные результаты.
Проверьте возможности каждого инструмента
Перед запуском автоматизации составьте короткий паспорт подключённых операций. Для каждой укажите, принимает ли она сигнал отмены, можно ли узнать её состояние и сколько обычно занимает выход. Отдельно пометьте операции, которые продолжаются на стороне поставщика после разрыва соединения.
Такой паспорт помогает определить честный результат остановки. Если сервис распознавания позволяет только дождаться ответа, система прекращает следующие этапы и помечает текущую работу как ожидающую завершения. Она не должна сообщать, что удалённый сервер уже освободил ресурсы.
Проверяйте паспорт при замене библиотеки, поставщика или способа запуска. Одинаково названный метод отмены у двух инструментов может иметь разный смысл. Для критичного сценария закрепите это поведение испытанием: управляемо задержите ответ и проверьте, какой процесс действительно прекратился. Если наблюдать удалённую работу невозможно, именно эта неопределённость должна оставаться в описании ограничения.
Подтвердите остановку понятным сообщением
Сразу после команды можно показать «Остановка запрошена». Это подтверждает приём запроса, но не завершение вычислений. Следующий статус должен отражать полученные сведения от исполнителей.
Для обычного сценария достаточно нескольких состояний: выполняется, останавливается, остановлено, завершено, требуется проверка. Последнее пригодится, когда контролируемые процессы завершились, а состояние внешней операции ещё неизвестно. Конкретные технические подробности доступны инженеру; пользователю нужен понятный смысл.
Не обещайте возврат уже потраченных вычислительных ресурсов или отмену списаний у поставщика. Условия оплаты и возможность удалённой остановки проверяются отдельно. Корректная кнопка управляет процессом в пределах доступного контроля.
Проверьте отмену в неудобных моментах
Испытание на пустом задании почти ничего не доказывает. Подготовьте небольшой набор сценариев с искусственными задержками и известным количеством дочерних работ.
Сначала отмените задание до его получения исполнителем. Затем – во время параллельной обработки, ожидания модели, сохранения промежуточного результата и аккуратного завершения. Отдельно повторите проверку после перезапуска сервера и при временной недоступности одного обработчика.
Проверяйте наблюдаемые последствия: новые шаги перестали выдаваться, дочерние работы завершились, ресурсы освободились, частичный отчёт не опубликован как полный. После восстановления связи отмена не должна забываться.
Измеряйте время от принятия команды до прекращения управляемых вычислений, число оставшихся активных работ и объём ресурсов, потраченных после отмены. Для последней метрики задайте источник измерения: биллинг поставщика может приходить позже, чем внутренние события. Разные величины нельзя выдавать за одну точную цифру.
Начните с одного длительного сценария
Выберите процесс, отмена которого уже понятна пользователю: анализ папки, сбор аналитической сводки или обработка входящей пачки документов. Выпишите исполнителей, дочерние задания и внешние вызовы. Напротив каждого укажите, как он узнает об остановке и чем подтверждает завершение.
Затем реализуйте сохранение команды, запрет новой работы, проверку в безопасных точках и итоговое сообщение. Проведите испытание с задержанным исполнителем. Если он продолжает работать после того, как интерфейс сообщил об остановке, исправляйте договор и управление заданием вместе.
ИИ-сотрудник становится управляемым, когда компания умеет не только поручать ему задачи, но и отзывать поручение с понятными последствиями. Начните с вопроса к своей системе: если сейчас нажать «стоп», кто конкретно получит эту команду и где появится доказательство, что она исполнена?
Изображение на обложке: AIHUMMER
Комментарии