---
title: 多 worktree 共享一个 Temporal Server，按 namespace 隔离 —— 不要每个 worktree 起一套
date: 2026-04-30
type: workflow
tags: [worktree, temporal, dev-server, multi-tenancy]
---

## 背景

新建 worktree（slot 40，`approval-form-polish`）后跑 `npm run start:dev`，后端日志报：
> ❌ Failed to connect to Temporal: Failed to connect before the deadline
> ⚠️ Temporal is not available. Workflow features will be DISABLED.

第一直觉是"给本 worktree 起独立 Temporal"，但这是错的。

## 正解

Temporal Server **天然多租户**——一个 server 可以承载无数 namespace，workflow ID 在 namespace 内唯一，跨 namespace 互不影响。多个 worktree 共享一个 Temporal server、各自用独立 namespace 是 Temporal 的标准用法。

### 现状盘点
- 团队里已经有 `ffoa-wt-dingtalk-temporal` 容器在跑（host port 3133→7233）
- 每个 worktree 的 setup-worktree.sh 给自己分配了 `TEMPORAL_GRPC_PORT`（slot 40 → 4033），但**根本没起 Temporal 容器**，只是写了 .env 占位
- 结果：所有非 dingtalk 的 worktree 后端启动时连 4033（不存在）失败

### 修复（worktree 本地，3 步）

```bash
# 1. 在已有 Temporal 上注册本 worktree 的 namespace
docker exec ffoa-wt-dingtalk-temporal tctl --address temporal:7233 \
    --namespace <worktree-name> namespace register --retention 7

# 2. 改 backend/.env 指过去
TEMPORAL_ADDRESS=localhost:3133              # 已运行的 Temporal host port
TEMPORAL_NAMESPACE=<worktree-name>           # 独立 namespace 避免 ID 撞

# 3. 重启 backend
```

### tctl 容器内调用的坑

容器内 `tctl` 默认 `--address 127.0.0.1:7233`，但 temporal 进程绑定的是容器 hostname `temporal:7233`（docker-compose 内部网络名），所以必须 `--address temporal:7233` 才连得通。

```bash
# ❌ 不通
docker exec ffoa-wt-dingtalk-temporal tctl namespace list
# Error: dial tcp 127.0.0.1:7233: connect: connection refused

# ✅ 通
docker exec ffoa-wt-dingtalk-temporal tctl --address temporal:7233 namespace list
```

## 长期改进（建议单独 PR）

1. `scripts/dev/setup-worktree.sh` 在最后追加一段：
   - 检测是否有 `*-temporal` 容器在跑
   - 自动 `tctl --address temporal:7233 namespace register --retention 7 <worktree-name>`
   - 把 `.env` 的 `TEMPORAL_ADDRESS` 改成已运行 Temporal 的 host port、`TEMPORAL_NAMESPACE` 设成 worktree 名
2. `.env.example` 注释里说明"Temporal 多 worktree 共享，namespace 隔离"

## 跟自己起一套 Temporal 的对比

| 方案 | 工作量 | 资源 | 可观测性 | 隔离强度 |
|------|-------|------|---------|---------|
| **共享 + namespace（当前）** | 3 行命令 | 0 增 | Temporal UI 同一个面板看所有 worktree | 逻辑隔离够用 |
| 每 worktree 起一套 | 改 compose 让 temporal 复用外部 PG（depends_on 解耦），改 setup-worktree 起容器 + 端口冲突排查 | 每 worktree 多 2 个容器 | 每 worktree 一个 UI 端口 | 物理隔离 |

dev 场景下**第一种完胜**。物理隔离是 staging/prod 的需求，dev 不必。

## 适用范围

任何用到 Temporal 的 worktree 开发任务（审批、表单、长流程业务）。

## 关联

- ERR-20260429-002（slot 探测漏过非标准命名容器）
- `2026-04-29-setup-worktree-manual-tails.md`（脚本中途失败要补完所有阶段）
- 本次 D4 撤回流程 E2E 卡口已解除
