Commit 99276f71 authored by vicotor's avatar vicotor

add user info to cache

parent 85e94860
package cachedata
import "errors"
var (
ErrNotExist = errors.New("not exist")
)
package cachedata
......@@ -95,3 +95,15 @@ func (c *CacheData) GetTaskWithId(id int64) (*model.TaskType, error) {
return nil, err
}
}
func (c *CacheData) SetTaskDataToRedis(task *model.TaskType) error {
taskIdKey := "task-id-" + strconv.FormatInt(task.ID, 10)
if data, err := json.Marshal(task); err == nil {
if err = c.rdb.Set(c.ctx, taskIdKey, string(data), 0).Err(); err == nil {
return nil
}
return err
} else {
return err
}
}
package cachedata
import (
"github.com/odysseus/payment/model"
"github.com/odysseus/payment/redisService"
goredislib "github.com/redis/go-redis/v9"
log "github.com/sirupsen/logrus"
"strconv"
"time"
)
const (
USER_INFO_LOCK_PRE = "u-lock:"
USER_INFO_KEY_PRE = "u-info:"
USER_INFO_DELETED_KEY = USER_INFO_KEY_PRE + "deleted:"
USER_INFO_LEVEL_KEY = USER_INFO_KEY_PRE + "level:"
USER_INFO_BALANCE_KEY = USER_INFO_KEY_PRE + "bal:"
USER_INFO_CHARGE_KEY = USER_INFO_KEY_PRE + "charge:"
USER_INFO_LOCK_DURATION = 10 * 1000 * 1000
)
type UserInfo struct {
Deleted int `json:"deleted"`
Level int `json:"level"`
Balance int64 `json:"balance"`
Charge int64 `json:"charge"`
}
func (c *CacheData) checkExist(uid int64) (bool, error) {
key := USER_INFO_DELETED_KEY + strconv.FormatInt(uid, 10)
if _, err := c.rdb.Get(c.ctx, key).Result(); err == nil {
return true, nil
} else if err == goredislib.Nil {
return false, nil
} else {
return false, err
}
}
// value: 0: not deleted, 1: deleted
func (c *CacheData) UpdateUserDeleted(uid int64, value int) error {
exist, err := c.checkExist(uid)
if err != nil {
return err
}
if !exist {
return ErrNotExist
}
lockKey := USER_INFO_LOCK_PRE + strconv.FormatInt(uid, 10)
for {
locked, release, err := redisService.TryAcquire(c.ctx, c.rdb, lockKey, USER_INFO_LOCK_DURATION)
if err != nil {
log.WithError(err).Error("failed to acquire user lock")
return err
}
if !locked {
time.Sleep(USER_INFO_LOCK_DURATION)
continue
}
defer release()
key := USER_INFO_DELETED_KEY + strconv.FormatInt(uid, 10)
err = c.rdb.Set(c.ctx, key, value, 0).Err()
if err != nil {
log.WithError(err).Error("failed to set user deleted")
return err
}
}
return nil
}
func (c *CacheData) UpdateUserLevel(uid int64, value int) error {
exist, err := c.checkExist(uid)
if err != nil {
return err
}
if !exist {
return ErrNotExist
}
lockKey := USER_INFO_LOCK_PRE + strconv.FormatInt(uid, 10)
for {
locked, release, err := redisService.TryAcquire(c.ctx, c.rdb, lockKey, USER_INFO_LOCK_DURATION)
if err != nil {
log.WithError(err).Error("failed to acquire user lock")
return err
}
if !locked {
time.Sleep(USER_INFO_LOCK_DURATION)
continue
}
defer release()
key := USER_INFO_LEVEL_KEY + strconv.FormatInt(uid, 10)
err = c.rdb.Set(c.ctx, key, value, 0).Err()
if err != nil {
log.WithError(err).Error("failed to set user level")
return err
}
}
return nil
}
func (c *CacheData) UpdateUserBalance(uid int64, value int) error {
exist, err := c.checkExist(uid)
if err != nil {
return err
}
if !exist {
return ErrNotExist
}
lockKey := USER_INFO_LOCK_PRE + strconv.FormatInt(uid, 10)
for {
locked, release, err := redisService.TryAcquire(c.ctx, c.rdb, lockKey, USER_INFO_LOCK_DURATION)
if err != nil {
log.WithError(err).Error("failed to acquire user lock")
return err
}
if !locked {
time.Sleep(USER_INFO_LOCK_DURATION)
continue
}
defer release()
key := USER_INFO_BALANCE_KEY + strconv.FormatInt(uid, 10)
err = c.rdb.Set(c.ctx, key, value, 0).Err()
if err != nil {
log.WithError(err).Error("failed to set user balance")
return err
}
}
return nil
}
// update equal set
func (c *CacheData) UpdateUserCharge(uid int64, value int) error {
exist, err := c.checkExist(uid)
if err != nil {
return err
}
if !exist {
return ErrNotExist
}
lockKey := USER_INFO_LOCK_PRE + strconv.FormatInt(uid, 10)
for {
locked, release, err := redisService.TryAcquire(c.ctx, c.rdb, lockKey, USER_INFO_LOCK_DURATION)
if err != nil {
log.WithError(err).Error("failed to acquire user lock")
return err
}
if !locked {
time.Sleep(USER_INFO_LOCK_DURATION)
continue
}
defer release()
key := USER_INFO_CHARGE_KEY + strconv.FormatInt(uid, 10)
err = c.rdb.Set(c.ctx, key, value, 0).Err()
if err != nil {
log.WithError(err).Error("failed to set user charge")
return err
}
}
return nil
}
func (c *CacheData) SetUserInfo(user *model.User) error {
info := UserInfo{
Deleted: int(user.Deleted),
Level: int(user.LevelId),
Balance: user.Balance,
Charge: 0,
}
idStr := strconv.FormatInt(user.ID, 10)
// set every info with pipeline
pip := c.rdb.TxPipeline()
// set user deleted
pip.Set(c.ctx, USER_INFO_DELETED_KEY+idStr, info.Deleted, 0)
// set user level
pip.Set(c.ctx, USER_INFO_LEVEL_KEY+idStr, info.Level, 0)
// set user balance
pip.Set(c.ctx, USER_INFO_BALANCE_KEY+idStr, info.Balance, 0)
// set user charge
pip.Set(c.ctx, USER_INFO_CHARGE_KEY+idStr, info.Charge, 0)
_, err := pip.Exec(c.ctx)
return err
}
func (c *CacheData) GetUserInfo(uid int64) (*UserInfo, error) {
idStr := strconv.FormatInt(uid, 10)
// get every info with pipeline
pip := c.rdb.Pipeline()
// get user deleted
deletedCmd := pip.Get(c.ctx, USER_INFO_DELETED_KEY+idStr)
// get user level
levelCmd := pip.Get(c.ctx, USER_INFO_LEVEL_KEY+idStr)
// get user balance
balCmd := pip.Get(c.ctx, USER_INFO_BALANCE_KEY+idStr)
// get user charge
chargeCmd := pip.Get(c.ctx, USER_INFO_CHARGE_KEY+idStr)
_, err := pip.Exec(c.ctx)
if err != nil {
log.WithError(err).Error("failed to get user info")
return nil, err
}
var info = new(UserInfo)
if deletedCmd.Err() == nil && levelCmd.Err() == nil && balCmd.Err() == nil && chargeCmd.Err() == nil {
info.Deleted, _ = strconv.Atoi(deletedCmd.Val())
info.Level, _ = strconv.Atoi(levelCmd.Val())
info.Balance, _ = strconv.ParseInt(balCmd.Val(), 10, 64)
info.Charge, _ = strconv.ParseInt(chargeCmd.Val(), 10, 64)
return info, nil
}
if deletedCmd.Err() == goredislib.Nil || levelCmd.Err() == goredislib.Nil || balCmd.Err() == goredislib.Nil || chargeCmd.Err() == goredislib.Nil {
// get user from db.
if user, err := c.userRepo.GetById(uid); err == nil {
info.Deleted = int(user.Deleted)
info.Level = int(user.LevelId)
info.Balance = user.Balance
info.Charge = 0
c.SetUserInfo(user)
return info, nil
}
}
return nil, err
}
......@@ -2,6 +2,7 @@ package payment
import (
"context"
"github.com/odysseus/payment/redisService"
"github.com/redis/go-redis/v9"
"time"
)
......@@ -10,6 +11,12 @@ type Payment struct {
rdb *redis.Client
}
type RedisConnParam struct {
Addr string
Password string
DbIndex int
}
func NewPayment(redisConfig RedisConnParam) *Payment {
return &Payment{
rdb: redis.NewClient(&redis.Options{
......@@ -95,7 +102,7 @@ func (p *Payment) MIncrBalance(ctx context.Context, uids []string, bals []int64)
for i, _ := range uids {
for {
locked, release, _ := tryAcquire(ctx, p.rdb, lockkeys[i], 5*time.Second)
locked, release, _ := redisService.TryAcquire(ctx, p.rdb, lockkeys[i], 5*time.Second)
if locked {
releases[i] = release
break
......@@ -142,7 +149,7 @@ func (p *Payment) MDecrBalance(ctx context.Context, uids []string, bals []int64)
for i, _ := range uids {
for {
locked, release, _ := tryAcquire(ctx, p.rdb, lockkeys[i], 5*time.Second)
locked, release, _ := redisService.TryAcquire(ctx, p.rdb, lockkeys[i], 5*time.Second)
if locked {
releases[i] = release
break
......@@ -189,7 +196,7 @@ func (p *Payment) MIncrCharge(ctx context.Context, uids []string, bals []int64)
for i, _ := range uids {
for {
locked, release, _ := tryAcquire(ctx, p.rdb, lockkeys[i], 5*time.Second)
locked, release, _ := redisService.TryAcquire(ctx, p.rdb, lockkeys[i], 5*time.Second)
if locked {
releases[i] = release
break
......@@ -236,7 +243,7 @@ func (p *Payment) MDecrCharge(ctx context.Context, uids []string, bals []int64)
for i, _ := range uids {
for {
locked, release, _ := tryAcquire(ctx, p.rdb, lockkeys[i], 5*time.Second)
locked, release, _ := redisService.TryAcquire(ctx, p.rdb, lockkeys[i], 5*time.Second)
if locked {
releases[i] = release
break
......@@ -283,7 +290,7 @@ func (p *Payment) MIncrCredits(ctx context.Context, uids []string, bals []int64)
for i, _ := range uids {
for {
locked, release, _ := tryAcquire(ctx, p.rdb, lockkeys[i], 5*time.Second)
locked, release, _ := redisService.TryAcquire(ctx, p.rdb, lockkeys[i], 5*time.Second)
if locked {
releases[i] = release
break
......@@ -330,7 +337,7 @@ func (p *Payment) MDecrCredits(ctx context.Context, uids []string, bals []int64)
for i, _ := range uids {
for {
locked, release, _ := tryAcquire(ctx, p.rdb, lockkeys[i], 5*time.Second)
locked, release, _ := redisService.TryAcquire(ctx, p.rdb, lockkeys[i], 5*time.Second)
if locked {
releases[i] = release
break
......@@ -365,7 +372,7 @@ func (p *Payment) IncrBalance(ctx context.Context, uid string, bal int64) (int64
key := "balance:" + uid
lockkey := "lk-bal" + uid
for {
locked, release, err := tryAcquire(ctx, p.rdb, lockkey, 5*time.Second)
locked, release, err := redisService.TryAcquire(ctx, p.rdb, lockkey, 5*time.Second)
if err != nil {
return 0, err
}
......@@ -387,7 +394,7 @@ func (p *Payment) DecrBalance(ctx context.Context, uid string, bal int64) (int64
key := "balance:" + uid
lockkey := "lk-bal" + uid
for {
locked, release, err := tryAcquire(ctx, p.rdb, lockkey, 5*time.Second)
locked, release, err := redisService.TryAcquire(ctx, p.rdb, lockkey, 5*time.Second)
if err != nil {
return 0, err
}
......@@ -406,7 +413,7 @@ func (p *Payment) IncrCharge(ctx context.Context, uid string, bal int64) (int64,
key := "charge:" + uid
lockkey := "lk-char" + uid
for {
locked, release, err := tryAcquire(ctx, p.rdb, lockkey, 5*time.Second)
locked, release, err := redisService.TryAcquire(ctx, p.rdb, lockkey, 5*time.Second)
if err != nil {
return 0, err
}
......@@ -430,7 +437,7 @@ func (p *Payment) DecrCharge(ctx context.Context, uid string, bal int64) (int64,
key := "charge:" + uid
lockkey := "lk-char" + uid
for {
locked, release, err := tryAcquire(ctx, p.rdb, lockkey, 5*time.Second)
locked, release, err := redisService.TryAcquire(ctx, p.rdb, lockkey, 5*time.Second)
if err != nil {
return 0, err
}
......@@ -449,7 +456,7 @@ func (p *Payment) IncrCredits(ctx context.Context, uid string, bal int64) (int64
key := "credits:" + uid
lockkey := "lk-credit" + uid
for {
locked, release, err := tryAcquire(ctx, p.rdb, lockkey, 5*time.Second)
locked, release, err := redisService.TryAcquire(ctx, p.rdb, lockkey, 5*time.Second)
if err != nil {
return 0, err
}
......@@ -473,7 +480,7 @@ func (p *Payment) DecrCredits(ctx context.Context, uid string, bal int64) (int64
key := "credits:" + uid
lockkey := "lk-credit" + uid
for {
locked, release, err := tryAcquire(ctx, p.rdb, lockkey, 5*time.Second)
locked, release, err := redisService.TryAcquire(ctx, p.rdb, lockkey, 5*time.Second)
if err != nil {
return 0, err
}
......
package payment
package redisService
import (
"context"
......@@ -11,13 +11,7 @@ import (
"time"
)
type RedisConnParam struct {
Addr string
Password string
DbIndex int
}
func tryAcquire(ctx context.Context, rs *goredislib.Client, lockKey string, lockTimeout time.Duration) (acquired bool, release func(), _ error) {
func TryAcquire(ctx context.Context, rs *goredislib.Client, lockKey string, lockTimeout time.Duration) (acquired bool, release func(), _ error) {
timeout := time.Now().Add(lockTimeout).UnixNano()
lockToken := fmt.Sprintf("%d,%s", timeout, uuid.New().String())
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment