DEX 索引器源码解析:NewScanner 中 db 参数与数据库的交互机制

1. 引言

在 DEX 链上数据索引器的设计中,NewScanner 构造函数承担着初始化扫描器的核心职责。它接收 config.Config*sql.DB 两个参数,其中 db 参数看似简单,却在后续的断点续扫、池子状态恢复等关键流程中扮演着不可替代的角色。本文将从源码出发,逐行拆解 NewScanner 内部与 db 产生的每一次交互,剖析其设计意图与实现细节。

2. 函数签名与整体职责

func NewScanner(config config.Config, db *sql.DB) (*Scanner, error)

该函数接收两个参数:

  • config:应用配置,包含 RPC 节点地址、起始区块、合约地址等。
  • db:标准库 database/sql 的数据库连接句柄。

返回值是 *ScannererrorScanner 结构体持有区块链客户端、数据库句柄、配置、池子集合、当前扫描高度等状态。db 被直接存入 Scanner 结构体,意味着后续所有扫描逻辑都能随时访问数据库。

3. 第一次交互:加载历史池子

3.1 查询语句

rows, err := db.Query("SELECT address FROM pools")
if err != nil {
   
   
    return nil, fmt.Errorf("failed to load pools: %v", err)
}
defer rows.Close()

这是 NewScanner 中与 db 的第一次实际交互。它从 pools 表中读取所有已记录的池子地址,目的是在内存中重建池子集合。

3.2 逐行扫描

for rows.Next() {
   
   
    var addr string
    if err := rows.Scan(&addr); err != nil {
   
   
        continue
    }
    scanner.Pools[common.HexToAddress(addr)] = true
}

每一行记录被扫描为字符串形式的地址,再通过 common.HexToAddress 转换为 common.Address 类型,作为 Pools map 的键存入。Pools 的类型是 map[common.Address]bool,这里用 true 作为占位值,表示该地址已被索引。

3.3 设计意图

这一步的意义在于状态恢复。扫描器重启后,内存中的 Pools 是空的。如果不从数据库恢复,扫描器会误以为所有池子都是新建的,从而重复处理历史事件。通过加载历史池子,扫描器能够跳过已索引的池子,只关注新增池子。

4. 第二次交互:断点续扫

4.1 获取网络标识

network := getNetworkFromURL(config.RPC.Url)

在查询扫描高度之前,先从 RPC URL 中提取网络标识(如 mainnetsepolia)。这是因为同一个数据库可能服务于多个网络,需要按网络区分扫描进度。

4.2 查询扫描高度

var lastBlock sql.NullInt64
err = db.QueryRow("SELECT last_block FROM indexed_status WHERE network = $1", network).Scan(&lastBlock)

这里使用了参数化查询,$1 是 PostgreSQL 风格的占位符,network 作为参数传入。sql.NullInt64 用于处理数据库中的 NULL 值——如果该网络从未被索引过,last_block 字段可能为 NULL

4.3 分支处理

if err == nil && lastBlock.Valid {
   
   
    scanner.Current = uint64(lastBlock.Int64) + 1
    log.Printf("Resuming from indexed_status: network=%s, last_block=%d, starting from block %d", network, lastBlock.Int64, scanner.Current)
} else {
   
   
    scanner.Current = uint64(config.RPC.StartBlock)
    log.Printf
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北冥you鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值