Skip to content

Commit 2698584

Browse files
authored
Merge pull request #3 from DirectoryTree/enhancement-2
Dispatch `MailboxWatchAttemptsExceeded` when failing to idle on mailbox
2 parents a7820a0 + 00a1269 commit 2698584

File tree

4 files changed

+81
-5
lines changed

4 files changed

+81
-5
lines changed

src/Commands/HandleMessageReceived.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
use DirectoryTree\ImapEngine\Laravel\Events\MessageReceived;
66
use DirectoryTree\ImapEngine\MessageInterface;
7+
use Illuminate\Support\Carbon;
8+
use Illuminate\Support\Facades\Date;
79
use Illuminate\Support\Facades\Event;
810

911
class HandleMessageReceived
@@ -12,7 +14,9 @@ class HandleMessageReceived
1214
* Constructor.
1315
*/
1416
public function __construct(
15-
protected WatchMailbox $command
17+
protected WatchMailbox $command,
18+
protected int &$attempts = 0,
19+
protected ?Carbon &$lastReceivedAt = null,
1620
) {}
1721

1822
/**
@@ -24,6 +28,10 @@ public function __invoke(MessageInterface $message): void
2428
"Message received: [{$message->uid()}]"
2529
);
2630

31+
$this->attempts = 0;
32+
33+
$this->lastReceivedAt = Date::now();
34+
2735
Event::dispatch(new MessageReceived($message));
2836
}
2937
}

src/Commands/WatchMailbox.php

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,14 @@
33
namespace DirectoryTree\ImapEngine\Laravel\Commands;
44

55
use DirectoryTree\ImapEngine\FolderInterface;
6+
use DirectoryTree\ImapEngine\Laravel\Events\MailboxWatchAttemptsExceeded;
67
use DirectoryTree\ImapEngine\Laravel\Facades\Imap;
78
use DirectoryTree\ImapEngine\Laravel\Support\LoopInterface;
89
use DirectoryTree\ImapEngine\MailboxInterface;
910
use DirectoryTree\ImapEngine\Message;
1011
use Exception;
1112
use Illuminate\Console\Command;
13+
use Illuminate\Support\Facades\Event;
1214
use Illuminate\Support\Str;
1315

1416
class WatchMailbox extends Command
@@ -40,14 +42,14 @@ public function handle(LoopInterface $loop): void
4042

4143
$attempts = 0;
4244

43-
$loop->run(function () use ($mailbox, $with, &$attempts) {
45+
$lastReceivedAt = null;
46+
47+
$loop->run(function () use ($mailbox, $name, $with, &$attempts, &$lastReceivedAt) {
4448
try {
4549
$folder = $this->folder($mailbox);
4650

47-
$attempts = 0;
48-
4951
$folder->idle(
50-
new HandleMessageReceived($this),
52+
new HandleMessageReceived($this, $attempts, $lastReceivedAt),
5153
new ConfigureIdleQuery($with),
5254
$this->option('timeout')
5355
);
@@ -65,6 +67,10 @@ public function handle(LoopInterface $loop): void
6567
if ($attempts >= $this->option('attempts')) {
6668
$this->info("Exception: {$e->getMessage()}");
6769

70+
Event::dispatch(
71+
new MailboxWatchAttemptsExceeded($name, $attempts, $e, $lastReceivedAt)
72+
);
73+
6874
throw $e;
6975
}
7076

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
namespace DirectoryTree\ImapEngine\Laravel\Events;
4+
5+
use Carbon\Carbon;
6+
use Exception;
7+
8+
class MailboxWatchAttemptsExceeded
9+
{
10+
/**
11+
* Constructor.
12+
*/
13+
public function __construct(
14+
public string $mailbox,
15+
public int $attempts,
16+
public Exception $exception,
17+
public ?Carbon $lastReceivedAt = null,
18+
) {}
19+
}

tests/Commands/WatchMailboxTest.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace DirectoryTree\ImapEngine\Laravel\Tests;
44

55
use DirectoryTree\ImapEngine\Laravel\Commands\WatchMailbox;
6+
use DirectoryTree\ImapEngine\Laravel\Events\MailboxWatchAttemptsExceeded;
67
use DirectoryTree\ImapEngine\Laravel\Events\MessageReceived;
78
use DirectoryTree\ImapEngine\Laravel\Facades\Imap;
89
use DirectoryTree\ImapEngine\Laravel\Support\LoopFake;
@@ -13,6 +14,7 @@
1314
use Illuminate\Support\Facades\Config;
1415
use Illuminate\Support\Facades\Event;
1516
use InvalidArgumentException;
17+
use RuntimeException;
1618

1719
use function Pest\Laravel\artisan;
1820

@@ -48,3 +50,44 @@
4850
fn (MessageReceived $event) => $event->message->is($message)
4951
);
5052
});
53+
54+
it('dispatches event when failure attempts have been reached', function () {
55+
Config::set('imap.mailboxes.test', [
56+
'host' => 'localhost',
57+
'port' => 993,
58+
'encryption' => 'ssl',
59+
'username' => '',
60+
'password' => '',
61+
]);
62+
63+
Imap::fake('test', folders: [
64+
new class('inbox') extends FakeFolder
65+
{
66+
public function idle(
67+
callable $callback,
68+
?callable $query = null,
69+
int $timeout = 300
70+
): void {
71+
throw new RuntimeException('Simulated exception');
72+
}
73+
},
74+
]);
75+
76+
Event::fake();
77+
78+
try {
79+
artisan(WatchMailbox::class, [
80+
'mailbox' => 'test',
81+
'--attempts' => 5,
82+
]);
83+
} catch (RuntimeException) {
84+
// Do nothing.
85+
}
86+
87+
Event::assertDispatched(function (MailboxWatchAttemptsExceeded $event) {
88+
return $event->attempts === 5
89+
&& $event->mailbox === 'test'
90+
&& is_null($event->lastReceivedAt)
91+
&& $event->exception->getMessage() === 'Simulated exception';
92+
});
93+
});

0 commit comments

Comments
 (0)