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_shardstore.go 4.1 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. package ticktock
  2. import (
  3. "fmt"
  4. "time"
  5. "github.com/samber/lo"
  6. "gitlink.org.cn/cloudream/common/pkgs/logger"
  7. "gitlink.org.cn/cloudream/common/pkgs/mq"
  8. "gitlink.org.cn/cloudream/common/utils/reflect2"
  9. "gitlink.org.cn/cloudream/jcs-pub/client/internal/db"
  10. clitypes "gitlink.org.cn/cloudream/jcs-pub/client/types"
  11. stgglb "gitlink.org.cn/cloudream/jcs-pub/common/globals"
  12. hubmq "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/mq/hub"
  13. )
  14. // CheckShardStore 代表一个用于处理代理缓存检查事件的结构体
  15. type CheckShardStore struct {
  16. }
  17. func (j *CheckShardStore) Name() string {
  18. return reflect2.TypeNameOf[CheckShardStore]()
  19. }
  20. // Execute 执行缓存检查操作,对比本地缓存与代理返回的缓存信息,更新数据库中的缓存记录
  21. func (j *CheckShardStore) Execute(t *TickTock) {
  22. log := logger.WithType[CheckShardStore]("TickTock")
  23. startTime := time.Now()
  24. log.Debugf("job start")
  25. defer func() {
  26. log.Debugf("job end, time: %v", time.Since(startTime))
  27. }()
  28. db2 := t.db
  29. spaceIDs, err := db2.UserSpace().GetAllIDs(db2.DefCtx())
  30. if err != nil {
  31. log.Warnf("getting all user space ids: %s", err.Error())
  32. return
  33. }
  34. for _, spaceID := range spaceIDs {
  35. detail := t.spaceMeta.Get(spaceID)
  36. if detail == nil {
  37. continue
  38. }
  39. err := j.checkOne(t, detail)
  40. if err != nil {
  41. log.Warnf("checking user space %v: %v", detail.String(), err)
  42. continue
  43. }
  44. }
  45. }
  46. func (j *CheckShardStore) checkOne(t *TickTock, space *clitypes.UserSpaceDetail) error {
  47. log := logger.WithType[CheckShardStore]("TickTock")
  48. if space.MasterHub == nil {
  49. log.Infof("user space %v has no master hub", space.UserSpace)
  50. return nil
  51. }
  52. agtCli, err := stgglb.HubMQPool.Acquire(space.MasterHub.HubID)
  53. if err != nil {
  54. return fmt.Errorf("new hub mq client: %w", err)
  55. }
  56. defer stgglb.HubMQPool.Release(agtCli)
  57. checkResp, err := agtCli.CheckCache(hubmq.NewCheckCache(*space), mq.RequestOption{Timeout: time.Minute})
  58. if err != nil {
  59. return fmt.Errorf("request to check cache: %w", err)
  60. }
  61. realFileHashes := lo.SliceToMap(checkResp.FileHashes, func(hash clitypes.FileHash) (clitypes.FileHash, bool) { return hash, true })
  62. // 在事务中执行缓存更新操作
  63. t.db.DoTx(func(tx db.SQLContext) error {
  64. j.checkPinnedObject(t, tx, space, realFileHashes)
  65. j.checkObjectBlock(t, tx, space, realFileHashes)
  66. return nil
  67. })
  68. return nil
  69. }
  70. // checkPinnedObject 对比PinnedObject表,若实际文件不存在,则进行删除操作
  71. func (*CheckShardStore) checkPinnedObject(t *TickTock, tx db.SQLContext, space *clitypes.UserSpaceDetail, realFileHashes map[clitypes.FileHash]bool) {
  72. log := logger.WithType[CheckShardStore]("TickTock")
  73. objs, err := t.db.PinnedObject().GetObjectsByUserSpaceID(tx, space.UserSpace.UserSpaceID)
  74. if err != nil {
  75. log.Warnf("getting pinned objects by user space id %v: %v", space.UserSpace, err)
  76. return
  77. }
  78. var rms []clitypes.ObjectID
  79. for _, c := range objs {
  80. if realFileHashes[c.FileHash] {
  81. continue
  82. }
  83. rms = append(rms, c.ObjectID)
  84. }
  85. if len(rms) > 0 {
  86. err = t.db.PinnedObject().BatchDelete(tx, space.UserSpace.UserSpaceID, rms)
  87. if err != nil {
  88. log.Warnf("batch delete user space %v pinned objects: %v", space.UserSpace, err)
  89. }
  90. }
  91. }
  92. // checkObjectBlock 对比ObjectBlock表,若实际文件不存在,则进行删除操作
  93. func (*CheckShardStore) checkObjectBlock(t *TickTock, tx db.SQLContext, space *clitypes.UserSpaceDetail, realFileHashes map[clitypes.FileHash]bool) {
  94. log := logger.WithType[CheckShardStore]("TickTock")
  95. blocks, err := t.db.ObjectBlock().GetByUserSpaceID(tx, space.UserSpace.UserSpaceID)
  96. if err != nil {
  97. log.Warnf("getting object blocks by user space id %v: %v", space.UserSpace, err)
  98. return
  99. }
  100. var rms []clitypes.FileHash
  101. for _, b := range blocks {
  102. if realFileHashes[b.FileHash] {
  103. continue
  104. }
  105. rms = append(rms, b.FileHash)
  106. }
  107. if len(rms) > 0 {
  108. err = t.db.ObjectBlock().BatchDeleteByFileHash(tx, space.UserSpace.UserSpaceID, rms)
  109. if err != nil {
  110. log.Warnf("batch delete user space %v object blocks: %v", space.UserSpace, err)
  111. }
  112. }
  113. }

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