发布 redis 扩展库
By
terrorist
at 2021-12-25 • 0人收藏 • 1332人看过
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有啥区别?![](/static/editor/dialogs/emotion/images/pp/i_f02.png)