Переглянути джерело

准备对接 web 启动接口

Signed-off-by: allan716 <[email protected]>
allan716 3 роки тому
батько
коміт
49f3b5adb5

+ 42 - 17
cmd/chinesesubfinder/main.go

@@ -1,11 +1,14 @@
 package main
 
 import (
+	"github.com/allanpk716/ChineseSubFinder/internal/backend"
+	"github.com/allanpk716/ChineseSubFinder/internal/logic/cron_helper"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/global_value"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/log_helper"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/my_util"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/settings"
-	"github.com/robfig/cron/v3"
+	"os"
+	"strconv"
 )
 
 func init() {
@@ -21,31 +24,53 @@ func init() {
 
 func main() {
 
-	// 任务还没执行完,下一次执行时间到来,下一次执行就跳过不执行
-	c := cron.New(cron.WithChain(cron.SkipIfStillRunning(cron.DefaultLogger)))
-	// 定时器
-	entryID, err := c.AddFunc("@every "+settings.GetSettings().CommonSettings.ScanInterval, func() {
-		// do something
-	})
+	cronHelper, err := cron_helper.NewCronHelper()
 	if err != nil {
-		log_helper.GetLogger().Errorln("cron entryID:", entryID, "Error:", err)
-		return
+		panic("NewCronHelper " + err.Error())
 	}
 
-	if settings.GetSettings().CommonSettings.RunScanAtStartUp == true {
-		log_helper.GetLogger().Infoln("First Time Download Start")
-		// do something
-		log_helper.GetLogger().Infoln("First Time Download End")
+	if settings.GetSettings().UserInfo.Username == "" || settings.GetSettings().UserInfo.Password == "" {
+		// 如果没有完成,那么就不开启
+
 	} else {
-		log_helper.GetLogger().Infoln("RunAtStartup: false, so will not Run At Startup, wait", settings.GetSettings().CommonSettings.ScanInterval, "to Download")
+		// 是否完成了 Setup,如果完成了,那么就开启第一次的扫描
+		go func() {
+			cronHelper.Start(settings.GetSettings().CommonSettings.RunScanAtStartUp)
+		}()
 	}
+	// 支持在外部配置特殊的端口号,以防止本地本占用了无法使用
+	backend.StartBackEnd(readCustomPortFile(), cronHelper)
+}
+
+func readCustomPortFile() int {
+	if my_util.IsFile(customPort) == false {
+		return defPort
+	} else {
+		bytes, err := os.ReadFile(customPort)
+		if err != nil {
+			log_helper.GetLogger().Errorln("ReadFile CustomPort Error", err)
+			log_helper.GetLogger().Infoln("Use DefPort", defPort)
+			return defPort
+		}
 
-	c.Start()
-	// 阻塞
-	select {}
+		atoi, err := strconv.Atoi(string(bytes))
+		if err != nil {
+			log_helper.GetLogger().Errorln("Atoi CustomPort Error", err)
+			log_helper.GetLogger().Infoln("Use DefPort", defPort)
+			return defPort
+		}
+
+		log_helper.GetLogger().Infoln("Use CustomPort", atoi)
+		return atoi
+	}
 }
 
 /*
 	使用 git tag 来做版本描述,然后在编译的时候传入版本号信息到这个变量上
 */
 var AppVersion = "unknow"
+
+const (
+	defPort    = 19035
+	customPort = "CustomPort"
+)

+ 3 - 2
internal/backend/backend.go

@@ -3,18 +3,19 @@ package backend
 import (
 	"fmt"
 	"github.com/allanpk716/ChineseSubFinder/internal/backend/routers"
+	"github.com/allanpk716/ChineseSubFinder/internal/logic/cron_helper"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/log_helper"
 	"github.com/gin-contrib/cors"
 	"github.com/gin-gonic/gin"
 )
 
 // StartBackEnd 开启后端的服务器
-func StartBackEnd(httpPort int) {
+func StartBackEnd(httpPort int, cronHelper *cron_helper.CronHelper) {
 
 	engine := gin.Default()
 	// 默认所有都通过
 	engine.Use(cors.Default())
-	routers.InitRouter(engine)
+	routers.InitRouter(engine, cronHelper)
 
 	// listen and serve on 0.0.0.0:8080(default)
 	log_helper.GetLogger().Infoln("Try Start Server At Port", httpPort)

+ 9 - 2
internal/backend/backend_test.go

@@ -1,8 +1,15 @@
 package backend
 
-import "testing"
+import (
+	"testing"
+)
 
 func TestStartBackEnd(t *testing.T) {
 
-	StartBackEnd(9981)
+	//cronHelper, err := cron_helper.NewCronHelper()
+	//if err != nil {
+	//	panic("NewCronHelper " + err.Error())
+	//}
+	//
+	//StartBackEnd(19035)
 }

+ 2 - 0
internal/backend/controllers/base/system_status.go

@@ -1,6 +1,7 @@
 package base
 
 import (
+	"github.com/allanpk716/ChineseSubFinder/internal/pkg/global_value"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/settings"
 	"github.com/allanpk716/ChineseSubFinder/internal/types/backend"
 	"github.com/gin-gonic/gin"
@@ -24,5 +25,6 @@ func (cb ControllerBase) SystemStatusHandler(c *gin.Context) {
 
 	c.JSON(http.StatusOK, backend.ReplySystemStatus{
 		IsSetup: isSetup,
+		Version: global_value.AppVersion,
 	})
 }

+ 4 - 2
internal/backend/controllers/v1/controller_base.go

@@ -1,6 +1,7 @@
 package v1
 
 import (
+	"github.com/allanpk716/ChineseSubFinder/internal/logic/cron_helper"
 	"github.com/allanpk716/ChineseSubFinder/internal/pkg/log_helper"
 	"github.com/allanpk716/ChineseSubFinder/internal/types/backend"
 	"github.com/gin-gonic/gin"
@@ -8,10 +9,11 @@ import (
 )
 
 type ControllerBase struct {
+	cronHelper *cron_helper.CronHelper
 }
 
-func NewControllerBase() *ControllerBase {
-	return &ControllerBase{}
+func NewControllerBase(cronHelper *cron_helper.CronHelper) *ControllerBase {
+	return &ControllerBase{cronHelper}
 }
 
 func (cb ControllerBase) GetVersion() string {

+ 8 - 0
internal/backend/controllers/v1/job_things.go

@@ -18,3 +18,11 @@ func (cb ControllerBase) JobStopHandler(c *gin.Context) {
 	}()
 
 }
+
+func (cb ControllerBase) JobStatusHandler(c *gin.Context) {
+	var err error
+	defer func() {
+		// 统一的异常处理
+		cb.ErrorProcess(c, "JobStatusHandler", err)
+	}()
+}

+ 6 - 2
internal/backend/routers/base_router.go

@@ -4,12 +4,14 @@ import (
 	"github.com/allanpk716/ChineseSubFinder/internal/backend/controllers/base"
 	v1 "github.com/allanpk716/ChineseSubFinder/internal/backend/controllers/v1"
 	"github.com/allanpk716/ChineseSubFinder/internal/backend/middle"
+	"github.com/allanpk716/ChineseSubFinder/internal/logic/cron_helper"
 	"github.com/gin-gonic/gin"
 )
 
-func InitRouter(router *gin.Engine) {
+func InitRouter(router *gin.Engine, cronHelper *cron_helper.CronHelper) {
+
 	cbBase := base.NewControllerBase()
-	cbV1 := v1.NewControllerBase()
+	cbV1 := v1.NewControllerBase(cronHelper)
 	// 基础的路由
 	router.GET("/system-status", cbBase.SystemStatusHandler)
 
@@ -29,7 +31,9 @@ func InitRouter(router *gin.Engine) {
 		GroupV1.POST("/check-proxy", cbV1.CheckProxyHandler)
 
 		GroupV1.POST("/check-path", cbV1.CheckPathHandler)
+
 		GroupV1.POST("/jobs/start", cbV1.JobStartHandler)
 		GroupV1.POST("/jobs/stop", cbV1.JobStopHandler)
+		GroupV1.POST("/jobs/status", cbV1.JobStatusHandler)
 	}
 }

+ 135 - 0
internal/logic/cron_helper/cron_helper.go

@@ -0,0 +1,135 @@
+package cron_helper
+
+import (
+	"github.com/allanpk716/ChineseSubFinder/internal/logic/downloader_helper"
+	"github.com/allanpk716/ChineseSubFinder/internal/logic/pre_download_process"
+	"github.com/allanpk716/ChineseSubFinder/internal/pkg/log_helper"
+	"github.com/allanpk716/ChineseSubFinder/internal/pkg/settings"
+	"github.com/robfig/cron/v3"
+	"sync"
+	"time"
+)
+
+type CronHelper struct {
+	runImmediately                bool
+	fullSubDownloadProcessing     bool
+	fullSubDownloadProcessingLock sync.Locker
+	cronHelperRunning             bool
+	c                             *cron.Cron
+	dh                            *downloader_helper.DownloaderHelper
+}
+
+func NewCronHelper() (*CronHelper, error) {
+
+	ch := CronHelper{}
+	ch.c = cron.New(cron.WithChain(cron.SkipIfStillRunning(cron.DefaultLogger)))
+	// 定时器
+	entryID, err := ch.c.AddFunc("@every "+settings.GetSettings().CommonSettings.ScanInterval, ch.fullSubDownloadProcess)
+	if err != nil {
+		log_helper.GetLogger().Errorln("CronHelper Cron entryID:", entryID, "Error:", err)
+		return nil, err
+	}
+	return &ch, nil
+}
+
+// Start 开启定时器任务,这个任务是非阻塞的,fullSubDownloadProcess 仅仅可能是这个函数执行耗时而已
+// runImmediately == false 那么 ch.c.Start() 是不会阻塞的
+func (ch *CronHelper) Start(runImmediately bool) {
+
+	ch.runImmediately = runImmediately
+	// 是否在定时器开启前先执行一次任务
+	if ch.runImmediately == true {
+
+		log_helper.GetLogger().Infoln("First Time fullSubDownloadProcess Start")
+
+		ch.fullSubDownloadProcess()
+
+		log_helper.GetLogger().Infoln("First Time fullSubDownloadProcess End")
+
+	} else {
+		log_helper.GetLogger().Infoln("RunAtStartup: false, so will not Run At Startup, wait",
+			settings.GetSettings().CommonSettings.ScanInterval, "to Download")
+	}
+
+	ch.c.Start()
+}
+
+// Stop 会阻塞等待任务完成
+func (ch *CronHelper) Stop() {
+
+	fullSubDownloadProcessing := false
+	ch.fullSubDownloadProcessingLock.Lock()
+	fullSubDownloadProcessing = ch.fullSubDownloadProcessing
+	ch.fullSubDownloadProcessingLock.Unlock()
+
+	if fullSubDownloadProcessing == true {
+		if ch.dh != nil {
+			ch.dh.Cancel()
+		}
+		// Stop stops the cron scheduler if it is running; otherwise it does nothing.
+		// A context is returned so the caller can wait for running jobs to complete.
+		nowContext := ch.c.Stop()
+		select {
+		case <-time.After(5 * time.Minute):
+			log_helper.GetLogger().Warningln("Wait over 5 min, CronHelper is timeout")
+		case <-nowContext.Done():
+			log_helper.GetLogger().Infoln("CronHelper.Stop() Done.")
+		}
+	} else {
+		// Stop stops the cron scheduler if it is running; otherwise it does nothing.
+		// A context is returned so the caller can wait for running jobs to complete.
+		nowContext := ch.c.Stop()
+		select {
+		case <-time.After(5 * time.Second):
+			log_helper.GetLogger().Warningln("Wait over 5 s, CronHelper is timeout")
+		case <-nowContext.Done():
+			log_helper.GetLogger().Infoln("CronHelper.Stop() Done.")
+		}
+	}
+}
+
+func (ch *CronHelper) Running() bool {
+
+	defer func() {
+		ch.fullSubDownloadProcessingLock.Unlock()
+	}()
+
+	ch.fullSubDownloadProcessingLock.Lock()
+	return ch.fullSubDownloadProcessing
+}
+
+// fullSubDownloadProcess 执行一次下载任务的多个步骤
+func (ch *CronHelper) fullSubDownloadProcess() {
+
+	defer func() {
+		ch.fullSubDownloadProcessingLock.Lock()
+		ch.fullSubDownloadProcessing = false
+		ch.fullSubDownloadProcessingLock.Unlock()
+	}()
+
+	ch.fullSubDownloadProcessingLock.Lock()
+	ch.fullSubDownloadProcessing = true
+	ch.fullSubDownloadProcessingLock.Unlock()
+
+	// 下载前的初始化
+	preDownloadProcess := pre_download_process.NewPreDownloadProcess().
+		Init().
+		Check().
+		HotFix().
+		ChangeSubNameFormat().
+		ReloadBrowser()
+	err := preDownloadProcess.Wait()
+	if err != nil {
+		log_helper.GetLogger().Errorln("pre_download_process", "Error:", err)
+		log_helper.GetLogger().Errorln("Skip DownloaderHelper.Start()")
+		return
+	}
+	// 开始下载
+	ch.dh = downloader_helper.NewDownloaderHelper(*settings.GetSettings(true),
+		preDownloadProcess.SubSupplierHub)
+	err = ch.dh.Start()
+	if err != nil {
+		log_helper.GetLogger().Errorln("downloader_helper.Start()", "Error:", err)
+		return
+	}
+}

+ 3 - 1
internal/logic/pre_download_process/pre_download_proces.go

@@ -231,7 +231,9 @@ func (p *PreDownloadProcess) ReloadBrowser() *PreDownloadProcess {
 }
 
 func (p *PreDownloadProcess) Wait() error {
-
+	defer func() {
+		log_helper.GetLogger().Infoln("PreDownloadProcess Wait() Done.")
+	}()
 	if p.gError != nil {
 		return errors.New(p.stageName + " " + p.gError.Error())