keeper.go 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. package keeper
  2. /*
  3. Сторож системных сигналов.
  4. Мониторит ОС и части сервиса на завершение работы.
  5. В системе он должен быть только один.
  6. */
  7. import (
  8. "fmt"
  9. "os"
  10. "os/signal"
  11. "syscall"
  12. "wartank/pkg/types"
  13. )
  14. // Сторож -- сторож системных и внутренних сигналов
  15. type Сторож struct {
  16. kernel types.ИЯдро
  17. слог types.ИСлог
  18. chSys chan os.Signal
  19. }
  20. const (
  21. стрСторож = "сторож"
  22. )
  23. // НовСторож -- возвращает глобальный объект сторожа *Keeper
  24. func НовСторож(kernel types.ИЯдро) *Сторож {
  25. if kernel == nil {
  26. panic("GetKeeper(): IKernel is nil")
  27. }
  28. сам := &Сторож{
  29. kernel: kernel,
  30. слог: kernel.Слог(),
  31. chSys: make(chan os.Signal, 3),
  32. }
  33. ош := сам.kernel.Wg().Add(стрСторож)
  34. if ош != nil {
  35. panic(fmt.Sprintf("НовСторож(): при добавлении группы ожидания %q, ош=\n\t%v\n", стрСторож, ош.Error()))
  36. }
  37. signal.Notify(сам.chSys, os.Interrupt, syscall.SIGTERM)
  38. go сам.run()
  39. сам.слог.Отладка("NewKeeper()\n")
  40. return сам
  41. }
  42. // Слушает сигналы завершения изнутри и снаружи
  43. func (сам *Сторож) run() {
  44. сам.слог.Инфо("Keeper.run()\n")
  45. defer func() {
  46. сам.слог.Инфо("Keeper.run(): end\n")
  47. ош := сам.kernel.Wg().Done(стрСторож)
  48. if ош != nil {
  49. сам.слог.Ошибка("Keeper.run(): при удалении группы ожидания, ош=\n\t%w", ош)
  50. }
  51. }()
  52. select {
  53. case sig := <-сам.kernel.Done(): // глобальная отмена контекста
  54. сам.слог.Инфо("Keeper.run(): intern_sig=%q\n", sig)
  55. case sig := <-сам.chSys: // Системный сигнал закрытия
  56. сам.kernel.Отменить()
  57. сам.слог.Инфо("Keeper.run(): sys_sig=%v\n", sig)
  58. }
  59. }