u
This commit is contained in:
1 parent
835958886e
commit
d04d22723b
155 files changed
+543
-9793
No files matched your search
@@ -0,0 +1,174 @@
|
||||
package redisx
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
// ---------------- 基础方法 ----------------
|
||||
|
||||
// Set 设置任意 key
|
||||
func Set(key string, value interface{}, expire time.Duration) error {
|
||||
return Client().Set(context.Background(), key, value, expire).Err()
|
||||
}
|
||||
|
||||
// Get 获取任意 key 的值,返回 string
|
||||
func Get(key string) (string, error) {
|
||||
val, err := Client().Get(context.Background(), key).Result()
|
||||
if errors.Is(err, redis.Nil) {
|
||||
return "", nil
|
||||
}
|
||||
return val, err
|
||||
}
|
||||
|
||||
// Delete 删除任意 key
|
||||
func Delete(key string) error {
|
||||
return Client().Del(context.Background(), key).Err()
|
||||
}
|
||||
|
||||
// Exists 判断 key 是否存在
|
||||
func Exists(key string) (bool, error) {
|
||||
cnt, err := Client().Exists(context.Background(), key).Result()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return cnt > 0, nil
|
||||
}
|
||||
|
||||
/*
|
||||
Key design:
|
||||
|
||||
space:user:{spaceId}:{userId} -> role (string/int)
|
||||
space:users:{spaceId} -> Set(userId)
|
||||
*/
|
||||
|
||||
// ================== Role ==================
|
||||
|
||||
const (
|
||||
RoleMember int32 = 1
|
||||
RoleAdmin int32 = 5
|
||||
RoleOwner int32 = 9
|
||||
|
||||
SpaceUserTTL = 10 * time.Minute
|
||||
)
|
||||
|
||||
// ================== Key helpers ==================
|
||||
|
||||
func spaceUserKey(spaceId, userId int64) string {
|
||||
return fmt.Sprintf("space:user:%d:%d", spaceId, userId)
|
||||
}
|
||||
|
||||
func spaceUsersKey(spaceId int64) string {
|
||||
return fmt.Sprintf("space:users:%d", spaceId)
|
||||
}
|
||||
|
||||
// ================== Domain APIs ==================
|
||||
|
||||
// JoinSpace
|
||||
// - add user to space users set
|
||||
// - set user role
|
||||
func JoinSpace(spaceId, userId int64, role int32) error {
|
||||
ctx := context.Background()
|
||||
|
||||
// 1. add to space users
|
||||
if err := Client().SAdd(ctx, spaceUsersKey(spaceId), userId).Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 2. set role
|
||||
if err := Set(spaceUserKey(spaceId, userId), role, SpaceUserTTL); err != nil {
|
||||
// rollback
|
||||
_ = Client().SRem(ctx, spaceUsersKey(spaceId), userId).Err()
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// LeaveSpace
|
||||
// - remove user from space
|
||||
// - delete role cache
|
||||
func LeaveSpace(spaceId, userId int64) error {
|
||||
ctx := context.Background()
|
||||
|
||||
if err := Client().SRem(ctx, spaceUsersKey(spaceId), userId).Err(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return Delete(spaceUserKey(spaceId, userId))
|
||||
}
|
||||
|
||||
// KickSpaceUser = LeaveSpace
|
||||
func KickSpaceUser(spaceId, userId int64) error {
|
||||
return LeaveSpace(spaceId, userId)
|
||||
}
|
||||
|
||||
// ChangeSpaceUserRole
|
||||
func ChangeSpaceUserRole(spaceId, userId int64, role int32) error {
|
||||
ok, err := IsUserInSpace(spaceId, userId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !ok {
|
||||
return fmt.Errorf("user not in space")
|
||||
}
|
||||
|
||||
return Set(spaceUserKey(spaceId, userId), role, SpaceUserTTL)
|
||||
}
|
||||
|
||||
// ================== Query APIs ==================
|
||||
|
||||
// GetSpaceUserRole
|
||||
// return 0 means not exists
|
||||
func GetSpaceUserRole(spaceId, userId int64) (int32, error) {
|
||||
val, err := Get(spaceUserKey(spaceId, userId))
|
||||
if err != nil || val == "" {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
r, err := strconv.ParseInt(val, 10, 32)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int32(r), nil
|
||||
}
|
||||
|
||||
func IsUserInSpace(spaceId, userId int64) (bool, error) {
|
||||
return Client().
|
||||
SIsMember(context.Background(), spaceUsersKey(spaceId), userId).
|
||||
Result()
|
||||
}
|
||||
|
||||
func GetSpaceUsers(spaceId int64) ([]int64, error) {
|
||||
members, err := Client().
|
||||
SMembers(context.Background(), spaceUsersKey(spaceId)).
|
||||
Result()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
users := make([]int64, 0, len(members))
|
||||
for _, m := range members {
|
||||
uid, err := strconv.ParseInt(m, 10, 64)
|
||||
if err == nil {
|
||||
users = append(users, uid)
|
||||
}
|
||||
}
|
||||
return users, nil
|
||||
}
|
||||
|
||||
// CheckRole
|
||||
// check whether user's role in space >= needRole
|
||||
func CheckRole(spaceId, userId int64, needRole int32) (bool, error) {
|
||||
userRole, err := GetSpaceUserRole(spaceId, userId)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return userRole == needRole, nil
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
package redisx
|
||||
|
||||
import (
|
||||
"allapp/conf"
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/redis/go-redis/v9"
|
||||
)
|
||||
|
||||
var (
|
||||
client *redis.Client
|
||||
once sync.Once
|
||||
)
|
||||
|
||||
// Init 初始化 Redis(只会执行一次)
|
||||
func Init() *redis.Client {
|
||||
once.Do(func() {
|
||||
redisConfig := conf.GetConf().Redis
|
||||
|
||||
addr := fmt.Sprintf("%s:%d", redisConfig.Host, redisConfig.Port)
|
||||
|
||||
client = redis.NewClient(&redis.Options{
|
||||
Addr: addr,
|
||||
Password: redisConfig.Password,
|
||||
DB: redisConfig.Db,
|
||||
})
|
||||
|
||||
// 启动时检测连接
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||
defer cancel()
|
||||
|
||||
if err := client.Ping(ctx).Err(); err != nil {
|
||||
panic("redis 连接失败: " + err.Error())
|
||||
}
|
||||
})
|
||||
|
||||
return client
|
||||
}
|
||||
|
||||
// Client 获取 Redis 客户端
|
||||
func Client() *redis.Client {
|
||||
if client == nil {
|
||||
panic("redis 尚未初始化")
|
||||
}
|
||||
return client
|
||||
}
|
||||
Reference in new issue
Block a user