Release 3.6
Optimistic Locking on Project
Doctrine-level version protection to prevent stale-write races on project saves
Overview
When two users edit the same project concurrently, the second save used to silently overwrite the first. This release adds optimistic locking at the entity level and a form-round-tripped version check to catch those races and surface them as a user-facing message.
The explicit $em->lock() check on the EasyAdmin form flow was tightened too aggressively and was rolled back in v3.7.1 after it started producing false positives on ~7-9 of every 10 saves (caused by background workers bumping the version mid-edit). Read the release 3.7 entry for the current state.
What Changed
Entity Version Column
Project::$versioncolumn with#[ORM\Version]. Doctrine emitsUPDATE ... WHERE version = Xon every write; zero affected rows throwsOptimisticLockException.- This catches the narrow "two requests in flight" race automatically at the DB layer.
EasyAdmin Form Flow (tightened, then softened in v3.7.1)
- Hidden
submittedVersionfield on every project form render, initialised with the project's current version. ProjectCrudController::updateEntity()called$em->lock($project, OPTIMISTIC, $submittedVersion)before applying form changes to catch the "long-held form" race too.
Exception Listener
OptimisticLockExceptionListenerconverts the exception into:- HTML request - flash message + redirect back to the listing.
- API / XHR /
Accept: application/json- HTTP 409 Conflict with JSON body.
Files Touched
| File | Change |
|---|---|
app/src/Entity/Project.php | $version column + #[ORM\Version] |
app/src/Controller/Admin/ProjectCrudController.php | Explicit $em->lock() in updateEntity (later removed in v3.7.1) |
app/src/EventListener/OptimisticLockExceptionListener.php | 409 / flash response branching |