ctrlc.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. package ctrlc
  2. import (
  3. "context"
  4. "fmt"
  5. "os"
  6. "os/signal"
  7. "strings"
  8. "syscall"
  9. "time"
  10. )
  11. const C_ICON_START = "🌟"
  12. const C_ICON_WARN = "⚡️"
  13. const C_ICON_HOT = "🔥"
  14. const C_ICON_MAG = "✨"
  15. const C_ICON_SC = "🌳"
  16. type Iface interface {
  17. Shutdown(ctx context.Context) error
  18. }
  19. type CallbackFunc func(ctx context.Context, shutdown context.CancelFunc) *[]Iface
  20. func App(t time.Duration, f CallbackFunc) {
  21. stop := make(chan os.Signal)
  22. signal.Notify(stop, syscall.SIGTERM)
  23. signal.Notify(stop, syscall.SIGINT)
  24. fmt.Printf(
  25. icon_start(UseColors())+"%s\n",
  26. cly(
  27. UseColors(),
  28. fmt.Sprintf(
  29. "Application started (%d sec)",
  30. t/time.Second,
  31. ),
  32. ),
  33. )
  34. sctx, shutdown := context.WithCancel(context.Background())
  35. ifaces := f(sctx, shutdown)
  36. select {
  37. case <-sctx.Done():
  38. fmt.Printf(
  39. "\r"+icon_warn(UseColors())+"%s\n",
  40. cly(
  41. UseColors(),
  42. fmt.Sprintf(
  43. "Shutting down (application) (%d sec)",
  44. t/time.Second,
  45. ),
  46. ),
  47. )
  48. case val := <-stop:
  49. switch val {
  50. case syscall.SIGINT:
  51. fmt.Printf(
  52. "\r"+icon_warn(UseColors())+"%s\n",
  53. cly(
  54. UseColors(),
  55. fmt.Sprintf(
  56. "Shutting down (interrupt) (%d sec)",
  57. t/time.Second,
  58. ),
  59. ),
  60. )
  61. case syscall.SIGTERM:
  62. fmt.Printf(
  63. icon_warn(UseColors())+"%s\n",
  64. cly(
  65. UseColors(),
  66. fmt.Sprintf(
  67. "Shutting down (terminate) (%d sec)",
  68. t/time.Second,
  69. ),
  70. ),
  71. )
  72. default:
  73. fmt.Printf(
  74. icon_warn(UseColors())+"%s\n",
  75. cly(
  76. UseColors(),
  77. fmt.Sprintf(
  78. "Shutting down (%d sec)",
  79. t/time.Second,
  80. ),
  81. ),
  82. )
  83. }
  84. }
  85. shutdown()
  86. errors := false
  87. ctx, cancel := context.WithTimeout(context.Background(), t)
  88. for _, iface := range *ifaces {
  89. if err := iface.Shutdown(ctx); err != nil {
  90. errors = true
  91. fmt.Printf(
  92. icon_hot(UseColors())+"%s\n",
  93. clr(
  94. UseColors(),
  95. fmt.Sprintf(
  96. "Shutdown error (%T): %s",
  97. iface,
  98. err.Error(),
  99. ),
  100. ),
  101. )
  102. }
  103. }
  104. cancel()
  105. if errors {
  106. fmt.Printf(
  107. icon_mag(UseColors())+"%s\n",
  108. cly(
  109. UseColors(),
  110. fmt.Sprintf(
  111. "Application exited with errors (%d sec)",
  112. t/time.Second,
  113. ),
  114. ),
  115. )
  116. os.Exit(1)
  117. } else {
  118. fmt.Printf(
  119. icon_sc(UseColors())+"%s\n",
  120. clg(
  121. UseColors(),
  122. fmt.Sprintf(
  123. "Application exited successfully (%d sec)",
  124. t/time.Second,
  125. ),
  126. ),
  127. )
  128. }
  129. }
  130. func UseColors() bool {
  131. useColors := strings.Contains(
  132. fmt.Sprintf("%s", os.Args),
  133. "--color=always",
  134. )
  135. if !useColors {
  136. useColors = strings.Contains(
  137. fmt.Sprintf("%s", os.Args),
  138. "-color=always",
  139. )
  140. }
  141. if !useColors {
  142. useColors = strings.Contains(
  143. fmt.Sprintf("%s", os.Args),
  144. "color=always",
  145. )
  146. }
  147. if !useColors {
  148. useColors = strings.Contains(
  149. fmt.Sprintf("%s", os.Args),
  150. "--color always",
  151. )
  152. }
  153. if !useColors {
  154. useColors = strings.Contains(
  155. fmt.Sprintf("%s", os.Args),
  156. "-color always",
  157. )
  158. }
  159. if !useColors {
  160. useColors = strings.Contains(
  161. fmt.Sprintf("%s", os.Args),
  162. "color always",
  163. )
  164. }
  165. return !IS_WIN_PLATFORM && useColors
  166. }