跳转至

db.redis

since: std-0.5 stability: experimental

Redis RESP2 客户端核(P5-E;回放优先架构,镜像 pg.ct) ═══ 架构口径(镜像 pg.ct 双薄源共驱一核)═══ ① redis_recv_script(回放源):List[Str] 十六进制回包逐条出(一行一条 完整回包;tests/db/redis_replay/.script + README)——CI 零真库; ② redis_recv_fd(真源):fd 直读(db 自有垫片 db/c_src/ ctron_dbredis.c,ctron_dbpg.c 同构镜像;真 fd 冒烟 Task 6 nightly; interp 无 extern 运行时 ⇒ fd 源面 emit 专臂,x_ 前缀)。 核解析器 redisx_(字节表 + 游标)双源共享;统一产出 RedisReply。 ═══ 依赖纪律 ═══ 零 std use 纯叶(与 pg.ct/db.ct 同口径;严格互斥树——db 不 use std.net)。十六进制面自持(redis_hex_,pg.ct 自持 b64 同款先例:仅 为夹具 I/O 复制 30 行工具面,不为此拉 std/enc 载荷面)。extern 符号 前缀 ctron_dbredis_(与 ctron_dbpg_ 分置:同名 extern decl 二次 合并即 E5030,P5-D 探针实证)。 ═══ RESP2 面(本任务)═══ 命令编码 = RESP 数组(逐参 bulk string):N\r\n $len\r\n arg\r\n …; GET/SET/DEL/EXPIRE/INCR 五命令装配面(redis_cmd + 五具名包装)。 回包五形: '+' 简单字符串(sval)/ '-' 错误(rc -1 err 4,sval = 原文)/ ':' 整数(ival)/ '$' 批量字符串(sval + bval 精确字节面;$-1 = NULL → isnull 1)/ '' 数组(一屢单展开:items/inulls 平铺;-1 = NULL 数组 → isnull;嵌套数组 = 协议违例 err 2,v0 登记口径——基本面 五命令不产嵌套)。 ═══ 发射面/解释面纪律(divergences (f)-(i);全镜像 pg.ct)═══ ① (h) 载荷通道:RedisReply struct 标量字段 + rs_ 自由 getter。 ② (i) C10:长度/计数算术一律宽域播种(redisz)后运算;bulk 长域 乘前预门:累计超 bulk_max(= RESP2 协议上限 512MiB = 536870912, 已过 2^28 险带,故先门后乘,全程 I64 宽域,不落 32 位乘)即拒。 struct 字段只用 List[Str]/List[I32](List[I64] 字段发射面坏, P5-C 登记)。 ③ utf8_enc 解释口径坏(pg.ct 头注③同款):文本解码走可打印 ASCII 表切片(32..122,'{' 档 fail-closed);任意字节精确面 = bval (List[I32])/redis_hex_encode;非 ASCII 文本解码待解释器修复后 收敛(登记口径)。 ④ 无方法调用/无闭包/无 Tuple;状态随值携带;List 经形参 push 跨 函数传播;"fn 内未用结果绑定"毒化——忽略返回值用裸语句形。 ⑤ inline test 不落本文件(C17 宿主敏感);声明冒烟 + 行为面全在 tests/db/redis_replay。 ═══ 不完整流判别(P5-F 修订;fd 半包 ≠ 协议违例)═══ fd 真源 TCP 分片与违例必须分形——incomplete 面 = rc 0 / err 0 / used 0 / kind 0(redisx_incomplete),三途: ① 头行无 CRLF(首字节已到,行未完); ② bulk 数据未到齐(头行完整、声明长 sane ≤ bulk_max、数据越界); ③ 数组元素未到齐(计数完整但 cur == b.len,或元素 bulk 同②)。 redis_recv_fd 见 incomplete 续读(垫片 would-block -2 面 → 面返调 用方,rbuf/fill 持态续等);语法坏/声明长越域/嵌套数组仍 err 2*。 脚本源一行一整回包,incomplete 面 = 回包截断,经 redis_recv_script 映射 err 2(rr_replay 截断钉语义不变)。 ═══ err 码(RedisReply.err)═══ 1 帧面坏(非十六进制/空行) 2 协议违例(形式坏/长度域越界/截断/ 嵌套数组) 3 源耗尽(脚本走完/fd 对端关) 4 错误回包('-' 形收到, sval = 错误原文) 6 IO(fd 读写败;fd 源专面) rc 约定:0 成功 / -1 失败(net 门面同款;'-' 回包 rc -1 err 4)。 ═══ 连接状态面(pool.ct 消费)═══ redis_conn_dirty(err):0 = clean / 1 = dirty。v1 命令面(GET/SET/ DEL/EXPIRE/INCR)无会话态(无事务/无客户端命名态)⇒ 无复位面: 回包完成即干净;err != 0(协议/IO/源耗尽)流信任失 ⇒ 弃用不复用 (池侧 = 丢弃,不回池)。登记:pub/sub(P8)/MULTI 会话态落地时 本分类随动。

