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

3.0 KiB

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

  • Same-payload duplicate semantics are explicit and tested.
  • Conflicting payload is rejected.
  • Concurrent same-key and different-key behavior is tested on PostgreSQL.
  • Stale session version and stale per-session command sequence are rejected.
  • Wrong user, tenant, session state, or question membership is rejected.
  • Responses and restored sessions contain no answer key or explanation.
  • 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

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.