| 46 | } |
| 47 | |
| 48 | func writeUserCache(user *UserBase, includeQuota bool) error { |
| 49 | if user == nil || user.Id <= 0 || !common.RedisEnabled { |
| 50 | return nil |
| 51 | } |
| 52 | user.CacheSchema = userCacheSchemaVersion |
| 53 | if user.AuthVersion <= 0 { |
| 54 | return fmt.Errorf("invalid user auth version") |
| 55 | } |
| 56 | includeQuotaArg := "0" |
| 57 | if includeQuota { |
| 58 | includeQuotaArg = "1" |
| 59 | } |
| 60 | ttl := userCacheTTLSeconds() |
| 61 | const script = ` |
| 62 | local incoming = tonumber(ARGV[1]) |
| 63 | local pending = tonumber(redis.call('GET', KEYS[2]) or '0') |
| 64 | local committed = tonumber(redis.call('GET', KEYS[3]) or '0') |
| 65 | local current = tonumber(redis.call('HGET', KEYS[1], 'AuthVersion') or '0') |
| 66 | if pending > incoming or committed > incoming or current > incoming then |
| 67 | return 0 |
| 68 | end |
| 69 | if committed < incoming then |
| 70 | redis.call('SET', KEYS[3], ARGV[1]) |
| 71 | end |
| 72 | if pending > 0 and pending <= incoming then |
| 73 | redis.call('DEL', KEYS[2]) |
| 74 | end |
| 75 | if ARGV[10] == '0' and redis.call('EXISTS', KEYS[1]) == 0 then |
| 76 | return 1 |
| 77 | end |
| 78 | redis.call('HSET', KEYS[1], |
| 79 | 'Id', ARGV[2], 'Group', ARGV[3], 'Email', ARGV[4], |
| 80 | 'Status', ARGV[5], 'Role', ARGV[6], 'Username', ARGV[7], |
| 81 | 'Setting', ARGV[8], 'AuthVersion', ARGV[1], 'CacheSchema', ARGV[9]) |
| 82 | if ARGV[10] == '1' and redis.call('HEXISTS', KEYS[1], 'Quota') == 0 then |
| 83 | redis.call('HSET', KEYS[1], 'Quota', ARGV[11]) |
| 84 | end |
| 85 | redis.call('EXPIRE', KEYS[1], ARGV[12]) |
| 86 | return 1` |
| 87 | result, err := common.RDB.Eval(context.Background(), script, |
| 88 | []string{getUserCacheKey(user.Id), getUserAuthFenceKey(user.Id), getUserAuthVersionKey(user.Id)}, |
| 89 | user.AuthVersion, user.Id, user.Group, user.Email, user.Status, user.Role, |
| 90 | user.Username, user.Setting, user.CacheSchema, includeQuotaArg, user.Quota, ttl, |
| 91 | ).Int() |
| 92 | if err != nil { |
| 93 | return err |
| 94 | } |
| 95 | if result == 0 { |
| 96 | return ErrUserAuthCachePending |
| 97 | } |
| 98 | return nil |
| 99 | } |
| 100 | |
| 101 | func getUserAuthVersionFloor(userId int) (int64, error) { |
| 102 | if !common.RedisEnabled { |