user.go 5.36 KB
package user_c

import (
	"git.hilo.cn/hilo-common/domain"
	"git.hilo.cn/hilo-common/resource/mysql"
	redisV8 "github.com/go-redis/redis/v8"
	"github.com/jinzhu/copier"
	"hilo-group/_const/redis_key/user_k"
	"hilo-group/common"
	"hilo-group/domain/cache"
	"hilo-group/domain/model/user_m"
	"hilo-group/myerr"
	"hilo-group/myerr/bizerr"
	"time"
)

// 获取用户简要信息
// param userId 用户id
func GetUserTinyById(model *domain.Model, userId mysql.ID) (*user_m.UserTiny, error) {
	userTiny := new(user_m.UserTiny)
	key := user_k.GetUserTinyKey(userId)
	err := cache.GetJSON(model, key, userTiny)
	if err != nil && err != redisV8.Nil {
		return nil, err
	}
	if err == redisV8.Nil {
		// cache miss,get from mysql
		if user, err := user_m.GetUser(model, userId); err != nil {
			return nil, err
		} else {
			copier.Copy(userTiny, user)
			err = cacheUserTiny(model, user)
			if err != nil {
				return nil, err
			}
		}
	}
	return userTiny, nil
}

// 获取用户简要信息By ExternalId
func GetUserByExternalId(model *domain.Model, externalId mysql.Str) (*user_m.UserTiny, error) {
	userId, err := ToUserId(model, externalId)
	if err != nil {
		return nil, err
	}
	return GetUserTinyById(model, userId)
}

// externalId 到 userId
func ToUserId(model *domain.Model, externalId mysql.Str) (mysql.ID, error) {
	if externalId == "" {
		return 0, myerr.NewSysError("externalId 不能为空")
	}
	userId, err := model.Redis.Get(model.Context, user_k.GetExternalIdToUidKey(externalId)).Int64()
	if err != nil && err != redisV8.Nil {
		return 0, err
	}
	// cache miss,sync from db
	if err == redisV8.Nil {
		if user, err := user_m.GetUserByExtId(model, externalId); err != nil {
			return 0, bizerr.ExternalIdNoExist
		} else {
			if err = cacheUserTiny(model, user); err != nil {
				return 0, err
			}
			userId = int64(user.ID)
		}
	}
	return mysql.ID(userId), nil
}

// code 到 userId
func ToUserIdByCode(model *domain.Model, code mysql.Str) (mysql.ID, error) {
	if code == "" {
		return 0, myerr.NewSysError("code 不能为空")
	}
	userId, err := model.Redis.Get(model.Context, user_k.GetCodeToUidKey(code)).Int64()
	if err != nil && err != redisV8.Nil {
		return 0, err
	}
	// cache miss,sync from db
	if err == redisV8.Nil {
		if user, err := user_m.GetUserByCode(model, code); err != nil {
			return 0, bizerr.CodeNoExist
		} else {
			if err = cacheUserTiny(model, user); err != nil {
				return 0, err
			}
			userId = int64(user.ID)
		}
	}
	return mysql.ID(userId), nil
}

// 缓存userTiny
// 顺手缓存externalId->userId
// 顺手缓存code->userId
// param user: 已经在上层获取的db User结构
func cacheUserTiny(model *domain.Model, user *user_m.User) error {
	userTiny := ToUserTinyBy(user)
	//userTiny := new(user_m.UserTiny)
	//if err := copier.Copy(userTiny, user); err != nil {
	//	return err
	//}
	// cache externalId->userId
	if err := model.Redis.SetEX(model.Context, user_k.GetExternalIdToUidKey(user.ExternalId), user.ID, cache.GetDefaultTTL()).Err(); err != nil {
		return err
	}
	// cache code->userId
	if err := model.Redis.SetEX(model.Context, user_k.GetCodeToUidKey(user.Code), user.ID, cache.GetDefaultTTL()).Err(); err != nil {
		return err
	}
	if err := cache.SetJSON(model, user_k.GetUserTinyKey(user.ID), userTiny); err != nil {
		return err
	}
	return nil
}

// 获取用户简要信息
// param userIds 用户id列表
func GetUserTinyMap(model *domain.Model, userIds []mysql.ID, isDefAvatar bool) (map[mysql.ID]*user_m.UserTiny, error) {
	redisNoIds := make([]mysql.ID, 0)
	res := make(map[mysql.ID]*user_m.UserTiny)
	for _, id := range userIds {
		userTiny := new(user_m.UserTiny)
		key := user_k.GetUserTinyKey(id)
		err := cache.GetJSON(model, key, userTiny)
		if err != nil && err != redisV8.Nil {
			return nil, err
		}
		if err == redisV8.Nil {
			redisNoIds = append(redisNoIds, id)
		} else if userTiny.ID > 0 {
			res[id] = userTiny
		}
	}
	// 从db中读
	users, err := user_m.GetUsers(model, redisNoIds)
	if err != nil {
		return nil, err
	}
	for _, u := range users {
		userTiny := ToUserTinyBy(u)
		err = cacheUserTiny(model, u)
		if err != nil {
			return nil, err
		}
		res[userTiny.ID] = userTiny
	}
	if isDefAvatar {
		for _, v := range res {
			if len(v.Avatar) <= 0 {
				if v.Sex == mysql.MAN {
					v.Avatar = common.MakeFullUrl(common.DefaultAvatarMan)
				} else if v.Sex == mysql.WOMAN {
					v.Avatar = common.MakeFullUrl(common.DefaultAvatarWoman)
				}
			}
		}
	}
	return res, nil
}

func ToUserTinyBy(user *user_m.User) *user_m.UserTiny {
	return &user_m.UserTiny{
		ID:           user.ID,
		Avatar:       IfLogoutStr(IfLogout(user.LogoutTime), "", user.Avatar),
		ExternalId:   user.ExternalId,
		Nick:         IfLogoutNick(IfLogout(user.LogoutTime), user.Code, user.Nick),
		Sex:          user.Sex,
		Code:         user.Code,
		Country:      user.Country,
		CountryIcon:  user.CountryIcon,
		IsPrettyCode: user.IsPrettyCode(),
		IsLogout:     IfLogout(user.LogoutTime),
		Birthday:     BirthdayToUint64(&user.Birthday),
	}
}

func IfLogout(logoutTime int64) bool {
	return logoutTime > 0 && time.Now().Unix() > logoutTime
}

func BirthdayToUint64(birthday *mysql.Timestamp) *uint64 {
	if *birthday == 0 {
		return nil
	}
	return (*uint64)(birthday)
}

func IfLogoutStr(condition bool, trueVal, falseVal string) string {
	if condition {
		return trueVal
	}
	return falseVal
}

func IfLogoutNick(condition bool, code string, nick string) string {
	if condition {
		return "Hilo No." + code
	}
	return nick
}