feat: add a kill switch for the chatbot content feed

This commit is contained in:
fromme committed 2026-10-08 09:36:16 +02:00
1 parent 992ec19c33
commit 416ac5c13d
3 files changed
+50 -1

No files matched your search

+16
View File
@@ -10,3 +10,19 @@ GET https://ep-reisen.ddev.site/api/hotel
&key=abcabc123
###
### GET chatbot content manifest (cmsApiKey in extension configuration)
GET https://ep-reisen.ddev.site/api/content/manifest
X-Api-Key: abcabc123
### GET chatbot content records (type: product, hotel, region, country, city, concept, news; at most 100 uids)
GET https://ep-reisen.ddev.site/api/content/records
?type=product
&uids=1,2,3
X-Api-Key: abcabc123
### GET the content-only render of one page (use a contentUrl from the manifest)
GET https://ep-reisen.ddev.site/skireisen/infos/skiurlaub-infos/schneepchen/liegestuhl?type=1730
X-Api-Key: abcabc123
###
@@ -26,6 +26,8 @@ class ContentFeedApi
private const MAX_RECORDS_PER_REQUEST = 100;
private const DISABLED_RETRY_AFTER = 3600;
private const JSON_FLAGS = JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES;
/**
@@ -73,6 +75,10 @@ class ContentFeedApi
return $this->error('Invalid or missing api key', 403);
}
if (!$this->configuration->isEnabled()) {
return self::disabledResponse();
}
if ([] === $this->configuration->getSites()) {
// An empty feed would read as "everything was deleted". Refuse instead.
return $this->error('Content feed has no sites configured', 503);
@@ -137,6 +143,21 @@ class ContentFeedApi
return $manifest;
}
/**
* The kill switch: contentFeedEnabled = 0 in the extension configuration, for when the host
* is struggling. The consumer stops its run, keeps everything it has and tries again later -
* nothing is deleted on the chatbot side.
*/
public static function disabledResponse(): ResponseInterface
{
return new JsonResponse(
['message' => 'Content feed is switched off'],
503,
['Retry-After' => (string) self::DISABLED_RETRY_AFTER],
self::JSON_FLAGS
);
}
private function error(string $message, int $status): ResponseInterface
{
return new JsonResponse(['message' => $message], $status, [], self::JSON_FLAGS);
@@ -2,6 +2,8 @@
namespace EP\EpProducts\Middleware;
use EP\EpProducts\ContentFeed\ContentFeedApi;
use EP\EpProducts\ContentFeed\ContentFeedConfiguration;
use EP\EpProducts\ContentFeed\ManifestBuilder;
use EP\EpProducts\Http\ApiKeyAuthenticator;
use Psr\Http\Message\ResponseInterface;
@@ -27,9 +29,15 @@ class ContentPageTypeGuardMiddleware implements MiddlewareInterface
*/
private $authenticator;
public function __construct(ApiKeyAuthenticator $authenticator)
/**
* @var ContentFeedConfiguration
*/
private $configuration;
public function __construct(ApiKeyAuthenticator $authenticator, ContentFeedConfiguration $configuration)
{
$this->authenticator = $authenticator;
$this->configuration = $configuration;
}
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
@@ -48,6 +56,10 @@ class ContentPageTypeGuardMiddleware implements MiddlewareInterface
->pageNotFoundAction($request, 'The requested page does not exist');
}
if (!$this->configuration->isEnabled()) {
return ContentFeedApi::disabledResponse();
}
return $handler->handle($request);
}
}