feat: prepare warehouse 01 floor 1 inbound pilot

This commit is contained in:
zgw
2026-09-16 14:12:12 +08:00
parent 2632a57d73
commit 1225cf7287
25 changed files with 1465 additions and 3 deletions

View File

@@ -0,0 +1,38 @@
# FT546WMS Floor 1 Inbound Pilot Implementation Plan
**Goal:** Prepare, but do not activate, a warehouse `01` floor `1` inbound pilot with atomic mutation and automatic Legacy fallback.
**Constraints:** No field restart, process switch, SQL installation, or production business-data write. SQL Server 2016 syntax only. The independent pilot switch remains disabled in every prepared startup file.
## Task 1: Routing contract
- [x] Add failing configuration tests for the disabled default and explicit pilot properties.
- [x] Add failing service tests for out-of-scope Legacy routing, successful pilot single-writer routing, conflict fallback, and exception fallback.
- [x] Add the pilot properties, result contract, and the minimal `ToWmsServiceImpl` routing seam.
## Task 2: Floor-constrained bounded planning
- [x] Add a failing planning test proving `targetFloor=1` is forwarded to the algorithm.
- [x] Add a synchronous pilot planner that accepts only a current published warehouse `01` snapshot.
- [x] Run planning in a dedicated single-thread daemon executor with a bounded wait; timeout/cancellation remains read-only.
- [x] Reject missing, stale, changing, non-ready, or non-assigned plans and route them to Legacy.
## Task 3: Atomic production mutation
- [x] Add mapper contract tests and static SQL safety tests first.
- [x] Add `dbo.proc_allot_layer1_inbound_pilot` with one transaction, `XACT_ABORT`, update/range locks, live floor/lane/space checks, guarded row counts, and LED parity.
- [x] Add Java mutation result handling and post-exception assignment resolution so an uncertain commit never triggers a second writer.
- [x] Record best-effort `INBOUND_PILOT` evidence in existing `alg.decision_log`.
## Task 4: Operations package
- [x] Add SQL Server 2016 install, read-only check, rollback, and CMD wrappers.
- [x] Add a disabled IDEA run configuration template and a concise field runbook.
- [x] Ensure every prepared configuration sets `FORTUCKY_INBOUND_PILOT_ENABLED=false`.
## Task 5: Verification and delivery
- [x] Run focused red/green tests, all affected module tests, and offline packaging.
- [x] Inspect the JAR for the new classes/configuration and verify no secret is packaged by this change.
- [x] Request an independent code review and address critical or important findings.
- [ ] Prepare and upload versioned artifacts only; do not install, restart, switch, or activate.

View File

@@ -0,0 +1,56 @@
# FT546WMS Warehouse 01 Floor 1 Inbound Pilot Design
## Goal
Prepare a narrowly scoped inbound pilot for warehouse `01`, floor `1`, without enabling it or changing the running field system. The candidate remains Legacy-only by default. A later operator-controlled restart may enable the pilot after the database procedure has been installed and checked.
## Safety invariants
1. `FORTUCKY_INBOUND_PILOT_ENABLED` defaults to `false` and is independent of global algorithm mode.
2. Only a request with `RequestEnter.floor == "1"` and a job whose warehouse is equivalent to `01` is eligible.
3. Non-eligible requests execute the existing Legacy path unchanged.
4. Planning is read-only, uses one published shadow snapshot, is restricted to floor `1`, and has a bounded caller wait.
5. The algorithm writer and `dbo.proc_allot_space` are mutually exclusive. A committed pilot result never calls Legacy.
6. Missing, stale, changing, rejected, timed-out, or failed planning falls back to Legacy.
7. The production mutation is one SQL Server transaction. It revalidates the job, tray, warehouse, floor, snapshot generation and age, selected space, lane continuity, outbound obstruction, duplicate assignment, and live occupancy before updating anything.
8. A mutation conflict or a proven rollback falls back to Legacy. An ambiguous client failure is resolved by rereading the job; an existing assignment is returned rather than risking a second writer.
9. The mutation updates only the same business state owned by the Legacy inbound allocation path: the selected `mydo_job`, selected `bas_cargo_space`, and entry LED row for `L1004` or `L1005`.
10. Every eligible attempt writes best-effort diagnostic evidence to existing `alg.decision_log`; diagnostic failure cannot change the business result.
11. Outbound, relocation, other warehouses, and other floors remain unchanged.
## Request flow
1. Load the inbound job using the existing task number lookup.
2. If it is already allocated, return it unchanged.
3. Ask the floor-1 pilot router for an allocation.
4. When the pilot is disabled or the request is outside scope, immediately continue with the existing shadow-observation plus Legacy allocation path.
5. For an eligible request, load and validate the current published snapshot, then plan asynchronously with `targetFloor=1` and a bounded wait.
6. If planning returns one conservative eligible proposal, call the dedicated atomic mutation procedure once.
7. On procedure success or a reread that proves an assignment already exists, return the reloaded job and do not call Legacy.
8. For every other outcome, invoke the existing Legacy procedure exactly once and preserve its response.
## Atomic mutation contract
The prepared procedure is `dbo.proc_allot_layer1_inbound_pilot`. It accepts task, tray, device, selected space, warehouse, floor, snapshot generation, and maximum snapshot age. It returns a numeric result, message, and final space.
Within `SET XACT_ABORT ON` and one transaction it uses update/range locks to prove:
- exactly one unfinished inbound job matches task and tray;
- the job does not already point at another space;
- the requested published snapshot is still current and fresh;
- the selected live cargo space belongs to warehouse `01`, floor `1`, area A/C, is empty, unlocked, and has no stock;
- no active job already owns or targets that space;
- the lane has no locked or moving (`3`/`4`) space and no active outbound job;
- no physically inner free space exists, so the proposal remains the next legal slot.
The guarded updates must each affect exactly one row. Any failed guard rolls back and returns a non-success code. SQL exceptions roll back and escape to the Java resolver.
## Evidence
`alg.decision_log` uses decision type `INBOUND_PILOT`. The reason records task, tray, proposal, final space, elapsed time, outcome, and fallback reason. The snapshot generation is stored in `input_version`. Evidence is diagnostic only and never participates in the business transaction.
## Deployment boundary
This change prepares source, tests, SQL install/check/rollback files, a JAR, and a disabled IDEA configuration. Preparation does not execute the SQL installer, upload over the running JAR, restart WMS, or set the pilot switch to true.
Later activation requires this order: stop the candidate WMS during an agreed window, install and check the procedure, start the prepared JAR with shadow enabled and pilot disabled, verify Legacy operation, then perform a separate restart with the floor-1 pilot enabled. Rollback is a restart with the pilot disabled; the procedure may remain installed or be removed only after the pilot is disabled.