You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

executor.go 1.9 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. package task
  2. import (
  3. "context"
  4. "sync"
  5. "github.com/zyedidia/generic/list"
  6. mydb "gitlink.org.cn/cloudream/db"
  7. sccli "gitlink.org.cn/cloudream/rabbitmq/client/scanner"
  8. "gitlink.org.cn/cloudream/utils/ipfs"
  9. "golang.org/x/sync/semaphore"
  10. )
  11. type ExecuteOption struct {
  12. IsEmergency bool
  13. DontMerge bool
  14. }
  15. type ExecuteContext struct {
  16. Executor *Executor
  17. Scanner *sccli.ScannerClient
  18. DB *mydb.DB
  19. IPFS *ipfs.IPFS
  20. }
  21. type postedTask struct {
  22. Task Task
  23. Option ExecuteOption
  24. }
  25. type Executor struct {
  26. tasks list.List[postedTask]
  27. locker sync.Mutex
  28. taskSema semaphore.Weighted
  29. execCtx *ExecuteContext
  30. }
  31. func (e *Executor) Post(task Task, opts ...ExecuteOption) {
  32. opt := ExecuteOption{
  33. IsEmergency: false,
  34. DontMerge: false,
  35. }
  36. if len(opts) > 0 {
  37. opt = opts[0]
  38. }
  39. e.locker.Lock()
  40. defer e.locker.Unlock()
  41. // 紧急任务直接插入到队头,不进行合并
  42. if opt.IsEmergency {
  43. e.tasks.PushFront(postedTask{
  44. Task: task,
  45. Option: opt,
  46. })
  47. e.taskSema.Release(1)
  48. return
  49. }
  50. // 合并任务
  51. if opt.DontMerge {
  52. ptr := e.tasks.Front
  53. for ptr != nil {
  54. // 只与非紧急任务,且允许合并的任务进行合并
  55. if !ptr.Value.Option.IsEmergency && !ptr.Value.Option.DontMerge {
  56. if ptr.Value.Task.TryMerge(task) {
  57. return
  58. }
  59. }
  60. ptr = ptr.Next
  61. }
  62. }
  63. e.tasks.PushBack(postedTask{
  64. Task: task,
  65. Option: opt,
  66. })
  67. e.taskSema.Release(1)
  68. }
  69. // Execute 开始执行任务
  70. func (e *Executor) Execute() error {
  71. for {
  72. // TODO 打印错误日志
  73. e.taskSema.Acquire(context.Background(), 1)
  74. task := e.popFrontTask()
  75. if task == nil {
  76. continue
  77. }
  78. task.Task.Execute(e.execCtx, task.Option)
  79. }
  80. }
  81. func (e *Executor) popFrontTask() *postedTask {
  82. e.locker.Lock()
  83. defer e.locker.Unlock()
  84. if e.tasks.Front == nil {
  85. return nil
  86. }
  87. return &e.tasks.Front.Value
  88. }

本项目旨在将云际存储公共基础设施化,使个人及企业可低门槛使用高效的云际存储服务(安装开箱即用云际存储客户端即可,无需关注其他组件的部署),同时支持用户灵活便捷定制云际存储的功能细节。