diff --git a/src/Commands/HandleMessageReceived.php b/src/Commands/HandleMessageReceived.php index 8a1c5ac..b4c98c2 100644 --- a/src/Commands/HandleMessageReceived.php +++ b/src/Commands/HandleMessageReceived.php @@ -4,6 +4,8 @@ use DirectoryTree\ImapEngine\Laravel\Events\MessageReceived; use DirectoryTree\ImapEngine\MessageInterface; +use Illuminate\Support\Carbon; +use Illuminate\Support\Facades\Date; use Illuminate\Support\Facades\Event; class HandleMessageReceived @@ -12,7 +14,9 @@ class HandleMessageReceived * Constructor. */ public function __construct( - protected WatchMailbox $command + protected WatchMailbox $command, + protected int &$attempts = 0, + protected ?Carbon &$lastReceivedAt = null, ) {} /** @@ -24,6 +28,10 @@ public function __invoke(MessageInterface $message): void "Message received: [{$message->uid()}]" ); + $this->attempts = 0; + + $this->lastReceivedAt = Date::now(); + Event::dispatch(new MessageReceived($message)); } } diff --git a/src/Commands/WatchMailbox.php b/src/Commands/WatchMailbox.php index 67471d4..45a1dac 100644 --- a/src/Commands/WatchMailbox.php +++ b/src/Commands/WatchMailbox.php @@ -3,12 +3,14 @@ namespace DirectoryTree\ImapEngine\Laravel\Commands; use DirectoryTree\ImapEngine\FolderInterface; +use DirectoryTree\ImapEngine\Laravel\Events\MailboxWatchAttemptsExceeded; use DirectoryTree\ImapEngine\Laravel\Facades\Imap; use DirectoryTree\ImapEngine\Laravel\Support\LoopInterface; use DirectoryTree\ImapEngine\MailboxInterface; use DirectoryTree\ImapEngine\Message; use Exception; use Illuminate\Console\Command; +use Illuminate\Support\Facades\Event; use Illuminate\Support\Str; class WatchMailbox extends Command @@ -40,14 +42,14 @@ public function handle(LoopInterface $loop): void $attempts = 0; - $loop->run(function () use ($mailbox, $with, &$attempts) { + $lastReceivedAt = null; + + $loop->run(function () use ($mailbox, $name, $with, &$attempts, &$lastReceivedAt) { try { $folder = $this->folder($mailbox); - $attempts = 0; - $folder->idle( - new HandleMessageReceived($this), + new HandleMessageReceived($this, $attempts, $lastReceivedAt), new ConfigureIdleQuery($with), $this->option('timeout') ); @@ -65,6 +67,10 @@ public function handle(LoopInterface $loop): void if ($attempts >= $this->option('attempts')) { $this->info("Exception: {$e->getMessage()}"); + Event::dispatch( + new MailboxWatchAttemptsExceeded($name, $attempts, $e, $lastReceivedAt) + ); + throw $e; } diff --git a/src/Events/MailboxWatchAttemptsExceeded.php b/src/Events/MailboxWatchAttemptsExceeded.php new file mode 100644 index 0000000..5c61262 --- /dev/null +++ b/src/Events/MailboxWatchAttemptsExceeded.php @@ -0,0 +1,19 @@ + $event->message->is($message) ); }); + +it('dispatches event when failure attempts have been reached', function () { + Config::set('imap.mailboxes.test', [ + 'host' => 'localhost', + 'port' => 993, + 'encryption' => 'ssl', + 'username' => '', + 'password' => '', + ]); + + Imap::fake('test', folders: [ + new class('inbox') extends FakeFolder + { + public function idle( + callable $callback, + ?callable $query = null, + int $timeout = 300 + ): void { + throw new RuntimeException('Simulated exception'); + } + }, + ]); + + Event::fake(); + + try { + artisan(WatchMailbox::class, [ + 'mailbox' => 'test', + '--attempts' => 5, + ]); + } catch (RuntimeException) { + // Do nothing. + } + + Event::assertDispatched(function (MailboxWatchAttemptsExceeded $event) { + return $event->attempts === 5 + && $event->mailbox === 'test' + && is_null($event->lastReceivedAt) + && $event->exception->getMessage() === 'Simulated exception'; + }); +});