First to Site
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::$version column with #[ORM\Version]. Doctrine emits UPDATE ... WHERE version = X on every write; zero affected rows throws OptimisticLockException.
  • 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 submittedVersion field 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

  • OptimisticLockExceptionListener converts 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

FileChange
app/src/Entity/Project.php$version column + #[ORM\Version]
app/src/Controller/Admin/ProjectCrudController.phpExplicit $em->lock() in updateEntity (later removed in v3.7.1)
app/src/EventListener/OptimisticLockExceptionListener.php409 / flash response branching

Changelog Reference

  • fix: add optimistic locking to Project to prevent stale-save data loss (d82ea67)
  • fix: extend optimistic lock to EasyAdmin form flow via hidden version field (04390ce)