pub struct

struct RdsCell64

fd 出参标量胞(与 pg.ct PgCell64 同布局异名——同名 decl 合并 E5030
纪律;出参持态一律 Box[RdsCell64] 堆胞,跨调用可见)

Field Type
var v I64

struct RedisReply

Field Type
var rc I64
var err I64
var kind I32
var ival I64
var sval Str
var isnull I64
var nitems I64
var items List[Str]
var inulls List[I32]
var bval List[I32]
var used I64
var next I64

pub fn

Signature Returns Description
redis_bulk_max() I64 RESP 批量字符串协议上限(512MiB;C10 乘前界门基准)
redis_err_frame() I64 —
redis_err_proto() I64 —
redis_err_eof() I64 —
redis_err_reply() I64 —
redis_err_io() I64 —
redis_hex_decode(s: Str) List[I32] 十六进制串 → 字节表(0..255);奇长/非法数位/空串 → 空表(fail-closed)
redis_hex_encode(b: List[I32]) Str 字节表 → 小写十六进制串(空表 → "")
rs_rc(r: RedisReply) I64 —
rs_err(r: RedisReply) I64 —
rs_kind(r: RedisReply) I32 形字节:'+' 43 / '-' 45 / ':' 58 / '$' 36 / '*' 42(畸形 0)
rs_ival(r: RedisReply) I64 ':' 整数值;'*' 数组元素计数
rs_sval(r: RedisReply) Str '+' 简单串 / '-' 错误原文 / '$' 批量文本(ASCII 面;非打印 → "")
rs_isnull(r: RedisReply) I64 1 = NULL($-1 / *-1)
rs_nitems(r: RedisReply) I64 —
rs_item(r: RedisReply, i: I64) Str 数组一层数元(ASCII 面;OOB → "")
rs_inull(r: RedisReply, i: I64) I64 数组逐元 NULL 位(1 = $-1;OOB → -1)
rs_bval(r: RedisReply) List[I32] '$' 批量精确字节面(任意字节双臂可断言)
rs_used(r: RedisReply) I64 本回包消耗字节数(fd 源消费位;脚本源恒全行)
rs_next(r: RedisReply) I64 脚本源游标推进位(下一回包行下标)
redis_recv_script(lines: List[Str], cur: I64) RedisReply ① 回放源:十六进制回包逐条出(一行一整回包;cur 越界 → eof)
redis_recv_fd(fd: I64, rbuf: &[I64], fill: Box[RdsCell64], scr: &[I64]) RedisReply ② 真源:fd 直读(阻塞 fd = 循环至整包;非阻塞 fd = 边沿驱动,真 fd
冒烟 Task 6 nightly;x_ 夹具 emit 臂专面)。rbuf = 持续读缓冲 lane
(调用方持有;lane .len = 字面量显式槽数,P5-C 登记),fill = 缓冲
填充位(Box[RdsCell64] 堆胞,跨调用持态),scr = 单读暂存 lane(垫片
CT_CHUNK=4096 口径)。incomplete 面(判别见头注 P5-F 修订)→ 续读;
垫片 would-block(-2,非阻塞 fd)→ incomplete 面返调用方(rbuf/fill
持态,续等后重入);违例 → err 2;读败 → err 6;对端关 → err 3;
守卫计数防滞留。成功后 lane 前移消费 used 字节。
redis_send_cmd_fd(fd: I64, msg: List[I32], scr: &[I64]) I64 命令发送(fd 源;List[I32] → lane 暂存后整发;0 成 / -1 败)。垫片
write 为 send-all 整长 chunk 循环(ctron_dbpg.c 同口径,无静默截断)。
redis_fd_close(fd: I64) I64 —
redis_fd_last_errno() I64 —
redis_cmd(parts: List[Str]) List[I32] 通用命令装配:*N\r\n + 逐参 $len\r\n arg\r\n(参数计数 i16 域门先于
计数装配,(i) 族同门;空参表 = 空表 fail-closed——RESP 命令至少 1 参)
redis_get_cmd(key: Str) List[I32] GET key → *2\r\n$3\r\nGET\r\n$len\r\nkey\r\n
redis_set_cmd(key: Str, val: Str) List[I32] SET key val → *3
redis_del_cmd(key: Str) List[I32] DEL key → *2(多 key 删除面 v0 不展开,登记)
redis_expire_cmd(key: Str, secs: I64) List[I32] EXPIRE key seconds → *3(secs 十进制文本格)
redis_incr_cmd(key: Str) List[I32] INCR key → *2(回包恒整数形)
redis_conn_dirty(err: I64) I64 0 = clean(回包完成即干净,无会话态)/ 1 = dirty(协议/IO/源耗尽,
流信任失,弃用不复位不回池)