33namespace DirectoryTree \ImapEngine ;
44
55use Carbon \Carbon ;
6- use DirectoryTree \ImapEngine \Connection \Responses \Response ;
76use DirectoryTree \ImapEngine \Connection \Responses \UntaggedResponse ;
87use DirectoryTree \ImapEngine \Exceptions \ConnectionClosedException ;
98use DirectoryTree \ImapEngine \Exceptions \ConnectionTimedOutException ;
109use DirectoryTree \ImapEngine \Exceptions \Exception ;
10+ use Generator ;
1111
1212class Idle
1313{
@@ -35,33 +35,27 @@ public function await(callable $callback): void
3535 {
3636 $ this ->connect ();
3737
38- $ this ->idle ();
39-
40- $ ttl = $ this ->getNextTimeout ();
41-
42- try {
43- $ this ->listen ($ callback , $ ttl );
44- } catch (ConnectionTimedOutException ) {
45- $ this ->reidle ();
46-
47- $ ttl = $ this ->getNextTimeout ();
48-
49- $ this ->listen ($ callback , $ ttl );
50- } catch (ConnectionClosedException ) {
51- $ this ->reconnect ();
52-
38+ // Loop indefinitely, restarting IDLE sessions as needed.
39+ while (true ) {
5340 $ ttl = $ this ->getNextTimeout ();
5441
55- $ this ->listen ($ callback , $ ttl );
42+ try {
43+ $ this ->listen ($ callback , $ ttl );
44+ } catch (ConnectionTimedOutException ) {
45+ $ this ->restart ();
46+ } catch (ConnectionClosedException ) {
47+ $ this ->reconnect ();
48+ }
5649 }
5750 }
5851
5952 /**
60- * Start listening for new messages.
53+ * Start listening for new messages using the idle() generator .
6154 */
6255 protected function listen (callable $ callback , Carbon $ ttl ): void
6356 {
64- while ($ response = $ this ->getNextReply ()) {
57+ // Iterate over responses yielded by the idle generator.
58+ foreach ($ this ->idle () as $ response ) {
6559 if (! $ response instanceof UntaggedResponse) {
6660 continue ;
6761 }
@@ -74,77 +68,69 @@ protected function listen(callable $callback, Carbon $ttl): void
7468 $ ttl = $ this ->getNextTimeout ();
7569 }
7670
77- if (! Carbon:: now ()-> greaterThanOrEqualTo ( $ ttl )) {
78- continue ;
79- }
71+ // If we've been idle too long, break out to restart the session.
72+ if (Carbon:: now ()-> greaterThanOrEqualTo ( $ ttl )) {
73+ $ this -> restart ();
8074
81- try {
82- // If we've been idle too long, we'll send a DONE and re-IDLE.
83- // This will keep the server from killing the connection.
84- // Some Servers require this to avoid disconnection.
85- $ this ->done ();
86- } catch (Exception ) {
87- // If done fails, we're likely already disconnected.
88- // We'll attempt to reconnect and restart the IDLE.
89- $ this ->reconnect ();
75+ break ;
9076 }
91-
92- $ this ->idle ();
93-
94- $ ttl = $ this ->getNextTimeout ();
9577 }
9678 }
9779
9880 /**
99- * Connect the client and begin IDLE .
81+ * Get the folder to idle .
10082 */
101- protected function connect (): void
83+ protected function folder (): Folder
10284 {
103- $ this ->mailbox ->connect ();
104-
105- $ this ->mailbox ->select ($ this ->folder (), true );
85+ return $ this ->mailbox ->folders ()->find ($ this ->folder );
10686 }
10787
10888 /**
109- * Reconnect the client and restart IDLE .
89+ * Issue a done command and restart the idle session .
11090 */
111- protected function reconnect (): void
91+ protected function restart (): void
11292 {
113- $ this ->mailbox ->disconnect ();
114-
115- $ this ->connect ();
93+ try {
94+ // Send DONE to terminate the current IDLE session gracefully.
95+ $ this ->done ();
96+ } catch (Exception ) {
97+ $ this ->reconnect ();
98+ }
11699 }
117100
118101 /**
119- * Disconnect the client.
102+ * Reconnect the client and restart the idle session .
120103 */
121- protected function disconnect (): void
104+ protected function reconnect (): void
122105 {
123- $ this ->done ();
124-
125106 $ this ->mailbox ->disconnect ();
107+
108+ $ this ->connect ();
126109 }
127110
128111 /**
129- * Get the folder to idle.
112+ * Connect the client and select the folder to idle.
130113 */
131- protected function folder (): Folder
114+ protected function connect (): void
132115 {
133- return $ this ->mailbox ->folders ()->find ($ this ->folder );
116+ $ this ->mailbox ->connect ();
117+
118+ $ this ->mailbox ->select ($ this ->folder (), true );
134119 }
135120
136121 /**
137- * End the current IDLE session and start a new one .
122+ * Disconnect the client .
138123 */
139- protected function reidle (): void
124+ protected function disconnect (): void
140125 {
141126 try {
127+ // Attempt to terminate IDLE gracefully.
142128 $ this ->done ();
143129 } catch (Exception ) {
144- $ this -> reconnect ();
130+ // Do nothing.
145131 }
146132
147- $ this ->idle ();
133+ $ this ->mailbox -> disconnect ();
148134 }
149135
150136 /**
@@ -156,23 +142,15 @@ protected function done(): void
156142 }
157143
158144 /**
159- * Being a new IDLE session.
160- */
161- protected function idle (): void
162- {
163- $ this ->mailbox ->connection ()->idle ($ this ->timeout );
164- }
165-
166- /**
167- * Get the next reply from the connection.
145+ * Begin a new IDLE session as a generator.
168146 */
169- protected function getNextReply (): Response
147+ protected function idle (): Generator
170148 {
171- return $ this ->mailbox ->connection ()->nextReply ( );
149+ yield from $ this ->mailbox ->connection ()->idle ( $ this -> timeout );
172150 }
173151
174152 /**
175- * Get the next timeout.
153+ * Get the next timeout as a Carbon instance .
176154 */
177155 protected function getNextTimeout (): Carbon
178156 {
0 commit comments