3
3
namespace Enqueue \AmqpBunny ;
4
4
5
5
use Bunny \Channel ;
6
+ use Bunny \Client ;
7
+ use Bunny \Message ;
6
8
use Enqueue \AmqpTools \DelayStrategyAware ;
7
9
use Enqueue \AmqpTools \DelayStrategyAwareTrait ;
8
10
use Interop \Amqp \AmqpBind as InteropAmqpBind ;
11
+ use Interop \Amqp \AmqpConsumer as InteropAmqpConsumer ;
9
12
use Interop \Amqp \AmqpContext as InteropAmqpContext ;
10
13
use Interop \Amqp \AmqpMessage as InteropAmqpMessage ;
11
14
use Interop \Amqp \AmqpQueue as InteropAmqpQueue ;
@@ -43,6 +46,13 @@ class AmqpContext implements InteropAmqpContext, DelayStrategyAware
43
46
*/
44
47
private $ buffer ;
45
48
49
+ /**
50
+ * an item contains an array: [AmqpConsumerInterop $consumer, callable $callback];.
51
+ *
52
+ * @var array
53
+ */
54
+ private $ subscribers ;
55
+
46
56
/**
47
57
* Callable must return instance of \Bunny\Channel once called.
48
58
*
@@ -309,6 +319,77 @@ public function setQos($prefetchSize, $prefetchCount, $global)
309
319
$ this ->getBunnyChannel ()->qos ($ prefetchSize , $ prefetchCount , $ global );
310
320
}
311
321
322
+ /**
323
+ * {@inheritdoc}
324
+ */
325
+ public function subscribe (InteropAmqpConsumer $ consumer , callable $ callback )
326
+ {
327
+ if ($ consumer ->getConsumerTag () && array_key_exists ($ consumer ->getConsumerTag (), $ this ->subscribers )) {
328
+ return ;
329
+ }
330
+
331
+ $ bunnyCallback = function (Message $ message , Channel $ channel , Client $ bunny ) {
332
+ $ receivedMessage = $ this ->convertMessage ($ message );
333
+ $ receivedMessage ->setConsumerTag ($ message ->consumerTag );
334
+
335
+ /**
336
+ * @var AmqpConsumer
337
+ * @var callable $callback
338
+ */
339
+ list ($ consumer , $ callback ) = $ this ->subscribers [$ message ->consumerTag ];
340
+
341
+ if (false === call_user_func ($ callback , $ receivedMessage , $ consumer )) {
342
+ $ bunny ->stop ();
343
+ }
344
+ };
345
+
346
+ $ frame = $ this ->getBunnyChannel ()->consume (
347
+ $ bunnyCallback ,
348
+ $ consumer ->getQueue ()->getQueueName (),
349
+ $ consumer ->getConsumerTag (),
350
+ (bool ) ($ consumer ->getFlags () & InteropAmqpConsumer::FLAG_NOLOCAL ),
351
+ (bool ) ($ consumer ->getFlags () & InteropAmqpConsumer::FLAG_NOACK ),
352
+ (bool ) ($ consumer ->getFlags () & InteropAmqpConsumer::FLAG_EXCLUSIVE ),
353
+ (bool ) ($ consumer ->getFlags () & InteropAmqpConsumer::FLAG_NOWAIT )
354
+ );
355
+
356
+ if (empty ($ frame ->consumerTag )) {
357
+ throw new Exception ('Got empty consumer tag ' );
358
+ }
359
+
360
+ $ consumer ->setConsumerTag ($ frame ->consumerTag );
361
+
362
+ $ this ->subscribers [$ frame ->consumerTag ] = [$ consumer , $ callback ];
363
+ }
364
+
365
+ /**
366
+ * {@inheritdoc}
367
+ */
368
+ public function unsubscribe (InteropAmqpConsumer $ consumer )
369
+ {
370
+ if (false == $ consumer ->getConsumerTag ()) {
371
+ return ;
372
+ }
373
+
374
+ $ consumerTag = $ consumer ->getConsumerTag ();
375
+
376
+ $ this ->getBunnyChannel ()->cancel ($ consumerTag );
377
+ $ consumer ->setConsumerTag (null );
378
+ unset($ this ->subscribers [$ consumerTag ]);
379
+ }
380
+
381
+ /**
382
+ * {@inheritdoc}
383
+ */
384
+ public function consume ($ timeout = 0 )
385
+ {
386
+ if (empty ($ this ->subscribers )) {
387
+ throw new \LogicException ('There is no subscribers. Consider calling basicConsumeSubscribe before consuming ' );
388
+ }
389
+
390
+ $ this ->getBunnyChannel ()->getClient ()->run ($ timeout / 1000 );
391
+ }
392
+
312
393
/**
313
394
* @return Channel
314
395
*/
@@ -328,4 +409,27 @@ public function getBunnyChannel()
328
409
329
410
return $ this ->bunnyChannel ;
330
411
}
412
+
413
+ /**
414
+ * @param Message $bunnyMessage
415
+ *
416
+ * @return InteropAmqpMessage
417
+ */
418
+ private function convertMessage (Message $ bunnyMessage )
419
+ {
420
+ $ headers = $ bunnyMessage ->headers ;
421
+
422
+ $ properties = [];
423
+ if (isset ($ headers ['application_headers ' ])) {
424
+ $ properties = $ headers ['application_headers ' ];
425
+ }
426
+ unset($ headers ['application_headers ' ]);
427
+
428
+ $ message = new AmqpMessage ($ bunnyMessage ->content , $ properties , $ headers );
429
+ $ message ->setDeliveryTag ($ bunnyMessage ->deliveryTag );
430
+ $ message ->setRedelivered ($ bunnyMessage ->redelivered );
431
+ $ message ->setRoutingKey ($ bunnyMessage ->routingKey );
432
+
433
+ return $ message ;
434
+ }
331
435
}
0 commit comments