Enable Discovery debug logging for production troubleshooting

- Add DISCOVERY_LOG_LEVEL=debug
- Add DISCOVERY_SHOW_PROGRESS=true
- Temporary changes for debugging InitializerProcessor fixes on production
This commit is contained in:
2025-08-11 20:13:26 +02:00
parent 59fd3dd3b1
commit 55a330b223
3683 changed files with 2956207 additions and 16948 deletions

View File

@@ -0,0 +1,345 @@
<?php
declare(strict_types=1);
use App\Domain\Common\ValueObject\Email;
use App\Framework\CommandBus\CommandBus;
use App\Framework\Mail\Commands\SendEmailBatchCommand;
use App\Framework\Mail\Commands\SendEmailCommand;
use App\Framework\Mail\EmailList;
use App\Framework\Mail\Mailer;
use App\Framework\Mail\Message;
use App\Framework\Mail\Testing\MockTransport;
use App\Framework\Mail\TransportResult;
use App\Framework\Queue\Queue;
describe('Mailer', function () {
beforeEach(function () {
$this->transport = new MockTransport();
$this->queue = new MailTestQueue();
$this->commandBus = new TestCommandBus();
$this->mailer = new Mailer($this->transport, $this->queue, $this->commandBus);
$this->message = new Message(
from: new Email('sender@example.com'),
subject: 'Test Subject',
body: 'Test body',
to: new EmailList(new Email('recipient@example.com'))
);
});
describe('send method', function () {
it('sends email successfully using transport', function () {
$result = $this->mailer->send($this->message);
expect($result)->toBeTrue();
expect($this->transport->getSentMessageCount())->toBe(1);
expect($this->transport->getLastSentMessage()['message'])->toBe($this->message);
});
it('returns false when transport fails', function () {
$this->transport->setShouldFail(true, 'Transport error');
$result = $this->mailer->send($this->message);
expect($result)->toBeFalse();
expect($this->transport->getSentMessageCount())->toBe(0);
});
it('does not use queue for synchronous sending', function () {
$this->mailer->send($this->message);
expect($this->queue->wasUsed())->toBeFalse();
expect($this->commandBus->wasUsed())->toBeFalse();
});
});
describe('queue method', function () {
it('dispatches SendEmailCommand with default parameters', function () {
$result = $this->mailer->queue($this->message);
expect($result)->toBeTrue();
expect($this->commandBus->wasUsed())->toBeTrue();
$command = $this->commandBus->getLastCommand();
expect($command)->toBeInstanceOf(SendEmailCommand::class);
expect($command->message)->toBe($this->message);
expect($command->maxRetries)->toBe(3);
expect($command->delaySeconds)->toBe(0);
});
it('dispatches SendEmailCommand with custom parameters', function () {
$result = $this->mailer->queue($this->message, 5, 30);
expect($result)->toBeTrue();
expect($this->commandBus->wasUsed())->toBeTrue();
$command = $this->commandBus->getLastCommand();
expect($command)->toBeInstanceOf(SendEmailCommand::class);
expect($command->message)->toBe($this->message);
expect($command->maxRetries)->toBe(5);
expect($command->delaySeconds)->toBe(30);
});
it('returns false when command dispatch fails', function () {
$this->commandBus->setShouldFail(true);
$result = $this->mailer->queue($this->message);
expect($result)->toBeFalse();
});
it('does not use transport for queued sending', function () {
$this->mailer->queue($this->message);
expect($this->transport->getSentMessageCount())->toBe(0);
});
});
describe('sendBatch method', function () {
beforeEach(function () {
$this->messages = [
new Message(
from: new Email('sender@example.com'),
subject: 'Test 1',
body: 'Body 1',
to: new EmailList(new Email('recipient1@example.com'))
),
new Message(
from: new Email('sender@example.com'),
subject: 'Test 2',
body: 'Body 2',
to: new EmailList(new Email('recipient2@example.com'))
),
];
});
it('sends all messages successfully', function () {
$results = $this->mailer->sendBatch($this->messages);
expect($results)->toHaveCount(2);
expect($results[0])->toBeTrue();
expect($results[1])->toBeTrue();
expect($this->transport->getSentMessageCount())->toBe(2);
});
it('handles mixed success and failure', function () {
// Make transport fail on second call
$transport = new TestTransport();
$transport->failOn(2);
$mailer = new Mailer($transport, $this->queue, $this->commandBus);
$results = $mailer->sendBatch($this->messages);
expect($results)->toHaveCount(2);
expect($results[0])->toBeTrue();
expect($results[1])->toBeFalse();
});
it('handles invalid messages in batch', function () {
$mixedBatch = [
$this->messages[0],
'invalid-message',
$this->messages[1],
];
$results = $this->mailer->sendBatch($mixedBatch);
expect($results)->toHaveCount(3);
expect($results[0])->toBeTrue();
expect($results[1])->toBeFalse();
expect($results[2])->toBeTrue();
});
});
describe('queueBatch method', function () {
beforeEach(function () {
$this->messages = [
new Message(
from: new Email('sender@example.com'),
subject: 'Test 1',
body: 'Body 1',
to: new EmailList(new Email('recipient1@example.com'))
),
new Message(
from: new Email('sender@example.com'),
subject: 'Test 2',
body: 'Body 2',
to: new EmailList(new Email('recipient2@example.com'))
),
];
});
it('dispatches SendEmailBatchCommand for valid messages', function () {
$results = $this->mailer->queueBatch($this->messages);
expect($results)->toHaveCount(2);
expect($results[0])->toBeTrue();
expect($results[1])->toBeTrue();
expect($this->commandBus->wasUsed())->toBeTrue();
$command = $this->commandBus->getLastCommand();
expect($command)->toBeInstanceOf(SendEmailBatchCommand::class);
expect($command->messages)->toBe($this->messages);
expect($command->maxRetries)->toBe(3);
expect($command->delaySeconds)->toBe(0);
});
it('handles mixed valid and invalid messages', function () {
$mixedBatch = [
$this->messages[0],
'invalid-message',
$this->messages[1],
];
$results = $this->mailer->queueBatch($mixedBatch);
expect($results)->toHaveCount(3);
expect($results[0])->toBeTrue(); // Valid message
expect($results[1])->toBeFalse(); // Invalid message
expect($results[2])->toBeTrue(); // Valid message
$command = $this->commandBus->getLastCommand();
expect($command->messages)->toHaveCount(2);
});
it('returns early for all invalid messages', function () {
$invalidBatch = ['invalid1', 'invalid2'];
$results = $this->mailer->queueBatch($invalidBatch);
expect($results)->toHaveCount(2);
expect($results[0])->toBeFalse();
expect($results[1])->toBeFalse();
expect($this->commandBus->wasUsed())->toBeFalse();
});
it('marks all valid messages as failed when batch command fails', function () {
$this->commandBus->setShouldFail(true);
$results = $this->mailer->queueBatch($this->messages);
expect($results)->toHaveCount(2);
expect($results[0])->toBeFalse();
expect($results[1])->toBeFalse();
});
it('uses custom retry parameters', function () {
$this->mailer->queueBatch($this->messages, 5, 60);
$command = $this->commandBus->getLastCommand();
expect($command->maxRetries)->toBe(5);
expect($command->delaySeconds)->toBe(60);
});
});
});
// Test stubs
class MailTestQueue implements Queue
{
private bool $used = false;
private array $jobs = [];
public function push(object $job): void
{
$this->used = true;
$this->jobs[] = $job;
}
public function pop(): ?object
{
return array_shift($this->jobs);
}
public function wasUsed(): bool
{
return $this->used;
}
}
class TestCommandBus implements CommandBus
{
private bool $used = false;
private bool $shouldFail = false;
private ?object $lastCommand = null;
public function dispatch(object $command): mixed
{
$this->used = true;
$this->lastCommand = $command;
if ($this->shouldFail) {
throw new Exception('Command dispatch failed');
}
return null;
}
public function wasUsed(): bool
{
return $this->used;
}
public function getLastCommand(): ?object
{
return $this->lastCommand;
}
public function setShouldFail(bool $shouldFail): void
{
$this->shouldFail = $shouldFail;
}
}
class TestTransport implements \App\Framework\Mail\TransportInterface
{
private MockTransport $mockTransport;
private int $failOn = 0;
private int $callCount = 0;
public function __construct()
{
$this->mockTransport = new MockTransport();
}
public function send(Message $message): TransportResult
{
$this->callCount++;
if ($this->failOn > 0 && $this->callCount === $this->failOn) {
return TransportResult::failure('Simulated failure');
}
return $this->mockTransport->send($message);
}
public function isAvailable(): bool
{
return $this->mockTransport->isAvailable();
}
public function getName(): string
{
return $this->mockTransport->getName();
}
public function getSentMessageCount(): int
{
return $this->mockTransport->getSentMessageCount();
}
public function getLastSentMessage(): ?array
{
return $this->mockTransport->getLastSentMessage();
}
public function failOn(int $callNumber): void
{
$this->failOn = $callNumber;
}
}