diff --git a/cache/relation.go b/cache/relation.go index 2333dde..1bb8ff9 100644 --- a/cache/relation.go +++ b/cache/relation.go @@ -2,6 +2,7 @@ package cache import ( "electricity_bill_calc/global" + "fmt" "strings" "github.com/rueian/rueidis" @@ -69,3 +70,52 @@ func AbolishRelation(relationName string) error { return nil } } + +func ClearOrphanRelationItems() error { + var ( + err error + cursor int64 + keys = make([]string, 0) + sKeys []string + ) + for { + scanCmd := global.RedisConn.B().Scan().Cursor(cursor).Match(fmt.Sprintf("%s:*", TAG_RELATION)).Count(20).Build() + results := global.RedisConn.Do(global.Ctx, scanCmd) + cursor, sKeys, err = dissembleScan(results) + if err != nil { + return err + } + keys = append(keys, sKeys...) + if cursor == 0 { + break + } + } + var cmds = make(rueidis.Commands, 0) + for _, key := range keys { + relationItemsCmd := global.RedisConn.B().Smembers().Key(key).Build() + results := global.RedisConn.Do(global.Ctx, relationItemsCmd) + relationItems, err := results.AsStrSlice() + if err != nil { + return err + } + for _, item := range relationItems { + exist, err := Exists(item) + if err != nil { + return err + } + if !exist { + cmd := global.RedisConn.B().Srem().Key(key).Member(item).Build() + cmds = append(cmds, cmd) + } + } + } + errs := global.RedisConn.DoMulti(global.Ctx, cmds...) + firstErr, has := lo.Find(errs, func(elem rueidis.RedisResult) bool { + return elem.Error() != nil + }) + if has { + return firstErr.Error() + } else { + return nil + } +} diff --git a/main.go b/main.go index e617cf8..2332316 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main import ( + "electricity_bill_calc/cache" "electricity_bill_calc/config" "electricity_bill_calc/global" "electricity_bill_calc/model" @@ -157,8 +158,19 @@ func DBConnectionKeepLive() { } } +func RedisOrphanCleanup() { + for range time.Tick(2 * time.Minute) { + err := cache.ClearOrphanRelationItems() + if err != nil { + log.Printf("[Cache] [Cleanup] Orphan keys clear failed: %v", err) + continue + } + } +} + func main() { go DBConnectionKeepLive() + go RedisOrphanCleanup() gin.SetMode(config.ServerSettings.RunMode) r := router.Router() r.Run(fmt.Sprintf(":%d", config.ServerSettings.HttpPort))