При остановке приложения с КМА, приложение должно вызвать метод КМА stop(). При этом КМА должен дать сигнал агентам для их аккуратного завершения и отправить конечный результат работы в МА. Завершение КМА состоит из 3х фаз.

Статус

КомментарийДополнительный комментарий
  1. На 1й фазе для всех активных НЗ устанавливаем AgentContext#isCanceled в true. Для всех SCHED ставим флаг "прерван". Отменяем задачу ожидания запуска сигналов для запуска SCHED-агентов, чтобы новые агенты не запускать.
    Итераторы SCHED агентов должны перестать опрашивать очередные jms-сообщения. AsapAgentListener при получении сообщения не должен вызывать агент, а должен вызвать rollback() и закрыть свой JMSContext.
    ASAP и SCHED агенты теперь не получат новых сообщений, но могут обрабатывать последнее.
  2. На 2й фазе ждем 15 сек.
    Агенты могут завершить обработку последнего сообщения без InterruptedException и закоммитить его.
    Для завершенных SCHED шлем в МА статус прерывания на основании флага "прерван".
    Для завершенных ASAP шлем в МА статус успешного завершения.
    JMS-транзакции коммитим.
    Если все агенты завершились ранее 15 сек, то прерываем фазу 2 и пропускаем фазу 3.
  3. На 3й фазе принудительлно закрываем "зависших" агентов. Сначала для всех не завершенных SCHED вызываем Future.cancel(true). Затем для каждого не завершенного ASAP ставим флаг "прерван", вызываем thread.interrupt() и JMSContext.close() (т.к. JMSContext.close() блокируется в ожидании завершения ASAP-Listener). Но агенты могут всё ещё продолжить работать.
    JMSContext для SCHED закрывается при выходе из агента.
    Если получили любой эксепшен и установлен флаг "прерван", то шлем в МА статус "прерван". (Помимо InterruptedException могут быть ещё связанные с не возможностью закоммитить jms-транзакцию)
    ASAP на этой фазе тоже могут завершится без эксепшена - шлем статус успешного завершения.