Worker Service 后台服务模式
Worker Service 后台服务模式:Claude-Mem 的具体实现
学习目标
本章聚焦 Claude-Mem 的 Worker Service 如何作为 Bun 管理的后台 HTTP 服务运行。建议先阅读前置知识,下文直接聚焦具体落地方案。
项目实践
架构概览
worker-service.ts(约 46KB)是 Claude-Mem 的核心后台服务,基于 Express 5 构建 HTTP API:
端口分配策略
Worker Service 的默认端口基于 OS UID 计算,自动避免冲突:
port = 37700 + (uid % 100)两个不同 OS 用户在同一台机器上运行,自动获得不同端口。用户可通过 CLAUDE_MEM_WORKER_PORT 环境变量强制指定端口。
进程管理
Worker 通过 PID 文件管理进程生命周期:
| 操作 | 实现 |
|---|---|
| 启动 | 写入 PID 文件,检查端口占用 |
| 状态 | 读取 PID 文件,验证进程存在且端口匹配 |
| 停止 | 读取 PID 文件,发送 SIGTERM,清理 PID 文件 |
| 重启 | 停止 + 启动 |
| 陈旧清理 | 验证 PID 文件所有者,清理不属于当前用户的 PID |
Supervisor 模式
src/supervisor/ 实现了 Supervisor 监控:
- 心跳检测:每 30 秒检查父进程 PID,检测孤儿进程
- 进程注册表:跟踪所有子进程的状态
- 优雅关闭:接收 SIGTERM/SIGINT 后执行清理流程
- 环境净化:启动前清理环境变量,避免污染
多账户隔离
通过 CLAUDE_MEM_DATA_DIR 环境变量支持多账户:
export CLAUDE_MEM_DATA_DIR="$HOME/.claude-mem-work"所有路径(数据库、Chroma、日志、配置、PID 文件)都基于该目录派生:
$CLAUDE_MEM_DATA_DIR/├── claude-mem.db # SQLite 数据库├── chroma/ # Chroma 向量数据├── logs/ # Worker 日志├── settings.json # 配置文件└── worker.pid # PID 文件依赖自动安装
Worker Service 在启动时检查依赖:
- Bun:JS 运行时,缺失时通过 curl 安装脚本自动安装
- uv:Python 包管理器(用于 Chroma),缺失时自动安装
HTTP API 路由分类
| 路由前缀 | 功能 |
|---|---|
/api/search | 记忆搜索(FTS5 + 格式化) |
/api/timeline | 时间线上下文 |
/api/observations/batch | 批量获取观察详情 |
/api/corpus | 知识语料库 CRUD |
/api/health | 健康检查 |
/v1/* | Server-Beta REST API |
/sse | Server-Sent Events |
/auth/* | BetterAuth 认证 |
问题与规避
端口冲突
问题:两个 Worker 实例尝试绑定同一端口。
规避:启动时通过 isPortInUse() 检查端口,已占用时返回 'dead' 状态,调用方据此报告错误。UID 基础端口计算降低了同一机器上冲突的概率。
Windows 终端标签页累积
问题:Hook 非零退出码可能导致 Windows Terminal 为每次失败打开新标签页。
规避:Worker/Hook 默认 Exit 0(即使有 ERROR 级别日志),通过 stderr 输出错误信息但不触发终端行为。包装层/插件负责重启逻辑。
设计取舍
为什么用 Express 而非 Bun 原生 HTTP?
- 优势:Express 5 提供了成熟的中间件生态、路由参数解析、错误处理
- 代价:额外的依赖
- 权衡:BetterAuth(认证框架)也依赖 Express 生态,选择 Express 可以复用中间件