fix: resolve RedisCache array offset error and improve discovery diagnostics

- Fix RedisCache driver to handle MGET failures gracefully with fallback
- Add comprehensive discovery context comparison debug tools
- Identify root cause: WEB context discovery missing 166 items vs CLI
- WEB context missing RequestFactory class entirely (52 vs 69 commands)
- Improved exception handling with detailed binding diagnostics
This commit is contained in:
2025-09-12 20:05:18 +02:00
parent 8040d3e7a5
commit e30753ba0e
46990 changed files with 10789682 additions and 89639 deletions

View File

@@ -62,4 +62,14 @@ final readonly class WebhookReceived implements DomainEvent
'payload_size' => strlen($this->payload->rawBody),
];
}
public function isFromProvider(WebhookProvider $provider): bool
{
return $this->provider->equals($provider);
}
public function getData(): array
{
return $this->payload->data;
}
}

View File

@@ -7,8 +7,9 @@ namespace App\Framework\Webhook\Processing;
use App\Framework\Core\Events\EventDispatcher;
use App\Framework\Http\HttpRequest;
use App\Framework\Http\HttpResponse;
use App\Framework\Http\JsonResult;
use App\Framework\Http\Status;
use App\Framework\Logging\Logger;
use App\Framework\Router\Result\JsonResult;
use App\Framework\Webhook\Events\WebhookFailed;
use App\Framework\Webhook\Events\WebhookReceived;
use App\Framework\Webhook\Security\SignatureVerifier;
@@ -198,6 +199,6 @@ final readonly class WebhookRequestHandler
'message' => $message,
'request_id' => $requestId,
'timestamp' => date('c'),
], $statusCode);
], Status::from($statusCode));
}
}

View File

@@ -33,6 +33,8 @@ final readonly class WebhookSender
/**
* Send webhook to endpoint with signature
*
* @param array<string, mixed> $options
*/
public function send(
string $url,
@@ -109,7 +111,7 @@ final readonly class WebhookSender
]);
$this->eventDispatcher->dispatch(
WebhookSent::create($provider, $payload, $url, $result)
WebhookSent::create($url, $payload->toArray(), $result->statusCode, $provider->toString())
);
} else {
$this->logger->warning('Webhook failed with error response', [
@@ -159,6 +161,8 @@ final readonly class WebhookSender
/**
* Send webhook with automatic retry logic
*
* @param array<string, mixed> $options
*/
public function sendWithRetry(
string $url,
@@ -204,7 +208,7 @@ final readonly class WebhookSender
}
}
return $lastResult;
return $lastResult ?? throw new \RuntimeException('No webhook send attempts were made');
}
/**

View File

@@ -68,6 +68,16 @@ final readonly class WebhookProvider
);
}
public static function fromString(string $name): self
{
return match (strtolower(trim($name))) {
'stripe' => self::stripe(),
'github' => self::github(),
'legal-service' => self::legalService(),
default => self::generic($name)
};
}
public function toString(): string
{
return $this->name;

View File

@@ -30,6 +30,7 @@ final readonly class WebhookService
/**
* Process incoming webhook request
* @param array<string> $allowedEvents
*/
public function processIncoming(
HttpRequest $request,
@@ -44,6 +45,7 @@ final readonly class WebhookService
/**
* Send webhook immediately (synchronous)
* @param array<string, mixed> $options
*/
public function send(
string $url,
@@ -51,12 +53,13 @@ final readonly class WebhookService
WebhookProvider $provider,
string $secret,
array $options = []
) {
): mixed {
return $this->sender->send($url, $payload, $provider, $secret, $options);
}
/**
* Send webhook with automatic retries (synchronous)
* @param array<string, mixed> $options
*/
public function sendWithRetry(
string $url,
@@ -65,7 +68,7 @@ final readonly class WebhookService
string $secret,
int $maxRetries = 3,
array $options = []
) {
): mixed {
return $this->sender->sendWithRetry($url, $payload, $provider, $secret, $maxRetries, $options);
}
@@ -73,6 +76,7 @@ final readonly class WebhookService
/**
* Schedule webhook for asynchronous delivery
* @param array<string, mixed> $options
*/
public function schedule(
string $url,
@@ -86,6 +90,7 @@ final readonly class WebhookService
/**
* Schedule webhook for future delivery
* @param array<string, mixed> $options
*/
public function scheduleAt(
string $url,
@@ -100,6 +105,7 @@ final readonly class WebhookService
/**
* Schedule webhook with delay in seconds
* @param array<string, mixed> $options
*/
public function scheduleIn(
string $url,
@@ -114,6 +120,7 @@ final readonly class WebhookService
/**
* Schedule high priority webhook
* @param array<string, mixed> $options
*/
public function scheduleUrgent(
string $url,
@@ -129,6 +136,8 @@ final readonly class WebhookService
/**
* Send event webhook (creates payload automatically)
* @param array<string, mixed> $eventData
* @param array<string, mixed> $options
*/
public function sendEvent(
string $url,
@@ -138,7 +147,7 @@ final readonly class WebhookService
string $secret,
bool $async = true,
array $options = []
) {
): mixed {
$payload = WebhookPayload::create($eventData, $eventType);
if ($async) {
@@ -150,6 +159,8 @@ final readonly class WebhookService
/**
* Send legal content update webhook (for impressum/privacy updates)
* @param array<string, mixed> $legalData
* @param array<string, mixed> $options
*/
public function sendLegalUpdate(
string $url,
@@ -157,7 +168,7 @@ final readonly class WebhookService
string $secret,
bool $async = true,
array $options = []
) {
): mixed {
$provider = WebhookProvider::fromString('legal-service');
$payload = WebhookPayload::create($legalData, 'legal.content.updated');
@@ -170,6 +181,8 @@ final readonly class WebhookService
/**
* Bulk send multiple webhooks
* @param array<array{url: string, payload: WebhookPayload, provider: WebhookProvider, secret: string, options?: array<string, mixed>}> $webhooks
* @return array<mixed>
*/
public function sendBulk(array $webhooks, bool $async = true): array
{
@@ -195,6 +208,7 @@ final readonly class WebhookService
/**
* Create webhook payload from data
* @param array<string, mixed> $data
*/
public function createPayload(array $data, ?string $eventType = null): WebhookPayload
{
@@ -213,6 +227,7 @@ final readonly class WebhookService
/**
* Get queue statistics
* @return array<string, mixed>
*/
public function getQueueStats(): array
{