Files
ruoyi-vue-pro/docs/education/migration/issues/EDU-008-idempotent-answer-save.md

54 lines
3.0 KiB
Markdown

# EDU-008 — Verify idempotent answer saving
- **Status:** done — answer idempotency and rollback contract verified on PostgreSQL
- **Type:** implementation/verification
- **Phase:** 2
- **Blockers:** EDU-007
## Implementation result
The existing unified PostgreSQL idempotency claim remains the final guard. Matching keys replay only a complete, valid stored response; null, blank, malformed, or structurally incomplete replay data now fails closed without re-executing the answer mutation. Completion of a newly claimed response must update exactly one idempotency row before session/question state changes.
Answer saving remains limited to Option-backed Questions. Optionless/free-text behavior is explicitly rejected until a separate subjective-answer contract is designed. The answer HTTP seam now uses the EDU-007 Member principal and TenantContextHolder boundary and rejects ADMIN principals.
PostgreSQL tests prove same-key/same-payload replay, same-key/different-payload conflict including concurrent requests, different-key CAS serialization, stale version/sequence rejection, user/tenant/state/question ownership checks, full rollback of answer/session/claim state, refresh recovery, and no answer-key/explanation leakage. No migration was added or executed by EDU-008.
## Scope
- Same key and same canonical payload replays the original result.
- Same key and different payload returns a conflict.
- Database uniqueness is the final idempotency guard.
- Session version and client sequence prevent stale updates.
- Selected options are validated against the safe snapshot contract.
- Optionless answer behavior remains blocked until explicitly designed; do not pretend it is option-backed.
## Acceptance criteria
- [x] Same-payload duplicate semantics are explicit and tested.
- [x] Conflicting payload is rejected.
- [x] Concurrent same-key and different-key behavior is tested on PostgreSQL.
- [x] Stale session version and stale per-session command sequence are rejected.
- [x] Wrong user, tenant, session state, or question membership is rejected.
- [x] Responses and restored sessions contain no answer key or explanation.
- [x] Failure does not partially update answer, sequence, session version, or the idempotency claim.
## Verification
Focused answer service/controller/Mapper tests, PostgreSQL concurrency tests, EDU-001 regressions, and required diff/compile gates.
## Verification performed
```text
PracticeAnswerControllerHttpTest: 16 passed
PracticeAnswerServiceImplTest: 37 passed on PostgreSQL/V4030
Total focused: 53 passed
Failures/errors/skipped: 0
```
The service suite includes concurrent same-key identical and conflicting payloads plus exact different-key winner/loser assertions. Incomplete replay rows fail closed, and rollback assertions cover session version, session sequence, question state, and claim removal.
## Risk and rollback
- **Risk:** Medium-to-high concurrency and offline-retry risk.
- **Rollback:** Application rollback with schema retained; forward migration for any constraint correction.