Problem/Motivation
DrimageSubscriber::onKernelRequest() calls DrimageManager::image(), which extends core ImageStyleDownloadController and calls deliver(). When another request holds the lock image_style_deliver:<style>:<hash>, core throws ServiceUnavailableHttpException. The subscriber does not catch it, so it is logged as an exception and <img> tags never retry: visitors see broken images. Seen on a production site under concurrent requests on cold derivatives.
Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException: Image generation in progress. Try again shortly.
Related: #3546893 (same message, closed as works as designed, no code change), #3587334 (return handling in the subscriber), #3626466 (subscriber priority).
Steps to reproduce
- Install Drupal with Dynamic Responsive Image (Drimage) - Improved 1.0.x-dev, PHP and database as per your environment.
- Clear the image style derivatives for a Drimage-rendered image.
- Request the same cold derivative from concurrent clients, or hold the
image_style_deliver:<style>:<hash>lock from another process while requesting it. - Requests that hit the lock throw the uncaught exception above.
Proposed resolution
In DrimageSubscriber::onKernelRequest(), catch ServiceUnavailableHttpException, retry up to 5 times with usleep(500000), and if still locked answer with a plain Response (503, Retry-After: 3, Cache-Control: no-store) instead of an uncaught exception.
A Kernel test, DrimageSubscriberLockTest, covers both paths: lock held for every attempt (plain 503 with the headers) and lock released during the wait (retried to 200). Unpatched, both tests fail with ServiceUnavailableHttpException.
Also checked with real requests on a DDEV site:
- Lock held about 1.2s: 200 after about 1.6s.
- Lock held 8s: plain 503 with
Retry-After: 3andCache-Control: no-storeafter about 2s. - Missing source file: 404, unchanged. Normal request: 200, unchanged.
Remaining tasks
- ✅ File an issue
- ✅ Addition/Change/Update/Fix
- ✅ Testing to ensure no regression
- ✅ Automated unit/functional testing coverage
- ➖ Developer Documentation support
- ➖ User Guide Documentation support
- ➖ UX/UI designer responsibilities
- ➖ Accessibility and Readability
- ❌ Reviewed by a human
- ❌ Code review by maintainers
- ❌ Full testing and approval
- ❌ Credit contributors
- ❌ Review with the product owner
- ✅ Update Release Notes
- ✅ Release
User interface changes
- N/A
API changes
- N/A
Data model changes
- N/A
Release notes snippet
- N/A
Issue fork drimage_improved-3637295
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #3
josebc commentedCan we switch to using a lock like core? https://git.drupalcode.org/project/drupal/-/blob/11.x/core/modules/image...
Comment #5
rajab natshah@josebc yes, switched to a lock like core. Pushed to MR !46.
Ready for review.
Comment #6
rajab natshahRe-checked MR !46 against core's lock and stress tested it.
Follow-up for a separate issue: the web server can serve a half-written image, because core writes it in place. 1.0.14 does this too.
Comment #8
rajab natshah✅ Released in drimage_improved-1.0.15