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.

agent_check_cache.go 5.1 kB

2 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. package event
  2. import (
  3. "database/sql"
  4. "time"
  5. "github.com/jmoiron/sqlx"
  6. "github.com/samber/lo"
  7. "gitlink.org.cn/cloudream/common/pkgs/logger"
  8. "gitlink.org.cn/cloudream/common/pkgs/mq"
  9. cdssdk "gitlink.org.cn/cloudream/common/sdks/storage"
  10. stgglb "gitlink.org.cn/cloudream/storage/common/globals"
  11. agtmq "gitlink.org.cn/cloudream/storage/common/pkgs/mq/agent"
  12. scevt "gitlink.org.cn/cloudream/storage/common/pkgs/mq/scanner/event"
  13. )
  14. // AgentCheckCache 代表一个用于处理代理缓存检查事件的结构体
  15. type AgentCheckCache struct {
  16. *scevt.AgentCheckCache
  17. }
  18. // NewAgentCheckCache 创建一个新的 AgentCheckCache 实例
  19. func NewAgentCheckCache(evt *scevt.AgentCheckCache) *AgentCheckCache {
  20. return &AgentCheckCache{
  21. AgentCheckCache: evt,
  22. }
  23. }
  24. // TryMerge 尝试合并当前事件与另一个事件
  25. // 如果另一个事件类型不匹配或节点ID不同,则不进行合并
  26. func (t *AgentCheckCache) TryMerge(other Event) bool {
  27. event, ok := other.(*AgentCheckCache)
  28. if !ok {
  29. return false
  30. }
  31. if event.NodeID != t.NodeID {
  32. return false
  33. }
  34. return true
  35. }
  36. // Execute 执行缓存检查操作,对比本地缓存与代理返回的缓存信息,更新数据库中的缓存记录
  37. func (t *AgentCheckCache) Execute(execCtx ExecuteContext) {
  38. log := logger.WithType[AgentCheckCache]("Event")
  39. startTime := time.Now()
  40. log.Debugf("begin with %v", logger.FormatStruct(t.AgentCheckCache))
  41. defer func() {
  42. log.Debugf("end, time: %v", time.Since(startTime))
  43. }()
  44. agtCli, err := stgglb.AgentMQPool.Acquire(t.NodeID)
  45. if err != nil {
  46. log.WithField("NodeID", t.NodeID).Warnf("create agent client failed, err: %s", err.Error())
  47. return
  48. }
  49. defer stgglb.AgentMQPool.Release(agtCli)
  50. checkResp, err := agtCli.CheckCache(agtmq.NewCheckCache(), mq.RequestOption{Timeout: time.Minute})
  51. if err != nil {
  52. log.WithField("NodeID", t.NodeID).Warnf("checking ipfs: %s", err.Error())
  53. return
  54. }
  55. realFileHashes := lo.SliceToMap(checkResp.FileHashes, func(hash string) (string, bool) { return hash, true })
  56. // 在事务中执行缓存更新操作
  57. execCtx.Args.DB.DoTx(sql.LevelSerializable, func(tx *sqlx.Tx) error {
  58. t.checkCache(execCtx, tx, realFileHashes)
  59. t.checkPinnedObject(execCtx, tx, realFileHashes)
  60. t.checkObjectBlock(execCtx, tx, realFileHashes)
  61. return nil
  62. })
  63. }
  64. // checkCache 对比Cache表中的记录,根据实际存在的文件哈希值,进行增加或删除操作
  65. func (t *AgentCheckCache) checkCache(execCtx ExecuteContext, tx *sqlx.Tx, realFileHashes map[string]bool) {
  66. log := logger.WithType[AgentCheckCache]("Event")
  67. caches, err := execCtx.Args.DB.Cache().GetByNodeID(tx, t.NodeID)
  68. if err != nil {
  69. log.WithField("NodeID", t.NodeID).Warnf("getting caches by node id: %s", err.Error())
  70. return
  71. }
  72. realFileHashesCp := make(map[string]bool)
  73. for k, v := range realFileHashes {
  74. realFileHashesCp[k] = v
  75. }
  76. var rms []string
  77. for _, c := range caches {
  78. if realFileHashesCp[c.FileHash] {
  79. delete(realFileHashesCp, c.FileHash)
  80. continue
  81. }
  82. rms = append(rms, c.FileHash)
  83. }
  84. if len(rms) > 0 {
  85. err = execCtx.Args.DB.Cache().NodeBatchDelete(tx, t.NodeID, rms)
  86. if err != nil {
  87. log.Warnf("batch delete node caches: %w", err.Error())
  88. }
  89. }
  90. if len(realFileHashesCp) > 0 {
  91. err = execCtx.Args.DB.Cache().BatchCreateOnSameNode(tx, lo.Keys(realFileHashesCp), t.NodeID, 0)
  92. if err != nil {
  93. log.Warnf("batch create node caches: %w", err)
  94. return
  95. }
  96. }
  97. }
  98. // checkPinnedObject 对比PinnedObject表,若实际文件不存在,则进行删除操作
  99. func (t *AgentCheckCache) checkPinnedObject(execCtx ExecuteContext, tx *sqlx.Tx, realFileHashes map[string]bool) {
  100. log := logger.WithType[AgentCheckCache]("Event")
  101. objs, err := execCtx.Args.DB.PinnedObject().GetObjectsByNodeID(tx, t.NodeID)
  102. if err != nil {
  103. log.WithField("NodeID", t.NodeID).Warnf("getting pinned objects by node id: %s", err.Error())
  104. return
  105. }
  106. var rms []cdssdk.ObjectID
  107. for _, c := range objs {
  108. if realFileHashes[c.FileHash] {
  109. continue
  110. }
  111. rms = append(rms, c.ObjectID)
  112. }
  113. if len(rms) > 0 {
  114. err = execCtx.Args.DB.PinnedObject().NodeBatchDelete(tx, t.NodeID, rms)
  115. if err != nil {
  116. log.Warnf("batch delete node pinned objects: %s", err.Error())
  117. }
  118. }
  119. }
  120. // checkObjectBlock 对比ObjectBlock表,若实际文件不存在,则进行删除操作
  121. func (t *AgentCheckCache) checkObjectBlock(execCtx ExecuteContext, tx *sqlx.Tx, realFileHashes map[string]bool) {
  122. log := logger.WithType[AgentCheckCache]("Event")
  123. blocks, err := execCtx.Args.DB.ObjectBlock().GetByNodeID(tx, t.NodeID)
  124. if err != nil {
  125. log.WithField("NodeID", t.NodeID).Warnf("getting object blocks by node id: %s", err.Error())
  126. return
  127. }
  128. var rms []string
  129. for _, b := range blocks {
  130. if realFileHashes[b.FileHash] {
  131. continue
  132. }
  133. rms = append(rms, b.FileHash)
  134. }
  135. if len(rms) > 0 {
  136. err = execCtx.Args.DB.ObjectBlock().NodeBatchDelete(tx, t.NodeID, rms)
  137. if err != nil {
  138. log.Warnf("batch delete node object blocks: %s", err.Error())
  139. }
  140. }
  141. }
  142. // init 注册AgentCheckCache消息转换器
  143. func init() {
  144. RegisterMessageConvertor(NewAgentCheckCache)
  145. }

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