---
title: Temporal worker.ts 缺 namespace 参数 + workflow 启动后任务不被 worker 处理
date: 2026-04-30
type: bug
tags: [temporal, worker, namespace, infrastructure]
---

## 现象

worktree 接通 Temporal（namespace `approval-form-polish` 注册成功、backend 显示 `✅ Temporal client connected, namespace: approval-form-polish`、`✅ Started workflow`）后，提交表单触发 workflow，但：
1. Worker 启动 OK，"Polling for approval workflow tasks" 一直在转
2. DB 里 `approval_instances.status=RUNNING`、`workflow_id` 已写入
3. 但 `tctl namespace=approval-form-polish workflow list` 完全为空
4. `approval_tasks` 表也是空的（workflow 没推进到任务创建阶段）

切到 `default` namespace 也一样：backend log "Connected ... namespace: default"，提交后 workflow 仍不出现在 `tctl --namespace default workflow list` 里。

## 关键证据 1：Worker 缺 namespace 参数（确认 bug）

`backend/src/core/workflow/temporal/worker.ts:67-72`：

```ts
const worker = await Worker.create({
  connection,
  workflowsPath: require.resolve('@engines/approval/temporal/workflows'),
  activities,
  taskQueue,
  // ❌ 缺 namespace 参数 — 默认走 'default'
});
```

而 `temporal.service.ts` 给 Client 传了 `namespace: configService.get('temporal.namespace')`。所以：
- Client 在 `approval-form-polish` 启动 workflow
- Worker 在 `default` 轮询 task queue
- 两边永远见不到面

修复：

```ts
const namespace = configService.get<string>('temporal.namespace') || 'default';
const worker = await Worker.create({
  connection,
  namespace,                                     // ← 加这行
  workflowsPath: require.resolve('@engines/approval/temporal/workflows'),
  activities,
  taskQueue,
});
```

## 关键证据 2：默认走 default 也不通（待查）

把 `TEMPORAL_NAMESPACE=default` + 重启 backend + worker 后，workflow 仍不出现在 dingtalk Temporal 的 default namespace 里。猜测：可能 Node SDK 的 connection 解析 `localhost:3133` 时绕过了我们以为的那个 Temporal 容器（IPv6 / docker 网络命名空间问题），但 backend log 没报错。这一层未确认根因，作为后续待查项。

## 解法（短期）

跳过 Temporal-dependent E2E 测试，改成：
- 手工 SQL 造 `approval_instances` + `approval_tasks` 行，模拟 workflow 已运行到中间状态
- 直接 curl `POST /api/v1/form-management/instances/:id/withdraw` 验证 D4 fix
- 验证 DB 里 `form_instances.status=WITHDRAWN`、`approval_instances.status=WITHDRAWN`
- Temporal workflow 真终止靠日志兜底（`approvalService.withdraw` 调用 `temporalService.sendSignal('withdraw')`）

## 解法（长期，单独 PR）

1. 给 `worker.ts` 补 namespace 参数（5 行改动）
2. 调查 Node SDK 在本机 docker 网络下连 Temporal 的实际去向（可能加 `host.docker.internal` 反代，或显式 IP）
3. 给 `setup-worktree.sh` 加：检测 dingtalk Temporal 是否可用 → 自动在其上注册本 worktree namespace → 改 .env

## 关联

- `2026-04-30-worktree-temporal-not-auto-started.md`（多 worktree 共享 Temporal 思路）
- 本次 D4 撤回 E2E 卡口的真实原因（之前以为是没起 Temporal，实际是 worker.ts 配置 bug）
