cron_helper.go 5.8 KB

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