chore: init bj_power monorepo (dashboard/mes/wms/wms_client/workstation), clear subproject git metadata and align naming to folder names

This commit is contained in:
SunYF
2026-08-27 10:09:54 +08:00
commit 1f0ee844a4
408 changed files with 102201 additions and 0 deletions
@@ -0,0 +1,233 @@
# EventLoop: 理想模型推进计划
> 目标:EventLoop 为唯一状态读/写路径,JobRuntime 退化为复杂动作执行器。
> 进行中状态 -> 直接转 DB 调度。
## 当前架构 v12026-05-10
```
简单路径 (Scan/Mark/Load/Unload):
EventLoop → Worker dispatch → WorkerResult
→ SetJobContext/Position + NotifyStepComplete
→ JobRuntime.HandleTaskComplete → 步骤推进 → enqueueCurrentStep → notifyReady
→ SendScheduleTick → EventLoop → trySchedule
复杂路径 (Exchange/Cleaning/Washer):
EventLoop → SubmitCandidates → JobRuntime.buildXxxAction → ActionFn 闭包
→ Dispatcher.Enqueue → robotWorker → task.Execute → jr.HandleTaskComplete
DB 角色:
- job 表:status, position_type, position_ref_id, current_step_index, temp_slot_no
- equipment_slot 表:status, current_job_id
- task 表:仅 Dispatcher 路径使用
```
### v1 的问题
1. **双推进路径**`HandleTaskComplete`JobRuntime)和 `advanceJobStep`EventLoop)同时存在
2. **JobRuntime 状态缓存与 DB 不一致风险**:内存 `Context`/`PositionType`/`State` 可能滞后于 DB
3. **`jr.Start()` 是多余的入口**:调度应直接从 DB 读状态决定候选,不应依赖 JobRuntime 的 `enqueueCurrentStep`
4. **`enqueueCurrentStep → notifyReady` 仍通过 JobRuntime**:简单路径的步骤推进仍需要 JobRuntime
## 理想架构 v3
```
┌─────────────────────────────────────┐
│ EventLoop (唯一路径) │
│ │
MachineDone ──→│ handleMachineDone │
│ ├─ DB: slot OCCUPIED→DONE │
│ ├─ wake jobs │
│ └─ trySchedule │
│ │
Inspection ───→│ handleInspectionResult │
│ ├─ DB: set context │
│ ├─ advanceStep (DB only) │
│ └─ trySchedule │
│ │
WorkerResult ─→│ handleWorkerResult │
│ ├─ DB: set context/position │
│ ├─ advanceStep (DB only) │
│ └─ trySchedule │
│ │
Command ──────→│ handleXxx │
│ └─ trySchedule │
│ │
trySchedule ──→│ 刷新 DB 快照 │
│ ├─ 构建 JobView + SystemState │
│ ├─ 运行三层调度器 │
│ ├─ MachineWait → 标记 DB │
│ ├─ Decision → 更新 Context + 推进 │
│ ├─ BufferStage → 更新位置 + 推进 │
│ ├─ Scan/Mark → go dispatchWorker │
│ ├─ Load/Unload → go dispatchWorker │
│ └─ Exchange等 → SubmitCandidates │
│ └─ Dispatcher (仅复杂动作) │
│ │
Worker 结果 ──→│ handleWorkerResult │
│ └─ advanceStep (DB only) → trySchedule │
└─────────────────────────────────────┘
JobRuntime (仅用于复杂动作):
Exchange/Cleaning/Washer 的 ActionFn 闭包
不再承担: enqueueCurrentStep, notifyReady, syncStatusToDB
DB 状态完全由 EventLoop 读写
```
## 推进计划(4 个 Phase
### Phase 1: 简单路径完全脱离 JobRuntime
**目标**Scan/Mark/Load/Unload 路径不经过 `HandleTaskComplete`
而是由 EventLoop 的 `handleWorkerResult` 直接推进 DB 步骤。
**现状**
```
WorkerResult → SetJobContext/Position + NotifyStepComplete
→ jr.HandleTaskComplete → buildBranchConditions
→ GetNextStepIndex → jr.CurrentStepIdx = nextIdx
→ syncStatusToDB → enqueueCurrentStep → notifyReady → SendScheduleTick
```
**目标**
```
WorkerResult → EventLoop.advanceStep(jobID, ctxUpdates)
→ DB: 读 Context → 分支条件 → 写 CurrentStepIndex + Context
→ SendScheduleTick → trySchedule
```
**改动点**
1. `DBState` 新增 `AdvanceStep(ctx, jobID, contextUpdates)` 方法
- 读 job.context + 当前 recipe step
- 计算分支条件 → 下一步索引
- 如果是最后一步 → FinishJob
- 否则 → CompleteStep + 写 context
2. `handleWorkerResult` EventLoop 直派路径改为调用 `db.AdvanceStep`
3. 删除 `NotifyStepComplete` 调用(不再需要 JobRuntime
4. `SetJobContext` / `SetJobPosition` 改为 DB 直写
**风险**:低——不影响复杂路径,简单路径已有 Worker 直派基础。
### Phase 2: 调度入口去 JobRuntime 化
**目标**`trySchedule` 独立于 JobRuntime 运行,不依赖 `SubmitCandidates`
MachineWait/Decision/BufferStage 处理。
**现状**
```
trySchedule → 构建 views → 跑调度器 → Workers + SubmitCandidates
SubmitCandidates → jr.State = WAITING_MACHINE (MachineWait)
→ jr.HandleTaskComplete(...) (Decision/BufferStage)
```
**目标**
```
trySchedule → 构建 views → 跑调度器
→ MachineWait: DB 写 job.status = WAITING_UNLOAD
→ Decision: DB 读 context + 写 context + advanceStep
→ BufferStage: DB 写 position + advanceStep
→ Scan/Mark/Load/Unload: Worker dispatch
→ Exchange等: Dispatcher.Enqueue (不经过 SubmitCandidates 的 JobRuntime 操作)
```
**改动点**
1. `trySchedule` 中 MachineWait/Decision/BufferStage 直接调用 `DBState` 方法
2. 删除 `SubmitCandidates` 中的 MachineWait/Decision/BufferStage 直接处理逻辑
3. `SubmitCandidates` 简化为仅转换 + 入队 Dispatcher
4. 删除 `tryDirectDispatch` 方法(逻辑移到 trySchedule
5. MachineWait 不再写 JobRuntime.State,只写 DB
**风险**:中——`tryDirectDispatch` 逻辑需要搬迁到 EventLoop。
### Phase 3: 删除旧调度路径
**目标**`ScheduleAndSubmit` 完全被 `trySchedule` 替代。
**现状**
```
RestoreOrder → ScheduleAndSubmit (旧路径)
trySchedule nil entClient → ScheduleAndSubmit (测试 fallback)
```
**目标**
```
RestoreOrder → EventLoop.SendScheduleTick → trySchedule
删除 ScheduleAndSubmit 方法
```
**改动点**
1. `RestoreOrder` 末尾的 `ScheduleAndSubmit()` 改为 `jp.eventLoop.SendScheduleTick()`
2. 删除 `ScheduleAndSubmit` 方法
3. 删除 `scheduleMu` 字段(EventLoop 单线程保证序列化)
4. `trySchedule` nil entClient 路径改为直接 return
**风险**:低——仅旧的恢复路径受影响,改动量小。
### Phase 4: JobRuntime 最小化
**目标**JobRuntime 仅保留复杂动作所需的字段和方法。
**保留**
- `buildLoadAction/buildUnloadAction/buildScanAction/buildMarkingAction/buildDecisionAction/buildBufferStageAction`
- `executeExchange/executeCleaningExchange/executeWasherExchange/executeWasherBatchUnload`
- `handleMachineDone` (由 EventLoop 的 WakeJob 调用)
- `GetState` / `GetContext` (供 Dispatcher 读取)
- 所有依赖注入字段(registry, scanner, marker, robotCtrl 等)
**删除**
- `enqueueCurrentStep` 方法(不再需要)
- `HandleTaskComplete` 简化(仅复杂动作使用)
- `notifyReady` 回调 → 删除(调度由 EventLoop 直接触发)
- `syncStatusToDB` 简化为仅复杂动作使用
- `stepEnqueued` / `lastEnqueuedStep`(不再入队)
- `pendingPause` / `pendingSuspendReason` → 改为 DB 字段
- `complete()` / `cleanupOnError()` → 移到 EventLoop
**改动点**
1. 复杂动作的 ActionFn 闭包完成后,不调 `HandleTaskComplete`,而是投递 WorkerResult 到 EventLoop
2. `exchangePairer` 逻辑移到 EventLoop 管理
3. JobRuntime 变成纯粹的 "动作描述符"identity + position + context for closure capture
**风险**:高——深度改动 JobRuntime 状态机,需要大量回归测试。
## 优先级建议
| Phase | 优先级 | 影响 | 状态 |
|-------|--------|------|------|
| Phase 1 | 🔴 高 | 简单路径彻底 SSOT | ✅ 完成 (2026-05-10) |
| Phase 2 | 🟡 中 | 调度逻辑统一 | ✅ 完成 (2026-05-10) |
| Phase 3 | 🟢 低 | 清理旧代码 | ✅ 完成 (2026-05-10) |
| Phase 4 | ⚪ 部分 | 高风险的深度重构 | 仅移除 toolLocker 死代码 (2026-05-10) |
## 已完成改动
### Phase 1: DBState.AdvanceStep
- `dbstate.go` 新增 `AdvanceStep(ctx, jobID, ctxUpdates, posType, posRefID)`
- 从 DB 读 job → 计算下一步 → 如果是最后步则 FinishJob,否则 CompleteStep
- 同时更新 position、context
- `loop.go` handleWorkerResult 直派路径:`db.AdvanceStep` 替代 `NotifyStepComplete → HandleTaskComplete`
- Worker 结果不再经过 JobRuntime
### Phase 2: trySchedule 直接处理 MachineWait/Decision/BufferStage
- `trySchedule` 中新增 3 个方法,直接写 DB
- `handleMachineWaitCandidate` → DB 写 WaitingUnload
- `handleDecisionCandidate` → 读 context + 更新 + AdvanceStep
- `handleBufferStageCandidate` → 读 position + AdvanceStep
- `SubmitCandidates` 不再处理这 3 类候选
### Phase 3: 删除旧路径
- `RestoreOrder``ScheduleAndSubmit()` 改为 `SendScheduleTick()`
- 删除 `scheduleMu` 字段(EventLoop 单线程保障序列化)
- `ScheduleAndSubmit` 保留为 nil entClient fallback
## 验收标准
- [ ] `go test ./...` 全量通过
- [ ] mockrun 1 个 job 完整流程 ≤ 3 分钟完成
- [ ] EventLoop.advanceStep 是唯一的步骤推进路径
- [ ] `jp.jobs` map 的写入只发生在 StartOrder/RestoreOrder
- [ ] `syncStatusToDB` 不包含步骤推进逻辑
- [ ] 不存在 `jr.HandleTaskComplete` 被简单路径调用的情况