Остановка поднадзорного актора
Остановка поднадзорного актора — полное завершение работы актора, за которым следит другой актор (надзиратель).
Бывают два взаимоисключающих случая:
- Нам безразлично, грубо будет остановлен актор или нет. Грубая остановка не приведёт к потере важных данных или другим нежелательным последствиям.
- Мы переживаем за возможные нежелательные последствия. Например, при запуске актор превращает DETS-таблицу в ETS (которая, как ей и положено, хранится только в оперативной памяти), а при завершении должно произойти обратное: ETS-таблица превращается в DETS и сохраняется на диске.
В первом случае в спецификации актора (когда он запускается надзирателем) достаточно указать shutdown => brutal_kill. Пример спецификации:
#{id => foo,
start => {foo, start_link, []},
type => worker,
restart => permanent,
shutdown => brutal_kill}
Во втором случае надо предусмотреть следующее:
- Надзиратель теперь должен дать поднадзорному актору время для улаживания своих дел перед кончиной. Поэтому в спецификации поднадзорного будет что-то вроде
shutdown => 1_000. Здесь 1_000 — время таймаута в миллисекундах. Если через это время актор не завершит свою работу, он будет грубо остановлен с помощью exit(Child,kill). Время таймаута можно установить как infinity.
- Актор должен быть системным (уметь перехватывать EXIT-сообщения). Для этого где-нибудь в теле init следует добавить
process_flag(trap_exit, true).
- У актора надо предусмотреть обработку EXIT-сообщений: когда получено, надо завершиться должным образом. Если актор создан на основе обобщённого шаблона — согласно принципам OTP, тогда в нашем акторе для этой цели просто вставляем колбек terminate с той или иной арностью (у gen_server и gen_event — 2, у gen_statem — 3). Функция terminate должна вернуть атом ok. Если будем обрабатывать EXIT-сообщение с помощью
receive ... end, тогда надо предусмотреть шаблон для сообщений {'EXIT',Pid,shutdown}. Получив такое сообщение, актор должен уладить перед кончиной свои дела, после чего вызвать exit(shutdown).
Copyright © 2025 Алексей Карманов