Skip to content

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] —