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.

check_cache.go 5.0 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. package event
  2. import (
  3. "time"
  4. shell "github.com/ipfs/go-ipfs-api"
  5. "github.com/samber/lo"
  6. "gitlink.org.cn/cloudream/agent/internal/config"
  7. "gitlink.org.cn/cloudream/common/consts"
  8. evcst "gitlink.org.cn/cloudream/common/consts/event"
  9. "gitlink.org.cn/cloudream/common/pkg/logger"
  10. "gitlink.org.cn/cloudream/db/model"
  11. agtevt "gitlink.org.cn/cloudream/rabbitmq/message/agent/event"
  12. scmsg "gitlink.org.cn/cloudream/rabbitmq/message/scanner"
  13. scevt "gitlink.org.cn/cloudream/rabbitmq/message/scanner/event"
  14. )
  15. type CheckCache struct {
  16. agtevt.CheckCache
  17. }
  18. func NewCheckCache(isComplete bool, caches []model.Cache) *CheckCache {
  19. return &CheckCache{
  20. CheckCache: agtevt.NewCheckCache(isComplete, caches),
  21. }
  22. }
  23. func (t *CheckCache) TryMerge(other Event) bool {
  24. event, ok := other.(*CheckCache)
  25. if !ok {
  26. return false
  27. }
  28. if event.IsComplete {
  29. t.IsComplete = true
  30. t.Caches = event.Caches
  31. return true
  32. }
  33. if !t.IsComplete {
  34. t.Caches = append(t.Caches, event.Caches...)
  35. t.Caches = lo.UniqBy(t.Caches, func(ch model.Cache) string { return ch.FileHash })
  36. return true
  37. }
  38. return false
  39. }
  40. func (t *CheckCache) Execute(execCtx ExecuteContext) {
  41. logger.Debugf("begin check cache")
  42. filesMap, err := execCtx.Args.IPFS.GetPinnedFiles()
  43. if err != nil {
  44. logger.Warnf("get pinned files from ipfs failed, err: %s", err.Error())
  45. return
  46. }
  47. // TODO 根据锁定清单过滤被锁定的文件的记录
  48. if t.IsComplete {
  49. t.checkComplete(filesMap, execCtx)
  50. } else {
  51. t.checkIncrement(filesMap, execCtx)
  52. }
  53. }
  54. func (t *CheckCache) checkIncrement(filesMap map[string]shell.PinInfo, execCtx ExecuteContext) {
  55. var updateCacheOps []scevt.UpdateCacheEntry
  56. for _, cache := range t.Caches {
  57. _, ok := filesMap[cache.FileHash]
  58. if ok {
  59. if cache.State == consts.CACHE_STATE_PINNED {
  60. // 不处理
  61. } else if cache.State == consts.CACHE_STATE_TEMP {
  62. err := execCtx.Args.IPFS.Unpin(cache.FileHash)
  63. if err != nil {
  64. logger.WithField("FileHash", cache.FileHash).Warnf("unpin file failed, err: %s", err.Error())
  65. }
  66. }
  67. // 删除map中的记录,表示此记录已被检查过
  68. delete(filesMap, cache.FileHash)
  69. } else {
  70. if cache.State == consts.CACHE_STATE_PINNED {
  71. // TODO 需要考虑此处是否是同步的过程
  72. err := execCtx.Args.IPFS.Pin(cache.FileHash)
  73. if err != nil {
  74. logger.WithField("FileHash", cache.FileHash).Warnf("pin file failed, err: %s", err.Error())
  75. }
  76. } else if cache.State == consts.CACHE_STATE_TEMP {
  77. if time.Since(cache.CacheTime) > time.Duration(config.Cfg().TempFileLifetime)*time.Second {
  78. updateCacheOps = append(updateCacheOps, scevt.NewUpdateCacheEntry(cache.FileHash, evcst.UPDATE_CACHE_DELETE_TEMP))
  79. }
  80. }
  81. }
  82. }
  83. // 增量情况下,不需要对filesMap中没检查的记录进行处理
  84. if len(updateCacheOps) > 0 {
  85. evtmsg, err := scmsg.NewPostEventBody(
  86. scevt.NewUpdateCache(config.Cfg().ID, updateCacheOps),
  87. execCtx.Option.IsEmergency,
  88. execCtx.Option.DontMerge,
  89. )
  90. if err == nil {
  91. execCtx.Args.Scanner.PostEvent(evtmsg)
  92. } else {
  93. logger.Warnf("new post event body failed, err: %s", err.Error())
  94. }
  95. }
  96. }
  97. func (t *CheckCache) checkComplete(filesMap map[string]shell.PinInfo, execCtx ExecuteContext) {
  98. var updateCacheOps []scevt.UpdateCacheEntry
  99. for _, cache := range t.Caches {
  100. _, ok := filesMap[cache.FileHash]
  101. if ok {
  102. if cache.State == consts.CACHE_STATE_PINNED {
  103. // 不处理
  104. } else if cache.State == consts.CACHE_STATE_TEMP {
  105. err := execCtx.Args.IPFS.Unpin(cache.FileHash)
  106. if err != nil {
  107. logger.WithField("FileHash", cache.FileHash).Warnf("unpin file failed, err: %s", err.Error())
  108. }
  109. }
  110. // 删除map中的记录,表示此记录已被检查过
  111. delete(filesMap, cache.FileHash)
  112. } else {
  113. if cache.State == consts.CACHE_STATE_PINNED {
  114. // TODO 需要考虑此处是否是同步的过程
  115. err := execCtx.Args.IPFS.Pin(cache.FileHash)
  116. if err != nil {
  117. logger.WithField("FileHash", cache.FileHash).Warnf("pin file failed, err: %s", err.Error())
  118. }
  119. } else if cache.State == consts.CACHE_STATE_TEMP {
  120. if time.Since(cache.CacheTime) > time.Duration(config.Cfg().TempFileLifetime)*time.Second {
  121. updateCacheOps = append(updateCacheOps, scevt.NewUpdateCacheEntry(cache.FileHash, evcst.UPDATE_CACHE_DELETE_TEMP))
  122. }
  123. }
  124. }
  125. }
  126. // map中剩下的数据是没有被遍历过,即Cache中没有记录的
  127. for hash, _ := range filesMap {
  128. updateCacheOps = append(updateCacheOps, scevt.NewUpdateCacheEntry(hash, evcst.UPDATE_CACHE_CREATE_TEMP))
  129. }
  130. evtmsg, err := scmsg.NewPostEventBody(
  131. scevt.NewUpdateCache(config.Cfg().ID, updateCacheOps),
  132. execCtx.Option.IsEmergency,
  133. execCtx.Option.DontMerge,
  134. )
  135. if err == nil {
  136. execCtx.Args.Scanner.PostEvent(evtmsg)
  137. } else {
  138. logger.Warnf("new post event body failed, err: %s", err.Error())
  139. }
  140. }
  141. func init() {
  142. Register(func(val agtevt.CheckCache) Event { return NewCheckCache(val.IsComplete, val.Caches) })
  143. }

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