PostgreSQL 核心开发的脉搏藏在 pgsql-hackers 邮件列表里——补丁提议、架构辩论、功能迭代,全在这一个列表上完成。但它的界面?几十年前的邮件线程格式,信息密度极高、流速极快,新人看一眼就想关掉,老手也常常被淹没在几百条回复里找不到头。
今年一月,Zsolt 和 Kai Wagner 上线了 hackorum.dev,目标很朴素:让这份邮件列表变得可读。上周,他们和 Jack Bonatakis 通了个电话——Jack 在做几乎同样的事,他的项目叫 pginbox.dev。两个独立解决同一个问题的开发者,聊出了最兴奋的一次对话,然后决定合并。
同一个问题,两条路径
pgsql-hackers 的问题不是"内容不够好",而是"内容太难找"。一个补丁从提议到合入,可能横跨数十封邮件、跨越几个月。邮件列表的原始界面没有线程聚合,没有补丁状态追踪,没有diff高亮——你只能靠人肉翻页和记忆拼凑上下文。
hackorum 和 pginbox 各自从不同角度切入:
- hackorum.dev:侧重把邮件线程重新组织成可浏览的对话结构,让补丁讨论有清晰的脉络。
- pginbox.dev:侧重补丁的状态追踪和筛选,让你知道哪个补丁在哪个阶段、哪些需要关注。
两者功能高度重叠又各有侧重,合并后能覆盖更完整的工作流——从"读讨论"到"盯补丁状态"一站式解决。
合并意味着什么
两个独立项目合并,不是简单改个域名。实际要面对的问题包括:
- 数据源统一:两个项目都从同一份邮件列表抓数据,但解析逻辑、存储格式可能不同。
- 功能取舍:哪些保留、哪些重写、哪些丢弃。
- 用户迁移:已有用户习惯的交互路径不能突然消失。
Kai 在原文里用了"energizing"形容那通电话——两个 builder 发现对方在做同样的事,不是竞争,而是"终于不用一个人扛了"。这种合并的动力来自问题本身的共识,比商业谈判更干净。
实践:自己动手解析 pg-hackers 邦件列表
在合并后的工具上线之前,如果你想自己从邮件列表提取补丁讨论,可以用 PostgreSQL 官方提供的 mbox 归档做本地解析。下面是一个最小可运行的 Python 示例,从归档中提取包含 PATCH 关键词的邮件并汇总线程标题:
#!/usr/bin/env python3
"""从 pgsql-hackers mbox 归档中提取补丁相关邮件标题和线程线索"""
import mailbox
import email.utils
import re
from collections import defaultdict
# 1. 下载归档:访问 https://www.postgresql.org/list/pgsql-hackers/
# 选择年份和月份,下载 .mbox 文件,放到本地路径
MBOX_PATH = "pgsql-hackers-2024-01.mbox" # ← 替换为你下载的实际文件路径
def extract_subject_clean(subject):
"""去掉 [PATCH] 等前缀标签,返回干净标题"""
return re.sub(r"\[.*?\]\s*", "", subject).strip()
def main():
mbox = mailbox.mbox(MBOX_PATH)
threads = defaultdict(list) # key: thread subject, value: list of (date, from, subject)
for msg in mbox:
subject = msg.get("Subject", "")
if not subject:
continue
# 只关注包含 PATCH / WIP / CF 等补丁相关关键词的邮件
if re.search(r"\b(PATCH|WIP|CF|CommitFest)\b", subject, re.IGNORECASE):
clean_subject = extract_subject_clean(subject)
date = msg.get("Date", "")
from_ = msg.get("From", "")
threads[clean_subject].append((date, from_, subject))
print(f"共找到 {len(threads)} 个补丁相关线程:\n")
for thread_subject, messages in sorted(
threads.items(), key=lambda x: -len(x[1])
):
print(f"📌 {thread_subject} ({len(messages)} 封邮件)")
for date, from_, raw_subject in messages[:3]: # 只展示前3封
print(f" {date} {from_} → {raw_subject}")
if len(messages) > 3:
print(f" ... 还有 {len(messages) - 3} 封")
print()
if __name__ == "__main__":
main()
运行前需要:
- 从 postgresql.org/list/pgsql-hackers 下载某个月的
.mbox文件。 - 将
MBOX_PATH改为你下载的文件路径。 - 安装 Python 3(标准库
mailbox无需额外依赖)。
输出示例:
共找到 42 个补丁相关线程:
📌 Add JSON_TABLE support (18 封邮件)
Mon, 15 Jan 2024 10:00:00 +0300 someone@example.com → [PATCH] Add JSON_TABLE support
Mon, 15 Jan 2024 12:30:00 +0300 reviewer@example.com → Re: [PATCH] Add JSON_TABLE support
Tue, 16 Jan 2024 09:00:00 +0300 someone@example.com → Re: [PATCH] Add JSON_TABLE support v2
... 还有 15 封
这只是最基础的提取。hackorum 和 pginbox 做的事远不止于此——它们还要处理线程嵌套、补丁版本追踪、diff 渲染、状态标注。但上面的脚本足以让你理解原始数据的结构,也说明为什么"让邮件列表可读"这件事值得专门做工具。
给关注 PostgreSQL 开发的人
如果你是 PostgreSQL 贡献者或重度关注者:
- 现在就去试 hackorum.dev 和 pginbox.dev,感受它们各自解决了什么痛点。
- 合并后保持关注:两个项目合体,功能集大概率会扩展,交互可能调整。早期用户的反馈对合并方向有实际影响。
- 如果你也在做类似工具:这故事的核心教训是——当你发现有人在解决同一个问题时,打电话聊一次,可能比各自迭代一年更高效。
对更广泛的开发者社区来说,这件事也提醒了一个常被忽略的事实:很多关键基础设施的"接口"仍然是原始的邮件列表。让这些接口变得可读、可搜索、可追踪,不是锦上添花,是降低参与门槛的必要工程。hackorum 和 pginbox 合并,是这类工程从零散走向成熟的一个信号。