发布 redis 扩展库
By
terrorist
at 2021-12-25 • 0人收藏 • 1536人看过
7 个回复 | 最后更新于 2022-07-02
多刷几次又打开了......
为了方便git不方便上的人看, 代码展示如下, 切记最新代码还是从github链接那里下载.
库代码如下:
import wsock.tcp.client;
namespace aaz;
class redis{
ctor(){
..table.gc(this, "close")
};
close = function(){
if(this.tcpClient){
this.tcpClient.close();
this.tcpClient = null;
}
};
connect = function(ip="127.0.0.1", port=6379, timeout=3){
this.tcpClient := ..wsock.tcp.client();
if(!this.tcpClient.connectTimeout(ip, port, timeout)){
return false, "连接服务器失败";
}
return true;
};
setTimeouts = function(send=5000,receive=5000){
if(this.tcpClient){
return this.tcpClient.setTimeouts(send, receive);
}
};
command = function(...){
var args = {...};
var ptr = ..raw.realloc(1);
// *<参数数量> CR LF
ptr = ..raw.concat(ptr, resp.arrays ++ #args ++ resp.CRLF);
// $<参数 i 的字节数量> CR LF
// <参数 i 的数据> CR LF
for(i=1;#args;1){
ptr = ..raw.concat(ptr,
resp.bulkStrings ++ #args[i] ++ resp.CRLF ++
args[i] ++ resp.CRLF
);
}
var ok, err = this.tcpClient.write(..raw.tostring(ptr));
ptr = ..raw.realloc(0, ptr);
if(!ok){
this.tcpClient.close();
return false, err;
}
return this.readReply();
};
readReply = function(){
// 无参数表示读取一行,包含尾部的 CRLF,但返回的数据不包含尾部的 CRLF 这2个字节
var line = this.tcpClient.read();
if(!line){
// 获取错误代码, 10060 超时 10054 中断*/
var errCode = ::Ws2_32.WSAGetLastError();
// 超时关闭连接
if(errCode == 10060){
this.tcpClient.close();
}
return false, errCode;
}
var prefix = ..string.charCodeAt(line);
select(prefix) {
case 43/*status + Simple Strings*/ {
return ..string.slice(line, 2);
}
case 45/*error - 当用户对不正确的数据类型执行命令, 或者执行一个不存在的命令。收到错误回复时产生一个异常。*/ {
var err = ..string.slice(line, 2)
error(err, 2)
}
case 58/*Integers : 必须能够用 64 位有符号整数表示*/ {
return tonumber(..string.slice(line, 2));
}
case 36/*bulk $ "$6\r\nfoobar\r\n" 批量字符串是用来表示一个单一的二进制安全字符串,长度可达512MB*/{
var size = tonumber(..string.slice(line, 2));
// 如果被请求的值不存在, 那么批量回复会将特殊值 -1 用作回复的长度值
// 客户端应该返回空对象,而不是空字符串
if(size<0){
return null;
}
var data = this.tcpClient.read(size)
if(!data){
var errCode = ::Ws2_32.WSAGetLastError();
if(errCode == 10060){
this.tcpClient.close();
}
return false, errCode;
}
// 读末尾的 CRLF
var dummy = this.tcpClient.read(2)
if(!dummy){
var errCode = ::Ws2_32.WSAGetLastError();
if(errCode == 10060){
this.tcpClient.close();
}
return false, errCode;
}
return data;
}
case 42/*multi bulk * 多条批量回复是由多个回复组成的数组, 数组中的每个元素都可以是任意类型的回复, 包括多条批量回复本身。*/{
var n = tonumber(..string.slice(line, 2));
/*
无内容的多条批量回复(null multi bulk reply)也是存在的,
比如当 BLPOP 命令的阻塞时间超过最大时限时,
它就返回一个无内容的多条批量回复, 这个回复的计数值为 -1
客户端库应该区别对待空白多条回复和无内容多条回复:
当 Redis 返回一个无内容多条回复时, 客户端库应该返回一个 null 对象, 而不是一个空数组。
*/
if(n<0){
return null;
}
var tab = {};
for(i=1;n;1){
var res, err = this.readReply();
if(res){
tab[i] = res;
}
elseif(res === false){
return false, err;
}
elseif(res === null){
tab[i] = null;
}
}
return tab;
}
}
};
set = function(key, value){
var ret, err = this.command("set", key, value);
return ret == "OK", err;
};
// 当 key 不存在
setnx = function(key, value){
var ret, err = this.command("SETNX", key, value);
return ret == 1, err;
};
// 指定过期时间,秒为单位
setex = function(key, value, seconds){
var ret, err = this.command("SETEX", key, tostring(seconds), value);
return ret == "OK", err;
};
// 指定过期时间,毫秒为单位
psetex = function(key, value, seconds){
var ret, err = this.command("PSETEX", key, tostring(seconds), value);
return ret == "OK", err;
};
ttl = function(key){
return this.command("TTL", key);
};
pttl = function(key){
return this.command("PTTL", key);
};
// 如果 key 中存储的值不是字符串,则会返回错误,因为 GET 仅处理字符串值
get = function(key, value){
return this.command("get", key);
};
/*
第一次设置 key 返回 field 数量
重复设置 key 返回 0
*/
hset = function(key, field, value, ...){
var ret, err;
if(..table.type(field) == "object"){
var args = {}
for(k,v in field){
..table.push(args, tostring(k), tostring(v))
}
ret, err = this.command("HSET", key, ..table.unpack(args));
}
else {
ret, err = this.command("HSET", key, field, value, ...);
}
if(ret >= 0){
return true, ret;
}
return false, err;
};
hget = function(key, field){
return this.command("HGET", key, field);
};
hgetall = function(key){
var res, err = this.command("HGETALL", key);
if(res === false){
return res, err;
}
var ret = {};
for(i=1;#res;2){
var k = res[i];
var v = res[i+1];
ret[k] = v;
}
return ret;
};
}
namespace redis{
resp = {
simpleStrings = "+";
errors = "-";
integers = ":";
bulkStrings = "$";
arrays = "*";
CRLF = '\r\n';
}
respCharCode = {
simpleStrings = 43;
errors = 45;
integers = 58;
bulkStrings = 36;
arrays = 42;
}
}
// http://doc.redisfans.com/
// https://github.com/tporadowski/redis
// https://github.com/tporadowski/redis/releases
/**intellisense()
aaz.redis() = 创建 redis 客户端\n!aaz_redis.
aaz.redis = redis 客户端
end intellisense**/
/**intellisense(!aaz_redis)
set(.(key,value) = 将字符串值 value 关联到 key
ttl(.(key) = 以秒为单位,返回给定 key 的剩余生存时间 当 key 不存在时,返回 -2 , \n当 key 存在但没有设置剩余生存时间时,返回 -1
pttl(.(key) = 以毫秒为单位,返回给定 key 的剩余生存时间 当 key 不存在时,返回 -2 , \n当 key 存在但没有设置剩余生存时间时,返回 -1
end intellisense**/demo代码如下:
import console;
import aaz.redis;
var redis = aaz.redis()
redis.connect()
console.log( redis.setex("key1", "value", "2") )
console.log(redis.get("key1"))
console.pause(true);登录后方可回帖



github又打不开了
,
大T, 你这个和扩展库里那个hiredis有啥区别?