ctrlc.go 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. package ctrlc
  2. import (
  3. "context"
  4. "fmt"
  5. "os"
  6. "os/signal"
  7. "syscall"
  8. "time"
  9. )
  10. const C_ICON_START = "🌟"
  11. const C_ICON_WARN = "⚡️"
  12. const C_ICON_HOT = "🔥"
  13. const C_ICON_MAG = "✨"
  14. const C_ICON_SC = "🌳"
  15. type Iface interface {
  16. Shutdown(ctx context.Context) error
  17. }
  18. func App(t time.Duration, f func(ctx context.Context) *[]Iface) {
  19. stop := make(chan os.Signal)
  20. signal.Notify(stop, syscall.SIGTERM)
  21. signal.Notify(stop, syscall.SIGINT)
  22. fmt.Printf(
  23. C_ICON_START+" %s\n",
  24. cly(
  25. fmt.Sprintf(
  26. "Application started (%d sec)",
  27. t/time.Second,
  28. ),
  29. ),
  30. )
  31. sctx, shutdown := context.WithCancel(context.Background())
  32. ifaces := f(sctx)
  33. switch val := <-stop; val {
  34. case syscall.SIGINT:
  35. fmt.Printf(
  36. "\r"+C_ICON_WARN+" %s\n",
  37. cly(
  38. fmt.Sprintf(
  39. "Shutting down (interrupt) (%d sec)",
  40. t/time.Second,
  41. ),
  42. ),
  43. )
  44. case syscall.SIGTERM:
  45. fmt.Printf(
  46. C_ICON_WARN+" %s\n",
  47. cly(
  48. fmt.Sprintf(
  49. "Shutting down (terminate) (%d sec)",
  50. t/time.Second,
  51. ),
  52. ),
  53. )
  54. default:
  55. fmt.Printf(
  56. C_ICON_WARN+" %s\n",
  57. cly(
  58. fmt.Sprintf(
  59. "Shutting down (%d sec)",
  60. t/time.Second,
  61. ),
  62. ),
  63. )
  64. }
  65. shutdown()
  66. errors := false
  67. ctx, cancel := context.WithTimeout(context.Background(), t)
  68. for _, iface := range *ifaces {
  69. if err := iface.Shutdown(ctx); err != nil {
  70. errors = true
  71. fmt.Printf(
  72. C_ICON_HOT+" %s\n",
  73. clr(fmt.Sprintf(
  74. "Shutdown error (%T): %s",
  75. iface,
  76. err.Error(),
  77. )),
  78. )
  79. }
  80. }
  81. cancel()
  82. if errors {
  83. fmt.Printf(
  84. C_ICON_MAG+" %s\n",
  85. cly(
  86. fmt.Sprintf(
  87. "Application exited with errors (%d sec)",
  88. t/time.Second,
  89. ),
  90. ),
  91. )
  92. os.Exit(1)
  93. } else {
  94. fmt.Printf(
  95. C_ICON_SC+" %s\n",
  96. clg(
  97. fmt.Sprintf(
  98. "Application exited successfully (%d sec)",
  99. t/time.Second,
  100. ),
  101. ),
  102. )
  103. }
  104. }