package ticktock import ( "context" "fmt" "time" "gitlink.org.cn/cloudream/common/pkgs/logger" "gitlink.org.cn/cloudream/common/utils/reflect2" "gitlink.org.cn/cloudream/jcs-pub/client/internal/db" "gitlink.org.cn/cloudream/jcs-pub/client/types" stgglb "gitlink.org.cn/cloudream/jcs-pub/common/globals" cortypes "gitlink.org.cn/cloudream/jcs-pub/coordinator/types" "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/distlock/reqbuilder" hubrpc "gitlink.org.cn/cloudream/jcs-pub/common/pkgs/rpc/hub" ) type ShardStoreGC struct { } func (j *ShardStoreGC) Name() string { return reflect2.TypeNameOf[ShardStoreGC]() } // Execute 执行垃圾回收操作。 func (j *ShardStoreGC) Execute(t *TickTock) { log := logger.WithType[ShardStoreGC]("Event") startTime := time.Now() log.Debugf("job start") defer func() { log.Debugf("job end, time: %v", time.Since(startTime)) }() spaceIDs, err := t.db.UserSpace().GetAllIDs(t.db.DefCtx()) if err != nil { log.Warnf("getting user space ids: %v", err) return } for _, spaceID := range spaceIDs { detail := t.spaceMeta.Get(spaceID) if detail == nil { continue } err := j.gcOne(t, detail) if err != nil { log.Warnf("gc one user space: %v: %v", spaceID, err) continue } } } func (j *ShardStoreGC) gcOne(t *TickTock, space *types.UserSpaceDetail) error { mutex, err := reqbuilder.NewBuilder().Shard().GC(space.UserSpace.UserSpaceID).MutexLock(t.pubLock) if err != nil { return fmt.Errorf("acquire lock: %w", err) } defer mutex.Unlock() db2 := t.db // 收集需要进行垃圾回收的文件哈希值 var allFileHashes []types.FileHash err = db2.DoTx(func(tx db.SQLContext) error { blocks, err := db2.ObjectBlock().GetByUserSpaceID(tx, space.UserSpace.UserSpaceID) if err != nil { return fmt.Errorf("getting object blocks by hub id: %w", err) } for _, c := range blocks { allFileHashes = append(allFileHashes, c.FileHash) } objs, err := db2.PinnedObject().GetObjectsByUserSpaceID(tx, space.UserSpace.UserSpaceID) if err != nil { return fmt.Errorf("getting pinned objects by hub id: %w", err) } for _, o := range objs { allFileHashes = append(allFileHashes, o.FileHash) } return nil }) if err != nil { return err } // 获取与节点通信的代理客户端 addr, ok := space.MasterHub.Address.(*cortypes.GRPCAddressInfo) if !ok { return fmt.Errorf("master of user space %v has no grpc address", space.UserSpace) } agtCli := stgglb.HubRPCPool.Get(stgglb.SelectGRPCAddress(*space.MasterHub, *addr)) defer agtCli.Release() // 向代理发送垃圾回收请求 ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(time.Minute)) defer cancel() _, cerr := agtCli.CacheGC(ctx, &hubrpc.CacheGC{ UserSpace: *space, Availables: allFileHashes, }) if cerr != nil { return fmt.Errorf("request to cache gc: %w", cerr.ToError()) } return nil }