cron_helper.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. package cron_helper
  2. import (
  3. "github.com/allanpk716/ChineseSubFinder/internal/logic/downloader_helper"
  4. "github.com/allanpk716/ChineseSubFinder/internal/logic/pre_download_process"
  5. "github.com/allanpk716/ChineseSubFinder/internal/pkg/log_helper"
  6. "github.com/allanpk716/ChineseSubFinder/internal/pkg/settings"
  7. "github.com/robfig/cron/v3"
  8. "sync"
  9. "time"
  10. )
  11. type CronHelper struct {
  12. fullSubDownloadProcessing bool // 这个是核心耗时函数执行的状态
  13. fullSubDownloadProcessingLock sync.Mutex
  14. cronHelperRunning bool // 这个是定时器启动的状态,它为true,不代表核心函数在执行
  15. cronHelperRunningLock sync.Mutex
  16. c *cron.Cron
  17. dh *downloader_helper.DownloaderHelper
  18. }
  19. func NewCronHelper() (*CronHelper, error) {
  20. ch := CronHelper{}
  21. ch.c = cron.New(cron.WithChain(cron.SkipIfStillRunning(cron.DefaultLogger)))
  22. // 定时器
  23. entryID, err := ch.c.AddFunc("@every "+settings.GetSettings().CommonSettings.ScanInterval, ch.coreSubDownloadProcess)
  24. if err != nil {
  25. log_helper.GetLogger().Errorln("CronHelper Cron entryID:", entryID, "Error:", err)
  26. return nil, err
  27. }
  28. return &ch, nil
  29. }
  30. // Start 开启定时器任务,这个任务是非阻塞的,coreSubDownloadProcess 仅仅可能是这个函数执行耗时而已
  31. // runImmediately == false 那么 ch.c.Start() 是不会阻塞的
  32. func (ch *CronHelper) Start(runImmediately bool) {
  33. ch.cronHelperRunningLock.Lock()
  34. ch.cronHelperRunning = true
  35. ch.cronHelperRunningLock.Unlock()
  36. // 是否在定时器开启前先执行一次任务
  37. if runImmediately == true {
  38. log_helper.GetLogger().Infoln("First Time coreSubDownloadProcess Start")
  39. ch.coreSubDownloadProcess()
  40. log_helper.GetLogger().Infoln("First Time coreSubDownloadProcess End")
  41. } else {
  42. log_helper.GetLogger().Infoln("RunAtStartup: false, so will not Run At Startup, wait",
  43. settings.GetSettings().CommonSettings.ScanInterval, "to Download")
  44. }
  45. log_helper.GetLogger().Infoln("CronHelper Start...")
  46. log_helper.GetLogger().Infoln("Next Sub Scan Will Process After", settings.GetSettings().CommonSettings.ScanInterval)
  47. ch.c.Start()
  48. }
  49. // Stop 会阻塞等待任务完成
  50. func (ch *CronHelper) Stop() {
  51. fullSubDownloadProcessing := false
  52. ch.fullSubDownloadProcessingLock.Lock()
  53. fullSubDownloadProcessing = ch.fullSubDownloadProcessing
  54. ch.fullSubDownloadProcessingLock.Unlock()
  55. if fullSubDownloadProcessing == true {
  56. if ch.dh != nil {
  57. ch.dh.Cancel()
  58. }
  59. // Stop stops the cron scheduler if it is running; otherwise it does nothing.
  60. // A context is returned so the caller can wait for running jobs to complete.
  61. nowContext := ch.c.Stop()
  62. select {
  63. case <-time.After(5 * time.Minute):
  64. log_helper.GetLogger().Warningln("Wait over 5 min, CronHelper is timeout")
  65. case <-nowContext.Done():
  66. log_helper.GetLogger().Infoln("CronHelper.Stop() Done.")
  67. }
  68. } else {
  69. // Stop stops the cron scheduler if it is running; otherwise it does nothing.
  70. // A context is returned so the caller can wait for running jobs to complete.
  71. nowContext := ch.c.Stop()
  72. select {
  73. case <-time.After(5 * time.Second):
  74. log_helper.GetLogger().Warningln("Wait over 5 s, CronHelper is timeout")
  75. case <-nowContext.Done():
  76. log_helper.GetLogger().Infoln("CronHelper.Stop() Done.")
  77. }
  78. }
  79. ch.cronHelperRunningLock.Lock()
  80. ch.cronHelperRunning = false
  81. ch.cronHelperRunningLock.Unlock()
  82. }
  83. func (ch *CronHelper) CronHelperRunning() bool {
  84. defer func() {
  85. ch.cronHelperRunningLock.Unlock()
  86. }()
  87. ch.cronHelperRunningLock.Lock()
  88. return ch.cronHelperRunning
  89. }
  90. func (ch *CronHelper) CronRunningStatusString() string {
  91. if ch.CronHelperRunning() == true {
  92. return Running
  93. } else {
  94. return Stopped
  95. }
  96. }
  97. func (ch *CronHelper) FullDownloadProcessRunning() bool {
  98. defer func() {
  99. ch.fullSubDownloadProcessingLock.Unlock()
  100. }()
  101. ch.fullSubDownloadProcessingLock.Lock()
  102. return ch.fullSubDownloadProcessing
  103. }
  104. func (ch *CronHelper) FullDownloadProcessRunningStatusString() string {
  105. if ch.FullDownloadProcessRunning() == true {
  106. return Running
  107. } else {
  108. return Stopped
  109. }
  110. }
  111. // coreSubDownloadProcess 执行一次下载任务的多个步骤
  112. func (ch *CronHelper) coreSubDownloadProcess() {
  113. defer func() {
  114. ch.fullSubDownloadProcessingLock.Lock()
  115. ch.fullSubDownloadProcessing = false
  116. ch.fullSubDownloadProcessingLock.Unlock()
  117. log_helper.GetLogger().Infoln(log_helper.OnceSubsScanEnd)
  118. }()
  119. ch.fullSubDownloadProcessingLock.Lock()
  120. ch.fullSubDownloadProcessing = true
  121. ch.fullSubDownloadProcessingLock.Unlock()
  122. log_helper.GetLogger().Infoln(log_helper.OnceSubsScanStart)
  123. // 下载前的初始化
  124. preDownloadProcess := pre_download_process.NewPreDownloadProcess()
  125. err := preDownloadProcess.
  126. Init().
  127. Check().
  128. HotFix().
  129. ChangeSubNameFormat().
  130. ReloadBrowser().
  131. Wait()
  132. if err != nil {
  133. log_helper.GetLogger().Errorln("pre_download_process", "Error:", err)
  134. log_helper.GetLogger().Errorln("Skip DownloaderHelper.Start()")
  135. return
  136. }
  137. // 开始下载
  138. ch.dh = downloader_helper.NewDownloaderHelper(*settings.GetSettings(true),
  139. preDownloadProcess.SubSupplierHub)
  140. err = ch.dh.Start()
  141. if err != nil {
  142. log_helper.GetLogger().Errorln("downloader_helper.Start()", "Error:", err)
  143. return
  144. }
  145. }
  146. const (
  147. Stopped = "stopped"
  148. Running = "running"
  149. )