db.pool
since: std-0.5 stability: experimental
有界连接池(P5-E;回放优先架构;§12.3 池纪律) ═══ 规范面(Global Constraints 池纪律 + §12.3)═══ 池有界:容量必填(构造参数;cap < 1 → ok 0 fail-closed,零操作); 等待经有界 Channel表达背压;回池前复位(必须)——禁止跨取消/跨 错误复用脏连接;池绝不发放脏连接。 ═══ 架构口径(发射面现实裁定;探针实证见 divergences P5-E)═══ 核(本文件)= 纯 Ctron 无并发原语:池状态随值携带(PoolState struct 值语义,单属主),acquire = pool_take(空池 → ok 0 miss 面, 不阻塞),release = pool_release_(回池复位)。Channel 等待面 = 组合层标准接线(见下"等待接线"),在 tests/db/pool/pool_wait.ct 双臂 验收——Channel 半端(Sender/Receiver)不可作 struct 字段/形参* (emit 臂 int32 截断,P5-E 探针实证并登记),故池对象不持通道,通道 由属主任务局部持有:
等待接线(v1 标准形;pool_wait.ct 逐钉): let (idle_tx, idle_rx) = Channel[I64](cap) // 空闲槽通道,容量=池容量 获取:pool_take miss(ok 0)→ idle_rx.recv() 阻塞等待(背压显式) 归还:借出任务复位后 idle_tx.send(slot)(池满即阻塞 = 反向背压) 公平性:Channel FIFO + pool_take idle FIFO,先等先得 取消:recv/send 随作用域取消以 Err 返回(§7.2/06e_cancel 同面), 取消路径禁复用脏连接 = 分类面 pool_classify 恒不产 clean。
多任务共享 PoolState 经 Mutex[PoolState](Mutex[T] 恒 Send,T 任意) 为 v0 登记面:值语义 + with_mut 写回在 spawn 闭包内的发射面未证, v1 池属主单任务 + 通道接线为规范形。 ═══ 回池复位三件套(§12.3;P5-D 复位路径接线)═══ ① 活动事务回滚:Z('T') 陷阱(P5-D 评审裁定)——查询以 err 0 收口 但 ReadyForQuery 状态字节 'T' = 连接在事务中,池必须分类为需复位, 经 ROLLBACK 回放路径复位见 'I' 方可回池(pool_release_pg); E 收口(err 5,drain 档)先排空尾随 Z:排空读回已是 'I'(非事务内 普通查询错误,服务端 ErrorResponse 后已自回 idle)即保留回池—— 复位并未失败,健康连接不因单次查询错误而弃(P5 终审 I-1 keep 分支, p_drain_idle 钉);仍 'T'/'E' 再 ROLLBACK(Task 4 同路径:s_tx.ct 排空→回滚→'I')。 ② 会话变量复位:pg.ct v1 无 SET 面党 ⇒ 不建模(登记)。 ③ 预编译语句清理:命名语句生命周期归池策略 = pg_close_msg 归池消费 (pg.ct 预留;v1 池不持语句清单,登记 Task 6 nightly 随动)。 复位失败(源耗尽/协议坏/状态非 'I'/越界栅)→ 连接弃用:永不回池、 永不发放(ndrop 计数;真源 fd 关闭由属主组合层执行——池值语义不持 fd 生命周期,登记)。 ═══ 分类面(pool_classify;pool.ct 与接线层共驱一核)═══ 0 = 直接回池(err 0 且状态 'I' 且非事务)/ 1 = 复位回池(Z('T') 陷阱 或 drain 档)/ 2 = 弃用(dirty:pg_conn_dirty == 1,流信任失)。 Redis 侧:redis_conn_dirty(P5-E)——v1 命令面无会话态 ⇒ err 0 即 clean 直回池,否则弃用(pool_release_redis)。 ═══ 发射面纪律(divergences (f)-(i);全镜像 pg.ct/redis.ct)═══ ① (h) 载荷通道:PoolAcq/PoolState struct 标量字段 + pa_/pool_ 自由 getter。 ② (i) C10:计数/下标算术宽域播种(poolz);struct 字段只用 List[Str]/List[I32](List[I64] 字段发射面坏,P5-C 登记);槽位 表全 I32(容量/槽 id 值域小;fd 值域 ≤ 1024 亦 I32 槽)。 ③ List 经形参 push 跨函数传播已证形;struct 字段列表重建后整体 换新(值语义:局部新表 + 逐槽搬运,不在共享表上原地写)。 ④ 无方法调用/无闭包/无 Tuple;状态随值携带;"fn 内未用结果绑定" 毒化——忽略返回值用裸语句形。 ⑤ inline test 不落本文件(C17 宿主敏感);行为面在 tests/db/pool。 ═══ use 纪律(严格互斥树;单路径导入)═══ 单子扩展 db.pg(复位经 pg_query_script ROLLBACK 回放路径 + pg_conn_dirty 分类;db 树内互用 = client.ct→net.bind 同款 先例)。消费方二选一:use db.pool 或 use db.pg——加载器 为单路径导入树(pool→pg 边已占 pg;消费方再直 use pg 即 E5020 环, 探针实证),故借出面经 pool_borrow_pg(PoolQry struct 通道)穿透, 消费方面不触 pg 符号。不 use std.net/std.redis(redis 侧分类自持 标量面,不拉整个 redis.ct——池分类只依赖 err 标量)。
pub struct
struct PoolState
| Field | Type |
|---|---|
var ok |
I64 |
var cap |
I64 |
var kinds |
List[I32] |
var inuse |
List[I32] |
var cls |
List[I32] |
var status |
List[I32] |
var fds |
List[I32] |
var fstarts |
List[I32] |
var fends |
List[I32] |
var curs |
List[I32] |
var frames |
List[Str] |
var idle |
List[I32] |
var nadd |
I64 |
var ntake |
I64 |
var nrel |
I64 |
var nreset |
I64 |
var ndrop |
I64 |
struct PoolAcq
| Field | Type |
|---|---|
var ok |
I64 |
var slot |
I64 |
var kind |
I64 |
var fd |
I64 |
var cur |
I64 |
var fstart |
I64 |
var fend |
I64 |
var st |
PoolState |
struct PoolQry
借出连接上执行查询(回放源 = 池帧库;cur = 起跑游标,多查询会话由
调用方以 pq_next 线程化推进)。结果经 PoolQry
struct 通道((h) 裁定);栅内执行:cur 出槽位帧区间 [fstart, fend)
= 协议违例 err 2,防串池(复位路径同栅)。
| Field | Type |
|---|---|
var rc |
I64 |
var err |
I64 |
var status |
I64 |
var next |
I64 |
struct PgRecv
| Field | Type |
|---|---|
var rc |
I64 |
var err |
I64 |
var next |
I64 |
var mtype |
I32 |
var body |
List[I32] |
struct PgErrData
| Field | Type |
|---|---|
var ok |
I64 |
var sev |
Str |
var code |
Str |
var msg |
Str |
struct PgRows
| Field | Type |
|---|---|
var rc |
I64 |
var err |
I64 |
var nrows |
I64 |
var ncols |
I64 |
var tag |
Str |
var cols |
List[Str] |
var oids |
List[I32] |
var cells |
List[Str] |
var nulls |
List[I32] |
var cbytes |
List[I32] |
var coffs |
List[I32] |
var esev |
Str |
var ecode |
Str |
var emsg |
Str |
var next |
I64 |
var status |
I64 |
pub fn
| Signature | Returns | Description |
|---|---|---|
pool_ok(s: PoolState) |
I64 |
— |
pool_cap(s: PoolState) |
I64 |
— |
pool_nslots(s: PoolState) |
I64 |
— |
pool_nidle(s: PoolState) |
I64 |
— |
pool_nadd(s: PoolState) |
I64 |
— |
pool_ntake(s: PoolState) |
I64 |
— |
pool_nrel(s: PoolState) |
I64 |
— |
pool_nreset(s: PoolState) |
I64 |
— |
pool_ndrop(s: PoolState) |
I64 |
— |
pool_slot_kind(s: PoolState, slot: I64) |
I64 |
槽位面(OOB → -1;kind 0 pg / 1 redis;cls 0 clean / 1 dirty / 2 drain; status = 最近 ReadyForQuery 字节或 0) |
pool_slot_inuse(s: PoolState, slot: I64) |
I64 |
— |
pool_slot_cls(s: PoolState, slot: I64) |
I64 |
— |
pool_slot_status(s: PoolState, slot: I64) |
I64 |
— |
pool_slot_cur(s: PoolState, slot: I64) |
I64 |
— |
pool_slot_fd(s: PoolState, slot: I64) |
I64 |
— |
pool_open(cap: I64) |
PoolState |
池构造(容量必填;cap < 1 → ok 0 fail-closed:后续零操作) |
pool_add_pg(s: PoolState, frames: List[Str], fd: I64) |
PoolState |
PG 连接入池(frames = 该连接的回放脚本帧;fd = 真源 fd,回放面 -1)。 池满(槽数达 cap)或池坏 → 原样返回(fail-closed)。 |
pool_add_redis(s: PoolState, fd: I64) |
PoolState |
Redis 连接入池(v1 无会话态 ⇒ 无回放帧;kind 1;fd 同上) |
pa_ok(a: PoolAcq) |
I64 |
— |
pa_slot(a: PoolAcq) |
I64 |
— |
pa_kind(a: PoolAcq) |
I64 |
— |
pa_fd(a: PoolAcq) |
I64 |
— |
pa_cur(a: PoolAcq) |
I64 |
— |
pa_fstart(a: PoolAcq) |
I64 |
— |
pa_fend(a: PoolAcq) |
I64 |
— |
pa_st(a: PoolAcq) |
PoolState |
— |
pool_take(s: PoolState) |
PoolAcq |
获取:idle FIFO 队首(先入先出);空池 → ok 0(miss;等待接线 = 调用方 于空闲槽通道 recv 阻塞,背压显式——见头注)。池绝不发放脏连接:入 idle 者仅 add(clean)与复位成功面。取后态经 pa_st 线程化(值语义: st 不变式 — 调用方须以 pa_st(a) 为后续 release/take 的基态)。 |
pool_classify(err: I64, status: I64) |
I64 |
---- 分类面(接线层/池共驱一核;头注分类面)---- 返回 0 直接回池 / 1 复位回池 / 2 弃用。 |
pq_rc(q: PoolQry) |
I64 |
— |
pq_err(q: PoolQry) |
I64 |
— |
pq_status(q: PoolQry) |
I64 |
ReadyForQuery 状态字节('I'=73/'T'=84/'E'=69;未见 Z = 0) |
pq_next(q: PoolQry) |
I64 |
会话游标(下一查询续跑位;借出面见 pg.ct pgr_next 语义) |
pool_borrow_pg(s: PoolState, slot: I64, cur: I64, sql: Str) |
PoolQry |
— |
pool_release_pg(s: PoolState, slot: I64, err: I64, status: I64, next: I64) |
PoolState |
PG 连接回池。err = 最近操作 err 面(PoolQry pq_err),status = 最近 ReadyForQuery 状态字节(pq_status;未见 Z = 0),next = 最近操作后的 会话游标(pq_next;线上位置随查询推进)。复位 = ROLLBACK 回放 (drain 档先排空尾随 Z;Z('T') 陷阱直滚);成功 = rc 0 且状态 'I' 且 栅内(next ≤ fend);否则弃用。脏(cls 2)直弃——不复位不回池。 |
pool_release_redis(s: PoolState, slot: I64, err: I64) |
PoolState |
Redis 连接回池(v1 无会话态:err 0 即 clean 直回池;否则弃用)。 |
pg_frame_max() |
I64 |
— |
pg_err_frame() |
I64 |
— |
pg_err_proto() |
I64 |
— |
pg_err_eof() |
I64 |
— |
pg_err_response() |
I64 |
— |
pg_hex_decode(s: Str) |
List[I32] |
— |
pg_recv_frame_script(frames: List[Str], cur: I64) |
PgRecv |
— |
pg_conn_dirty(err: I64) |
I64 |
— |
pg_ready_status(body: List[I32]) |
I64 |
— |
pg_tag(body: List[I32]) |
Str |
— |
pg_err_data(body: List[I32]) |
PgErrData |
— |
pgr_rc(r: PgRows) |
I64 |
— |
pgr_err(r: PgRows) |
I64 |
— |
pgr_next(r: PgRows) |
I64 |
— |
pgr_status(r: PgRows) |
I64 |
— |
pg_query_script(frames: List[Str], cur: I64, sql: Str) |
PgRows |
— |
sha256_hex(msg: Str) |
Str |
— |
sha1_hex(msg: Str) |
Str |
— |
sha256_bytes(msg: List[I32]) |
List[I32] |
— |
hmac_sha256(key: List[I32], msg: List[I32]) |
List[I32] |
— |
bytes_to_hex(b: List[I32]) |
Str |
— |
bytes_from_hex(s: Str) |
List[I32] |
— |