Conditionally add `woltlab-background-queue-check: yes` to the response
authorAlexander Ebert <ebert@woltlab.com>
Mon, 14 Nov 2022 15:06:56 +0000 (16:06 +0100)
committerAlexander Ebert <ebert@woltlab.com>
Mon, 14 Nov 2022 15:06:56 +0000 (16:06 +0100)
This header is intended to signal the client that an async check for pending jobs in the background queue should be dispatched.

wcfsetup/install/files/lib/http/middleware/TriggerBackgroundQueue.class.php [new file with mode: 0644]
wcfsetup/install/files/lib/system/background/BackgroundQueueHandler.class.php
wcfsetup/install/files/lib/system/request/RequestHandler.class.php

diff --git a/wcfsetup/install/files/lib/http/middleware/TriggerBackgroundQueue.class.php b/wcfsetup/install/files/lib/http/middleware/TriggerBackgroundQueue.class.php
new file mode 100644 (file)
index 0000000..3e93059
--- /dev/null
@@ -0,0 +1,54 @@
+<?php
+
+namespace wcf\http\middleware;
+
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Server\MiddlewareInterface;
+use Psr\Http\Server\RequestHandlerInterface;
+use wcf\http\LegacyPlaceholderResponse;
+use wcf\system\background\BackgroundQueueHandler;
+
+/**
+ * Adds 'woltlab-background-queue-check: yes' to the response
+ * whenever a check was requested.
+ *
+ * @author Alexander Ebert
+ * @copyright 2001-2022 WoltLab GmbH
+ * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
+ * @package WoltLabSuite\Core\Http\Middleware
+ * @since 6.0
+ */
+final class TriggerBackgroundQueue implements MiddlewareInterface
+{
+    private const HEADER_NAME = 'woltlab-background-queue-check';
+    private const HEADER_VALUE = 'yes';
+
+    private readonly BackgroundQueueHandler $backgroundQueueHandler;
+
+    public function __construct()
+    {
+        $this->backgroundQueueHandler = BackgroundQueueHandler::getInstance();
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
+    {
+        $response = $handler->handle($request);
+        if (!$this->backgroundQueueHandler->hasPendingCheck()) {
+            return $response;
+        }
+
+        if ($response instanceof LegacyPlaceholderResponse) {
+            \header(
+                \sprintf('%s: %s', self::HEADER_NAME, self::HEADER_VALUE)
+            );
+
+            return $response;
+        }
+
+        return $response->withHeader(self::HEADER_NAME, self::HEADER_VALUE);
+    }
+}
index 19c1686511ba774bb125b0ed17a39204c63e275e..58bf713f923f857278e78b92368dbbaf8fe19092 100644 (file)
@@ -20,6 +20,12 @@ use wcf\system\WCF;
  */
 final class BackgroundQueueHandler extends SingletonFactory
 {
+    /**
+     * Indicates that the client should trigger a check for
+     * pending jobs in the background queue.
+     */
+    private bool $hasPendingCheck = false;
+
     /**
      * Forces checking whether a background queue item is due.
      * This means that the AJAX request to BackgroundQueuePerformAction is triggered.
@@ -31,6 +37,8 @@ final class BackgroundQueueHandler extends SingletonFactory
         WCF::getTPL()->assign([
             'forceBackgroundQueuePerform' => true,
         ]);
+
+        $this->hasPendingCheck = true;
     }
 
     /**
@@ -227,4 +235,12 @@ final class BackgroundQueueHandler extends SingletonFactory
 
         return $statement->fetchSingleColumn();
     }
+
+    /**
+     * @since 6.0
+     */
+    public function hasPendingCheck(): bool
+    {
+        return $this->hasPendingCheck;
+    }
 }
index bf11b184c86cff89bcdd43bf358ae75bb7255bfe..5299cdf67d2a3814d5e913f092aac9ae0e410895 100644 (file)
@@ -21,6 +21,7 @@ use wcf\http\middleware\EnforceFrameOptions;
 use wcf\http\middleware\HandleStartupErrors;
 use wcf\http\middleware\JsonBody;
 use wcf\http\middleware\PreventMimeSniffing;
+use wcf\http\middleware\TriggerBackgroundQueue;
 use wcf\http\middleware\Xsrf;
 use wcf\http\Pipeline;
 use wcf\system\application\ApplicationHandler;
@@ -110,6 +111,7 @@ final class RequestHandler extends SingletonFactory
                     new CheckForExpiredAppEvaluation(),
                     new CheckForOfflineMode(),
                     new JsonBody(),
+                    new TriggerBackgroundQueue(),
                 ]);
 
                 $response = $pipeline->process($psrRequest, $this->getActiveRequest());