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.4 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  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/utils/reflect2"
  8. "gitlink.org.cn/cloudream/jcs-pub/client/internal/db"
  9. stgtypes "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/storage/types"
  10. jcstypes "gitlink.org.cn/cloudream/jcs-pub/common/types"
  11. )
  12. // CheckShardStore 代表一个用于处理代理缓存检查事件的结构体
  13. type CheckShardStore struct {
  14. }
  15. func (j *CheckShardStore) Name() string {
  16. return reflect2.TypeNameOf[CheckShardStore]()
  17. }
  18. // Execute 执行缓存检查操作,对比本地缓存与代理返回的缓存信息,更新数据库中的缓存记录
  19. func (j *CheckShardStore) Execute(t *TickTock) {
  20. log := logger.WithType[CheckShardStore]("TickTock")
  21. startTime := time.Now()
  22. log.Infof("job start")
  23. defer func() {
  24. log.Infof("job end, time: %v", time.Since(startTime))
  25. }()
  26. db2 := t.db
  27. spaceIDs, err := db2.UserSpace().GetAllIDs(db2.DefCtx())
  28. if err != nil {
  29. log.Warnf("getting all user space ids: %s", err.Error())
  30. return
  31. }
  32. for _, spaceID := range spaceIDs {
  33. detail := t.spaceMeta.Get(spaceID)
  34. if detail == nil {
  35. continue
  36. }
  37. err := j.checkOne(t, detail)
  38. if err != nil {
  39. log.Warnf("checking user space %v: %v", detail.String(), err)
  40. continue
  41. }
  42. }
  43. }
  44. func (j *CheckShardStore) checkOne(t *TickTock, space *jcstypes.UserSpaceDetail) error {
  45. // addr, ok := space.RecommendHub.Address.(*jcstypes.GRPCAddressInfo)
  46. // if !ok {
  47. // return fmt.Errorf("master of user space %v has no grpc address", space.UserSpace)
  48. // }
  49. // agtCli := stgglb.HubRPCPool.Get(stgglb.SelectGRPCAddress(&space.RecommendHub, addr))
  50. // defer agtCli.Release()
  51. // ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(time.Minute))
  52. // defer cancel()
  53. // checkResp, cerr := agtCli.CheckCache(ctx, &hubrpc.CheckCache{
  54. // UserSpace: *space,
  55. // })
  56. // if cerr != nil {
  57. // return fmt.Errorf("request to check cache: %w", cerr.ToError())
  58. // }
  59. store, err := t.stgPool.GetShardStore(space)
  60. if err != nil {
  61. return fmt.Errorf("getting shard store: %w", err)
  62. }
  63. infos, err := store.ListAll()
  64. if err != nil {
  65. return fmt.Errorf("listing all files: %w", err)
  66. }
  67. fileHashes := lo.Map(infos, func(info stgtypes.FileInfo, _ int) jcstypes.FileHash { return info.Hash })
  68. realFileHashes := lo.SliceToMap(fileHashes, func(hash jcstypes.FileHash) (jcstypes.FileHash, bool) { return hash, true })
  69. // 在事务中执行缓存更新操作
  70. t.db.DoTx(func(tx db.SQLContext) error {
  71. j.checkPinnedObject(t, tx, space, realFileHashes)
  72. j.checkObjectBlock(t, tx, space, realFileHashes)
  73. return nil
  74. })
  75. return nil
  76. }
  77. // checkPinnedObject 对比PinnedObject表,若实际文件不存在,则进行删除操作
  78. func (*CheckShardStore) checkPinnedObject(t *TickTock, tx db.SQLContext, space *jcstypes.UserSpaceDetail, realFileHashes map[jcstypes.FileHash]bool) {
  79. log := logger.WithType[CheckShardStore]("TickTock")
  80. objs, err := t.db.PinnedObject().GetObjectsByUserSpaceID(tx, space.UserSpace.UserSpaceID)
  81. if err != nil {
  82. log.Warnf("getting pinned objects by user space id %v: %v", space.UserSpace, err)
  83. return
  84. }
  85. var rms []jcstypes.ObjectID
  86. for _, c := range objs {
  87. if realFileHashes[c.FileHash] {
  88. continue
  89. }
  90. rms = append(rms, c.ObjectID)
  91. }
  92. if len(rms) > 0 {
  93. err = t.db.PinnedObject().BatchDelete(tx, space.UserSpace.UserSpaceID, rms)
  94. if err != nil {
  95. log.Warnf("batch delete user space %v pinned objects: %v", space.UserSpace, err)
  96. }
  97. }
  98. }
  99. // checkObjectBlock 对比ObjectBlock表,若实际文件不存在,则进行删除操作
  100. func (*CheckShardStore) checkObjectBlock(t *TickTock, tx db.SQLContext, space *jcstypes.UserSpaceDetail, realFileHashes map[jcstypes.FileHash]bool) {
  101. log := logger.WithType[CheckShardStore]("TickTock")
  102. blocks, err := t.db.ObjectBlock().GetByUserSpaceID(tx, space.UserSpace.UserSpaceID)
  103. if err != nil {
  104. log.Warnf("getting object blocks by user space id %v: %v", space.UserSpace, err)
  105. return
  106. }
  107. var rms []jcstypes.FileHash
  108. for _, b := range blocks {
  109. if realFileHashes[b.FileHash] {
  110. continue
  111. }
  112. rms = append(rms, b.FileHash)
  113. }
  114. if len(rms) > 0 {
  115. err = t.db.ObjectBlock().BatchDeleteByFileHash(tx, space.UserSpace.UserSpaceID, rms)
  116. if err != nil {
  117. log.Warnf("batch delete user space %v object blocks: %v", space.UserSpace, err)
  118. }
  119. }
  120. }

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