Files
bj_power/bj_power_mes/docs/superpowers/specs/2026-05-16-current-step-id-design.md
T

109 lines
4.2 KiB
Markdown
Raw Normal View History

# job.current_step_id 设计
## 目标
`job.currentStepIndex` (int) → `job.currentStepId` (string),以 stepId 为 job 当前步骤的运行时标识,消除 `AdvanceStep` 中 stepId↔stepIndex 的来回转换。
## 动机
`recipe_step` 已采用 stepId 为主的设计:`nextStepDefault``nextStepBranches` 存储的都是 stepId(如 "OP20"),但 `job` 表仍用 `currentStepIndex` (int)。导致 `AdvanceStep` 中存在冗余转换:
```
nextStepDefault(stepId) → 二次查表转 stepIndex → 写 currentStepIndex
resolveBranch(stepId) → GetStepIndexByStepID → 写 currentStepIndex
```
同时 stepIndex 不稳定:工序重排时 index 会变,运行中的 job 会指错步骤。stepId(OP10-OP120)是稳定的业务标识。
## 设计
### Schema
job 表 (`schema/job.go`)
- 新增 `field.String("currentStepId").MaxLen(20).Default("")`,替代 `currentStepIndex` 作为运行时步骤标识
- 旧字段 `currentStepIndex` 暂保留但不写入(默认 0),给前端平滑过渡窗口
- 新字段不需要额外索引(仅作为数据列读取,不作为查询条件)
### stepId 排序
12 个步骤加载到内存按 stepIndex 排序(数量少,开销可忽略),必要时用辅助函数提取 stepId 中的数字:
```go
func sortedStepIDs(ctx, recipeID) []string {
// SELECT stepId FROM recipe_step WHERE recipeId=? ORDER BY stepIndex
}
```
### AdvanceStep 简化
**旧流程**
```
nextStepDefault(stepId) → 二次查表转 stepIndex → 写 currentStepIndex
resolveBranch(stepId) → GetStepIndexByStepID → 写 currentStepIndex
线性推进 → currentStepIndex + 1
```
**新流程**
```
nextStepDefault → 本身就是 stepId → 直接写 currentStepId
resolveBranch → 本身就是 stepId → 直接写 currentStepId
线性推进 → 当前 stepId 的 stepIndex + 1 → 按 stepIndex 找回 stepId
```
"是否最后一步":取 currentStepId 对应的 stepIndex 与 maxStepIndex 比较。
### DBState 方法调整
需修改的方法:
- `AdvanceStep` (`dbstate.go:162`) — `SetCurrentStepIndex``SetCurrentStepId``resolveBranch` 传 stepId
- `CompleteStep` (`dbstate.go:34`) — 同上
| 旧方法 | 新方法 | 说明 |
|--------|--------|------|
| `GetRecipeStep(recipeID, stepIndex)` | 保留,Generator 遍历用 | 按 stepIndex 依次取 |
| — | `GetRecipeStepByID(recipeID, stepID)` | 核心读路径用 stepId |
| `GetNextStepIndex` | 废弃 | nextStepDefault 即 stepId |
| `resolveBranch(recipeID, stepIndex, ctxMap)` | `resolveBranch(recipeID, stepID, ctxMap)` | 分支目标即 stepId |
| `GetStepIndexByStepID` | 保留 | 排序/比较 |
| — | `GetStepIDByIndex(recipeID, stepIndex)` | 线性推进用 |
| — | `getSortedStepIDs(recipeID)` | 加载全步骤排序 |
### 对外类型
```go
type JobView struct {
CurrentStepIndex int `json:"currentStepIndex"` // deprecated
CurrentStepId string `json:"currentStepId"`
}
```
`RuntimeSnapshot` 同理加 `StepID``StepIndex` 保留。
### 消费方改动
| 位置 | 改动 |
|------|------|
| `internal/eventloop/dbstate.go` | `AdvanceStep` + `CompleteStep``SetCurrentStepIndex``SetCurrentStepId` |
| `internal/eventloop/scheduler_bridge.go` | `GetRecipeStep(stepIndex)``GetRecipeStepByID(stepId)` |
| `internal/eventloop/candidate_handlers.go` | 同上 |
| `internal/eventloop/loop.go` | `RuntimeSnapshot``StepID` 字段 |
| `internal/scheduler/generator.go` | 遍历全步骤用 stepIndex(不变),候选任务用 stepId |
| `internal/processor/job_processor.go:254` | `SetCurrentStepIndex``SetCurrentStepId`(恢复/跳步场景) |
| `internal/processor/recipe_runtime.go` | `GetNextStepIndex` 标记废弃(processor 层作为兜底) |
| `internal/types/types.go` | `JobView`/`RuntimeSnapshot`/API 响应类型加 `CurrentStepId` |
| `cmd/mockrun/main.go:110` | `SetCurrentStepIndex``SetCurrentStepId` |
| `frontend/src/api/temp-station/index.ts:9` | 类型加 `currentStepId` |
| `frontend/src/api/dock/index.ts:9` | 类型加 `currentStepId` |
### 迁移
```sql
UPDATE job SET currentStepId = rs.stepId
FROM recipe_step rs
WHERE job.recipeId = rs.recipeId AND job.currentStepIndex = rs.stepIndex;
```
迁移脚本放入 `schema/tools/`,在 `EnsureDataInitialized` 中执行。