1313
1414class Consumer extends BaseConsumer
1515{
16- const TIMEOUT_TYPE_IDLE = 'idle ' ;
17- const TIMEOUT_TYPE_GRACEFUL_MAX_EXECUTION = 'graceful-max-execution ' ;
18-
1916 /**
2017 * @var int|null $memoryLimit
2118 */
@@ -32,6 +29,16 @@ class Consumer extends BaseConsumer
3229 */
3330 protected $ gracefulMaxExecutionTimeoutExitCode = 0 ;
3431
32+ /**
33+ * @var int|null
34+ */
35+ protected $ timeoutWait ;
36+
37+ /**
38+ * @var \DateTime|null
39+ */
40+ protected $ lastActivityDateTime ;
41+
3542 /**
3643 * Set the memory limit
3744 *
@@ -67,6 +74,7 @@ public function consume($msgAmount)
6774
6875 $ this ->setupConsumer ();
6976
77+ $ this ->setLastActivityDateTime (new \DateTime ());
7078 while (count ($ this ->getChannel ()->callbacks )) {
7179 $ this ->dispatchEvent (OnConsumeEvent::NAME , new OnConsumeEvent ($ this ));
7280 $ this ->maybeStopConsumer ();
@@ -76,29 +84,35 @@ public function consume($msgAmount)
7684 * graceful max execution timeout is being used.
7785 */
7886 $ waitTimeout = $ this ->chooseWaitTimeout ();
79- if (
80- $ waitTimeout ['timeoutType ' ] === self ::TIMEOUT_TYPE_GRACEFUL_MAX_EXECUTION
81- && $ waitTimeout ['seconds ' ] < 1
87+ if ($ this ->gracefulMaxExecutionDateTime
88+ && $ waitTimeout < 1
8289 ) {
8390 return $ this ->gracefulMaxExecutionTimeoutExitCode ;
8491 }
8592
8693 if (!$ this ->forceStop ) {
8794 try {
88- $ this ->getChannel ()->wait (null , false , $ waitTimeout ['seconds ' ]);
95+ $ this ->getChannel ()->wait (null , false , $ waitTimeout );
96+ $ this ->setLastActivityDateTime (new \DateTime ());
8997 } catch (AMQPTimeoutException $ e ) {
90- if (self ::TIMEOUT_TYPE_GRACEFUL_MAX_EXECUTION === $ waitTimeout ['timeoutType ' ]) {
91- return $ this ->gracefulMaxExecutionTimeoutExitCode ;
92- }
98+ $ now = time ();
9399
94- $ idleEvent = new OnIdleEvent ($ this );
95- $ this ->dispatchEvent (OnIdleEvent::NAME , $ idleEvent );
96-
97- if ($ idleEvent ->isForceStop ()) {
98- if (null !== $ this ->getIdleTimeoutExitCode ()) {
99- return $ this ->getIdleTimeoutExitCode ();
100- } else {
101- throw $ e ;
100+ if ($ this ->gracefulMaxExecutionDateTime
101+ && $ this ->gracefulMaxExecutionDateTime <= new \DateTime ("@ $ now " )
102+ ) {
103+ return $ this ->gracefulMaxExecutionTimeoutExitCode ;
104+ } elseif ($ this ->getIdleTimeout ()
105+ && ($ this ->getLastActivityDateTime ()->getTimestamp () + $ this ->getIdleTimeout () <= $ now )
106+ ) {
107+ $ idleEvent = new OnIdleEvent ($ this );
108+ $ this ->dispatchEvent (OnIdleEvent::NAME , $ idleEvent );
109+
110+ if ($ idleEvent ->isForceStop ()) {
111+ if (null !== $ this ->getIdleTimeoutExitCode ()) {
112+ return $ this ->getIdleTimeoutExitCode ();
113+ } else {
114+ throw $ e ;
115+ }
102116 }
103117 }
104118 }
@@ -115,7 +129,7 @@ public function purge()
115129 {
116130 $ this ->getChannel ()->queue_purge ($ this ->queueOptions ['name ' ], true );
117131 }
118-
132+
119133 /**
120134 * Delete the queue
121135 */
@@ -239,6 +253,11 @@ public function setGracefulMaxExecutionTimeoutExitCode($exitCode)
239253 $ this ->gracefulMaxExecutionTimeoutExitCode = $ exitCode ;
240254 }
241255
256+ public function setTimeoutWait (int $ timeoutWait ): void
257+ {
258+ $ this ->timeoutWait = $ timeoutWait ;
259+ }
260+
242261 /**
243262 * @return \DateTime|null
244263 */
@@ -255,20 +274,19 @@ public function getGracefulMaxExecutionTimeoutExitCode()
255274 return $ this ->gracefulMaxExecutionTimeoutExitCode ;
256275 }
257276
277+ public function getTimeoutWait (): ?int
278+ {
279+ return $ this ->timeoutWait ;
280+ }
281+
258282 /**
259- * Choose the timeout to use for the $this->getChannel()->wait() method.
260- *
261- * @return array Of structure
262- * {
263- * timeoutType: string; // one of self::TIMEOUT_TYPE_*
264- * seconds: int;
265- * }
283+ * Choose the timeout wait (in seconds) to use for the $this->getChannel()->wait() method.
266284 */
267- private function chooseWaitTimeout ()
285+ private function chooseWaitTimeout (): int
268286 {
269287 if ($ this ->gracefulMaxExecutionDateTime ) {
270288 $ allowedExecutionDateInterval = $ this ->gracefulMaxExecutionDateTime ->diff (new \DateTime ());
271- $ allowedExecutionSeconds = $ allowedExecutionDateInterval ->days * 86400
289+ $ allowedExecutionSeconds = $ allowedExecutionDateInterval ->days * 86400
272290 + $ allowedExecutionDateInterval ->h * 3600
273291 + $ allowedExecutionDateInterval ->i * 60
274292 + $ allowedExecutionDateInterval ->s ;
@@ -281,25 +299,30 @@ private function chooseWaitTimeout()
281299 * Respect the idle timeout if it's set and if it's less than
282300 * the remaining allowed execution.
283301 */
284- if (
285- $ this ->getIdleTimeout ()
302+ if ($ this ->getIdleTimeout ()
286303 && $ this ->getIdleTimeout () < $ allowedExecutionSeconds
287304 ) {
288- return array (
289- 'timeoutType ' => self ::TIMEOUT_TYPE_IDLE ,
290- 'seconds ' => $ this ->getIdleTimeout (),
291- );
305+ $ waitTimeout = $ this ->getIdleTimeout ();
306+ } else {
307+ $ waitTimeout = $ allowedExecutionSeconds ;
292308 }
309+ } else {
310+ $ waitTimeout = $ this ->getIdleTimeout ();
311+ }
293312
294- return array (
295- 'timeoutType ' => self ::TIMEOUT_TYPE_GRACEFUL_MAX_EXECUTION ,
296- 'seconds ' => $ allowedExecutionSeconds ,
297- );
313+ if (!is_null ($ this ->getTimeoutWait ()) && $ this ->getTimeoutWait () > 0 ) {
314+ $ waitTimeout = min ($ waitTimeout , $ this ->getTimeoutWait ());
298315 }
316+ return $ waitTimeout ;
317+ }
299318
300- return array (
301- 'timeoutType ' => self ::TIMEOUT_TYPE_IDLE ,
302- 'seconds ' => $ this ->getIdleTimeout (),
303- );
319+ public function setLastActivityDateTime (\DateTime $ dateTime )
320+ {
321+ $ this ->lastActivityDateTime = $ dateTime ;
322+ }
323+
324+ protected function getLastActivityDateTime (): ?\DateTime
325+ {
326+ return $ this ->lastActivityDateTime ;
304327 }
305328}
0 commit comments