You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
264 lines
5.6 KiB
264 lines
5.6 KiB
package common
|
|
|
|
import (
|
|
"encoding/json"
|
|
"time"
|
|
|
|
"laic-backend/logger"
|
|
|
|
"github.com/gomodule/redigo/redis"
|
|
)
|
|
|
|
var _redis *redis.Pool
|
|
|
|
func InitRedis(source string) {
|
|
_redis = &redis.Pool{
|
|
MaxIdle: 3,
|
|
IdleTimeout: 240 * time.Second,
|
|
Dial: func() (redis.Conn, error) { return redis.DialURL(source) },
|
|
TestOnBorrow: func(c redis.Conn, t time.Time) error {
|
|
if time.Since(t) < time.Minute {
|
|
return nil
|
|
}
|
|
_, err := c.Do("PING")
|
|
return err
|
|
},
|
|
}
|
|
logger.INFO("redis ready")
|
|
}
|
|
|
|
func GetRedisPool() *redis.Pool {
|
|
return _redis
|
|
}
|
|
|
|
func GetString(key string) (string, error) {
|
|
c := _redis.Get()
|
|
defer c.Close()
|
|
return redis.String(c.Do("GET", key))
|
|
}
|
|
|
|
func GetBytes(key string) ([]byte, error) {
|
|
c := _redis.Get()
|
|
defer c.Close()
|
|
return redis.Bytes(c.Do("GET", key))
|
|
}
|
|
|
|
func GetInt64(key string) (int64, error) {
|
|
c := _redis.Get()
|
|
defer c.Close()
|
|
return redis.Int64(c.Do("GET", key))
|
|
}
|
|
|
|
func GetJSON[T any](key string) (*T, error) {
|
|
c := _redis.Get()
|
|
defer c.Close()
|
|
r, err := redis.Bytes(c.Do("GET", key))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var v T
|
|
err = json.Unmarshal(r, &v)
|
|
return &v, err
|
|
}
|
|
|
|
func SetValue(key string, n any) error {
|
|
c := _redis.Get()
|
|
defer c.Close()
|
|
_, err := c.Do("SET", key, n)
|
|
return err
|
|
}
|
|
|
|
func SetJSON(key string, n any) error {
|
|
c := _redis.Get()
|
|
defer c.Close()
|
|
data, err := json.Marshal(n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, err = c.Do("SET", key, data)
|
|
return err
|
|
}
|
|
|
|
func SetJSONWithExpired(key string, n any, second uint) error {
|
|
c := _redis.Get()
|
|
defer c.Close()
|
|
data, err := json.Marshal(n)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_, err = c.Do("SET", key, data, "EX", second)
|
|
return err
|
|
}
|
|
|
|
func SetValueWithExpired(key string, n any, second uint) error {
|
|
c := _redis.Get()
|
|
defer c.Close()
|
|
_, err := c.Do("SET", key, n, "EX", second)
|
|
return err
|
|
}
|
|
|
|
func SetRemoveIfKeyMissing(setKey, presenceKey, member string) (bool, error) {
|
|
const script = `if redis.call('EXISTS', KEYS[2]) == 0 then return redis.call('SREM', KEYS[1], ARGV[1]) end return 0`
|
|
n, err := redis.Int(exec_lua(script, []string{setKey, presenceKey}, member))
|
|
return n == 1, err
|
|
}
|
|
|
|
// SetNX 仅当 key 不存在时写入,返回是否写入成功
|
|
func SetNX(key string, value any) (bool, error) {
|
|
c := _redis.Get()
|
|
defer c.Close()
|
|
n, err := redis.Int(c.Do("SET", key, value, "NX"))
|
|
return n == 1, err
|
|
}
|
|
|
|
// IncrBy 原子自增,返回自增后的值(计费充值用)
|
|
func IncrBy(key string, delta int64) (int64, error) {
|
|
c := _redis.Get()
|
|
defer c.Close()
|
|
return redis.Int64(c.Do("INCRBY", key, delta))
|
|
}
|
|
|
|
// DecrBy 原子自减,返回自减后的值(计费扣减用)
|
|
func DecrBy(key string, delta int64) (int64, error) {
|
|
c := _redis.Get()
|
|
defer c.Close()
|
|
return redis.Int64(c.Do("DECRBY", key, delta))
|
|
}
|
|
|
|
func HasKey(key string) bool {
|
|
c := _redis.Get()
|
|
defer c.Close()
|
|
exists, err := redis.Int(c.Do("EXISTS", key))
|
|
if err != nil {
|
|
return false
|
|
}
|
|
return exists == 1
|
|
}
|
|
|
|
func HashGet(key string, field string) (string, error) {
|
|
c := _redis.Get()
|
|
defer c.Close()
|
|
return redis.String(c.Do("HGET", key, field))
|
|
}
|
|
|
|
func HashGetAll(key string) (map[string]string, error) {
|
|
c := _redis.Get()
|
|
defer c.Close()
|
|
return redis.StringMap(c.Do("HGETALL", key))
|
|
}
|
|
|
|
func HashSetValue(key string, field string, n any) error {
|
|
c := _redis.Get()
|
|
defer c.Close()
|
|
_, err := c.Do("HSET", key, field, n)
|
|
return err
|
|
}
|
|
|
|
func HashSetValues(key string, values map[string]any) error {
|
|
c := _redis.Get()
|
|
defer c.Close()
|
|
args := make([]any, 0, len(values)*2+1)
|
|
args = append(args, key)
|
|
for k, v := range values {
|
|
args = append(args, k, v)
|
|
}
|
|
_, err := c.Do("HMSET", args...)
|
|
return err
|
|
}
|
|
|
|
func SetMembers(key string) ([]string, error) {
|
|
c := _redis.Get()
|
|
defer c.Close()
|
|
return redis.Strings(c.Do("SMEMBERS", key))
|
|
}
|
|
|
|
func SetAdd(key string, n any) error {
|
|
c := _redis.Get()
|
|
defer c.Close()
|
|
_, err := c.Do("SADD", key, n)
|
|
return err
|
|
}
|
|
|
|
func SetRemove(key string, n any) error {
|
|
c := _redis.Get()
|
|
defer c.Close()
|
|
_, err := c.Do("SREM", key, n)
|
|
return err
|
|
}
|
|
|
|
func SetMemberExists(key string, value string) (bool, error) {
|
|
c := _redis.Get()
|
|
defer c.Close()
|
|
exists, err := redis.Int(c.Do("SISMEMBER", key, value))
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return exists == 1, nil
|
|
}
|
|
|
|
func exec_lua(lua string, keys []string, args ...any) (any, error) {
|
|
c := _redis.Get()
|
|
defer c.Close()
|
|
keylen := 0
|
|
if keys != nil {
|
|
keylen = len(keys)
|
|
}
|
|
arr := make([]any, 0, keylen+len(args)+2)
|
|
arr = append(arr, lua)
|
|
arr = append(arr, keylen)
|
|
for _, k := range keys {
|
|
arr = append(arr, k)
|
|
}
|
|
arr = append(arr, args...)
|
|
return c.Do("EVAL", arr...)
|
|
}
|
|
|
|
func ExecLua(lua string, keys []string, args ...any) error {
|
|
_, err := exec_lua(lua, keys, args...)
|
|
return err
|
|
}
|
|
|
|
func GetLuaInt64(lua string, keys []string, args ...any) (int64, error) {
|
|
return redis.Int64(exec_lua(lua, keys, args...))
|
|
}
|
|
|
|
func GetLuaStrings(lua string, keys []string, args ...any) ([]string, error) {
|
|
return redis.Strings(exec_lua(lua, keys, args...))
|
|
}
|
|
|
|
func GetLuaInt64s(lua string, keys []string, args ...any) ([]int64, error) {
|
|
return redis.Int64s(exec_lua(lua, keys, args...))
|
|
}
|
|
|
|
func Delete(key ...string) error {
|
|
c := _redis.Get()
|
|
defer c.Close()
|
|
param := make([]any, len(key))
|
|
for i, k := range key {
|
|
param[i] = k
|
|
}
|
|
_, err := c.Do("DEL", param...)
|
|
return err
|
|
}
|
|
|
|
func GetKeysWithPrefix(prefix string) ([]string, error) {
|
|
c := _redis.Get()
|
|
defer c.Close()
|
|
cursor := 0
|
|
var keys []string
|
|
for {
|
|
values, err := redis.Values(c.Do("SCAN", cursor, "MATCH", prefix+"*"))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var items []string
|
|
if _, err := redis.Scan(values, &cursor, &items); err != nil {
|
|
return nil, err
|
|
}
|
|
keys = append(keys, items...)
|
|
if cursor == 0 {
|
|
break
|
|
}
|
|
}
|
|
return keys, nil
|
|
}
|
|
|