0

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.

5
  • 1
    Is this essentially a polling implementation? stackoverflow.com/questions/6835835/… (jQuery) levelup.gitconnected.com/polling-in-javascript-ab2d6378705a (JavaScript)
    – cilefen
    Jul 7, 2022 at 2:49
  • 1
    You can run custom javascript from an Ajax command and you can trigger Drupal Ajax requests in javascript. so you don't need to give up on Drupal Ajax to implement some custom javascript.
    – 4uk4
    Jul 7, 2022 at 6:36
  • @cilefen True, polling would be the correct term to describe the technique I plan to use here :)
    – donquixote
    Jul 7, 2022 at 11:56
  • @4uk4 Ok but with custom js, what kind of response would I send from my controller in php? I can send custom json, but what if I want to keep using this 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?
    – donquixote
    Jul 7, 2022 at 11:59
  • 1
    Yes, a custom ajax command would be perfect, but you can also run custom javascript with the InvokeCommand.
    – 4uk4
    Jul 7, 2022 at 12:16

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.