|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- package spacesyncer
-
- import (
- "context"
- "fmt"
- "sync"
-
- "gitlink.org.cn/cloudream/common/pkgs/async"
- "gitlink.org.cn/cloudream/common/pkgs/logger"
- "gitlink.org.cn/cloudream/jcs-pub/client/internal/db"
- "gitlink.org.cn/cloudream/jcs-pub/client/internal/metacache"
- clitypes "gitlink.org.cn/cloudream/jcs-pub/client/types"
- stgpool "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/storage/pool"
- )
-
- const (
- logMod = "SpaceSyncer"
- )
-
- type SpaceSyncerEvent interface {
- IsSpaceSyncerEvent() bool
- }
-
- type SpaceSyncer struct {
- db *db.DB
- stgPool *stgpool.Pool
- spaceMeta *metacache.UserSpaceMeta
- lock sync.Mutex
- tasks map[clitypes.SpaceSyncTaskID]*task
- }
-
- func New(db *db.DB, stgPool *stgpool.Pool, spaceMeta *metacache.UserSpaceMeta) *SpaceSyncer {
- return &SpaceSyncer{
- db: db,
- stgPool: stgPool,
- spaceMeta: spaceMeta,
- tasks: make(map[clitypes.SpaceSyncTaskID]*task),
- }
- }
-
- func (s *SpaceSyncer) Start() *async.UnboundChannel[SpaceSyncerEvent] {
- s.lock.Lock()
- defer s.lock.Unlock()
-
- log := logger.WithField("Mod", logMod)
-
- ch := async.NewUnboundChannel[SpaceSyncerEvent]()
-
- allTask, err := db.DoTx01(s.db, s.db.SpaceSyncTask().GetAll)
- if err != nil {
- log.Warnf("load task from db: %v", err)
- } else {
- var rms []clitypes.SpaceSyncTaskID
- for _, t := range allTask {
- ctx, cancel := context.WithCancel(context.Background())
- tsk := task{
- Task: t,
- Context: ctx,
- CancelFn: cancel,
- }
-
- switch tr := t.Trigger.(type) {
- case *clitypes.SpaceSyncTriggerOnce:
- // Once类型的任务没有执行完也不执行了
- rms = append(rms, t.TaskID)
-
- case *clitypes.SpaceSyncTriggerInterval:
- triggerInterval(s, &tsk, tr)
-
- case *clitypes.SpaceSyncTriggerAt:
- triggerAt(s, &tsk, tr)
- }
-
- log.Infof("load task %v from db", t.TaskID)
- }
-
- if len(rms) > 0 {
- err := s.db.SpaceSyncTask().BatchDelete(s.db.DefCtx(), rms)
- if err != nil {
- log.Warnf("batch delete task: %v", err)
- } else {
- log.Infof("%v once task deleted", len(rms))
- }
- }
- }
-
- return ch
- }
-
- func (s *SpaceSyncer) Stop() {
- s.lock.Lock()
- defer s.lock.Unlock()
-
- for _, t := range s.tasks {
- t.CancelFn()
- }
-
- s.tasks = make(map[clitypes.SpaceSyncTaskID]*task)
- }
-
- func (s *SpaceSyncer) CreateTask(t clitypes.SpaceSyncTask) (*TaskInfo, error) {
- log := logger.WithField("Mod", logMod)
-
- d := s.db
- err := d.DoTx(func(tx db.SQLContext) error {
- err := d.SpaceSyncTask().Create(tx, &t)
- if err != nil {
- return err
- }
-
- return nil
- })
- if err != nil {
- return nil, fmt.Errorf("creating space sync task: %w", err)
- }
-
- ctx, cancel := context.WithCancel(context.Background())
- tsk := task{
- Task: t,
- Context: ctx,
- CancelFn: cancel,
- }
-
- s.lock.Lock()
- s.tasks[t.TaskID] = &tsk
- s.lock.Unlock()
-
- switch tr := t.Trigger.(type) {
- case *clitypes.SpaceSyncTriggerOnce:
- triggerOnce(s, &tsk)
-
- case *clitypes.SpaceSyncTriggerInterval:
- triggerInterval(s, &tsk, tr)
-
- case *clitypes.SpaceSyncTriggerAt:
- triggerAt(s, &tsk, tr)
- }
-
- log.Infof("task %v created", t.TaskID)
-
- return &TaskInfo{
- Task: t,
- }, nil
- }
-
- func (s *SpaceSyncer) CancelTask(taskID clitypes.SpaceSyncTaskID) {
- log := logger.WithField("Mod", logMod)
-
- s.lock.Lock()
- defer s.lock.Unlock()
-
- t := s.tasks[taskID]
- if t == nil {
- log.Infof("task %v not found, cancel aborted", taskID)
- return
- }
-
- t.CancelFn()
- delete(s.tasks, taskID)
-
- err := s.db.SpaceSyncTask().Delete(s.db.DefCtx(), taskID)
- if err != nil {
- log.Warnf("delete task %v from db: %v", taskID, err)
- }
-
- log.Infof("task %v canceled", taskID)
- }
-
- func (s *SpaceSyncer) GetTask(taskID clitypes.SpaceSyncTaskID) *clitypes.SpaceSyncTask {
- s.lock.Lock()
- defer s.lock.Unlock()
-
- tsk := s.tasks[taskID]
- if tsk == nil {
- return nil
- }
-
- // TODO 考虑复制一份状态,防止修改
- t := tsk.Task
- return &t
- }
-
- type TaskInfo struct {
- Task clitypes.SpaceSyncTask
- }
-
- type task struct {
- Task clitypes.SpaceSyncTask
- Context context.Context
- CancelFn func()
- }
|