Use case
I am building a button to generate a pdf. The generation process can take a while.
Clicking the button triggers an ajax request which can meet one of 3 scenarios:
- The pdf was already generated, and the pdf url is now cached.
- Response: Replace the "Generate PDF" button with a "Download PDF" button.
- No pdf exists yet, and no other ongoing request is currently generating it.
- First generate the pdf, then send the response.
- Response: Replace the "Generate PDF" button with a "Download PDF" button.
- No pdf exists yet, but another ongoing request is currently in the process of generating the pdf file (using a lock like for image styles).
- Wait a few seconds, then retry.
- Response: Replace the "Generate PDF" button with a "Download PDF" button.
The ajax callback looks like this:
class MyController {
[..]
public function pdfButtonCallback(..) {
[..]
$response = new AjaxResponse();
$response->addCommand(new ReplaceCommand('#generate-pdf-button', $output));
return $response;
Question
How would I implement a "wait 3 seconds and retry" ajax response?
Alternatives I considered
Wait in php
An alternative might be to wait on server side.
However, this could lead to memory issues if there are many concurrent requests.
Send Retry-After header
For image styles, an exception is thrown if the lock cannot be acquired. See ImageStyleDownloadController
.
$lock_acquired = $this->lock->acquire($lock_name);
if (!$lock_acquired) {
// Tell client to retry again in 3 seconds. Currently no browsers are
// known to support Retry-After.
throw new ServiceUnavailableHttpException(3, 'Image generation in progress. Try again shortly.');
}
If I try this, in the browser developer tools I see a response with "Retry-After" header and with html response content. But no retry occurs.
Web socket?
Maybe, but then we still have the memory problem, if a bunch of them are opened in parallel, all using a full Drupal bootstrap.
Custom js and custom json response
The last option might be to give up on Drupal ajax, and instead just make a plain json response, and custom javascript.
I will consider this if there is no other way.
new AjaxResponse()
type of response? The benefit of that would be that I can also include other "commands" like "show a message" etc. Perhaps I need to define my own command type?