package redis import ( "encoding/json" "apigo.cc/gojs" "apigo.cc/gojs/goja" "github.com/ssgo/redis" "github.com/ssgo/u" ) var defaultConnName = "default" var defaultConn = &RedisObj{} func init() { tsCode := gojs.MakeTSCode(defaultConn) gojs.Register("apigo.cc/gojs/redis", gojs.Module{ ObjectMaker: func(vm *goja.Runtime) gojs.Map { defaultConn.pool = redis.GetRedis(defaultConnName, gojs.GetLogger(vm)) return gojs.ToMap(defaultConn) }, TsCode: tsCode, Desc: "redis api by github.com/ssgo/redis", SetSSKey: func(key, iv []byte) { redis.SetEncryptKeys(key, iv) }, }) } type RedisObj struct { Redis } func (rd *RedisObj) GetRedis(vm *goja.Runtime, connUrl string) *Redis { conn := redis.GetRedis(connUrl, gojs.GetLogger(vm)) return &Redis{pool: conn} } func (rd *RedisObj) SetDefault(connUrl string, thisArg goja.Value, vm *goja.Runtime) { defaultConnName = connUrl defaultConn.pool = redis.GetRedis(connUrl, gojs.GetLogger(vm)) } type Redis struct { pool *redis.Redis } // Destroy 关闭连接池 func (rd *Redis) Destroy() error { return rd.pool.Destroy() } // Do 执行Redis操作,这是底层接口 // Do cmd 命令 // Do values 参数,根据命令传入不同参数 // Do return 返回字符串数据,需要根据数据内容自行解析处理 func (rd *Redis) Do(cmd string, values ...any) string { return rd.pool.Do(cmd, values...).String() } // Del 删除 // Del keys 传入一个或多个Key // Del return 成功删除的个数 func (rd *Redis) Del(keys ...string) int { return rd.pool.Do("DEL", u.ToInterfaceArray(keys)...).Int() } // Exists 判断是否Key存在 // * key 指定一个Key // Exists return 是否存在 func (rd *Redis) Exists(key string) bool { return rd.pool.Do("EXISTS " + key).Bool() } // Expire 设置Key的过期时间 // * seconds 过期时间的秒数 // Expire return 是否成功 func (rd *Redis) Expire(key string, seconds int) bool { return rd.pool.Do("EXPIRE "+key, seconds).Bool() } // ExpireAt 设置Key的过期时间(指定具体时间) // ExpireAt time 过期时间的时间戳,单位秒 // ExpireAt return 是否成功 func (rd *Redis) ExpireAt(key string, time int) bool { return rd.pool.Do("EXPIREAT "+key, time).Bool() } // Keys 查询Key // * patten 查询条件,例如:"SESS_*" // * return []string 查询到的Key列表 func (rd *Redis) Keys(patten string) []string { return rd.pool.Do("KEYS " + patten).Strings() } // Get 读取Key的内容 // * return any 如果是一个对象则返回反序列化后的对象,否则返回字符串 func (rd *Redis) Get(key string) any { return makeRedisResult(rd.pool.Do("GET " + key)) } // GetEX 读取Key的内容并更新过期时间 func (rd *Redis) GetEX(key string, seconds int) any { r := rd.pool.Do("GET " + key) if r.String() != "" { rd.pool.EXPIRE(key, seconds) } return makeRedisResult(r) } // Set 存储内容到Key // * value 对象或字符串 // * return bool 是否成功 func (rd *Redis) Set(key string, value any) bool { return rd.pool.Do("SET "+key, value).Bool() } // SetEX 存储内容到Key并设置过期时间 func (rd *Redis) SetEX(key string, seconds int, value any) bool { return rd.pool.Do("SETEX "+key, seconds, value).Bool() } // SetNX 存储内容到一个不存在的Key,如果Key已经存在则设置失败 func (rd *Redis) SetNX(key string, value any) bool { return rd.pool.Do("SETNX "+key, value).Bool() } // GetSet 将给定 key 的值设为 value ,并返回 key 的旧值(old value) func (rd *Redis) GetSet(key string, value any) any { return makeRedisResult(rd.pool.Do("GETSET "+key, value)) } // Incr 将 key 中储存的数值增一 // Incr * int64 最新的计数 func (rd *Redis) Incr(key string) int64 { return rd.pool.Do("INCR " + key).Int64() } // Decr 将 key 中储存的数值减一 func (rd *Redis) Decr(key string) int64 { return rd.pool.Do("DECR " + key).Int64() } // IncrBy 将 key 中储存的数值加上增量 increment func (rd *Redis) IncrBy(key string, increment int64) int64 { return rd.pool.Do("INCRBY "+key, increment).Int64() } // DecrBy 将 key 中储存的数值减去加上增量 increment func (rd *Redis) DecrBy(key string, increment int64) int64 { return rd.pool.Do("DECRBY "+key, increment).Int64() } // MGet 获取所有(一个或多个)给定 key 的值 // MGet return []any 按照查询key的顺序返回结果,如果结果是一个对象则返回反序列化后的对象,否则返回字符串 func (rd *Redis) MGet(keys ...string) []any { return makeRedisResults(rd.pool.Do("MGET", u.ToInterfaceArray(keys)...)) } // MSet 同时设置一个或多个 key-value 对 // MSet keyAndValues 按照key-value的顺序依次传入一个或多个数据 func (rd *Redis) MSet(keyAndValues ...any) bool { return rd.pool.Do("MSET", keyAndValues...).Bool() } // HGet 获取存储在哈希表中指定字段的值 // * field 字段 func (rd *Redis) HGet(key, field string) any { return makeRedisResult(rd.pool.Do("HGET "+key, field)) } // HSet 将哈希表 key 中的字段 field 的值设为 value func (rd *Redis) HSet(key, field string, value any) bool { return rd.pool.Do("HSET "+key, field, value).Bool() } // HSetNX 只有在字段 field 不存在时,设置哈希表字段的值 func (rd *Redis) HSetNX(key, field string, value any) bool { return rd.pool.Do("HSETNX "+key, field, value).Bool() } // HMGet 获取所有给定字段的值 // * fields 字段列表 func (rd *Redis) HMGet(key string, fields ...string) []any { return makeRedisResults(rd.pool.Do("HMGET", append(append([]any{}, key), u.ToInterfaceArray(fields)...)...)) } // HGetAll 获取在哈希表中指定 key 的所有字段和值 // HGetAll return 返回所有字段的值,如果值是一个对象则返回反序列化后的对象,否则返回字符串 func (rd *Redis) HGetAll(key string) map[string]any { return makeRedisResultMap(rd.pool.Do("HGETALL " + key)) } // HMSet 将哈希表 key 中的字段 field 的值设为 value func (rd *Redis) HMSet(key string, fieldAndValues ...any) bool { return rd.pool.Do("HMSET", append(append([]any{}, key), fieldAndValues...)...).Bool() } // HKeys 获取所有哈希表中的字段 func (rd *Redis) HKeys(patten string) []string { return rd.pool.Do("HKEYS " + patten).Strings() } // HLen 获取哈希表中字段的数量 // HLen return 字段数量 func (rd *Redis) HLen(key string) int { return rd.pool.Do("HLEN " + key).Int() } // HDel 删除一个或多个哈希表字段 // HDel return 成功删除的个数 func (rd *Redis) HDel(key string, fields ...string) int { return rd.pool.Do("HDEL", append(append([]any{}, key), u.ToInterfaceArray(fields)...)...).Int() } // HExists 查看哈希表 key 中,指定的字段是否存在 func (rd *Redis) HExists(key, field string) bool { return rd.pool.Do("HEXISTS "+key, field).Bool() } // HIncr 为哈希表 key 中的指定字段的整数值加上增量1 func (rd *Redis) HIncr(key, field string) int64 { return rd.pool.Do("HINCRBY "+key, field, 1).Int64() } // HDecr 为哈希表 key 中的指定字段的整数值减去增量1 func (rd *Redis) HDecr(key, field string) int64 { return rd.pool.Do("HDECRBY "+key, field, 1).Int64() } // HIncrBy 为哈希表 key 中的指定字段的整数值加上增量 increment func (rd *Redis) HIncrBy(key, field string, increment int64) int64 { return rd.pool.Do("HINCRBY "+key, field, increment).Int64() } // HDecrBy 为哈希表 key 中的指定字段的整数值减去增量 increment func (rd *Redis) HDecrBy(key, field string, increment int64) int64 { return rd.pool.Do("HDECRBY "+key, field, increment).Int64() } // LPush 将一个或多个值插入到列表头部 // LPush return 成功添加的个数 func (rd *Redis) LPush(key string, values ...string) int { return rd.pool.Do("LPUSH", append(append([]any{}, key), u.ToInterfaceArray(values)...)...).Int() } // RPush 在列表中添加一个或多个值 // RPush return 成功添加的个数 func (rd *Redis) RPush(key string, values ...string) int { return rd.pool.Do("RPUSH", append(append([]any{}, key), u.ToInterfaceArray(values)...)...).Int() } // LPop 移出并获取列表的第一个元素 func (rd *Redis) LPop(key string) any { return makeRedisResult(rd.pool.Do("LPOP " + key)) } // RPop 移除并获取列表最后一个元素 func (rd *Redis) RPop(key string) any { return makeRedisResult(rd.pool.Do("RPOP " + key)) } // LLen 获取列表长度 // LLen 列表的长度 func (rd *Redis) LLen(key string) int { return rd.pool.Do("LLEN " + key).Int() } // LRange 获取列表指定范围内的元素 // LRange return []any 列表数据,如果值是一个对象则返回反序列化后的对象,否则返回字符串 func (rd *Redis) LRange(key string, start, stop int) []any { return makeRedisResults(rd.pool.Do("LRANGE "+key, start, stop)) } // TODO 支持订阅,还需要支持 Start、Stop、向Context注册析构函数确保Stop被执行,需要支持传入Function转化为func // Subscribe //func (rd *Redis) Subscribe(channel string, onReceived func([]byte)) bool { // return rd.pool.Subscribe(channel, nil, onReceived) //} // // Unsubscribe //func (rd *Redis) Unsubscribe(channel string) bool { // return rd.pool.Unsubscribe(channel) //} // Publish 将信息发送到指定的频道 // Publish channel 渠道名称 // Publish data 数据,字符串格式 func (rd *Redis) Publish(channel, data string) bool { return rd.pool.Do("PUBLISH "+channel, data).Bool() } func makeRedisResult(r *redis.Result) any { var v any buf := r.Bytes() if json.Unmarshal(buf, &v) == nil { return v } else { return string(buf) } } func makeRedisResults(rr *redis.Result) []any { out := make([]any, 0) for _, r := range rr.Results() { out = append(out, makeRedisResult(&r)) } return out } func makeRedisResultMap(rr *redis.Result) map[string]any { out := map[string]any{} for k, r := range rr.ResultMap() { out[k] = makeRedisResult(r) } return out }