20
20
use Interop \Queue \PsrTopic ;
21
21
use PhpAmqpLib \Channel \AMQPChannel ;
22
22
use PhpAmqpLib \Connection \AbstractConnection ;
23
+ use PhpAmqpLib \Exception \AMQPTimeoutException ;
24
+ use PhpAmqpLib \Message \AMQPMessage as LibAMQPMessage ;
23
25
use PhpAmqpLib \Wire \AMQPTable ;
24
26
25
27
class AmqpContext implements InteropAmqpContext, DelayStrategyAware
@@ -319,15 +321,55 @@ public function subscribe(InteropAmqpConsumer $consumer, callable $callback)
319
321
return ;
320
322
}
321
323
322
- throw new \LogicException ('Not implemented ' );
324
+ $ libCallback = function (LibAMQPMessage $ message ) {
325
+ $ receivedMessage = $ this ->convertMessage ($ message );
326
+ $ receivedMessage ->setConsumerTag ($ message ->delivery_info ['consumer_tag ' ]);
327
+
328
+ /**
329
+ * @var AmqpConsumer
330
+ * @var callable $callback
331
+ */
332
+ list ($ consumer , $ callback ) = $ this ->subscribers [$ message ->delivery_info ['consumer_tag ' ]];
333
+
334
+ if (false === call_user_func ($ callback , $ receivedMessage , $ consumer )) {
335
+ throw new StopBasicConsumptionException ();
336
+ }
337
+ };
338
+
339
+ $ consumerTag = $ this ->getChannel ()->basic_consume (
340
+ $ consumer ->getQueue ()->getQueueName (),
341
+ $ consumer ->getConsumerTag (),
342
+ (bool ) ($ consumer ->getFlags () & InteropAmqpConsumer::FLAG_NOLOCAL ),
343
+ (bool ) ($ consumer ->getFlags () & InteropAmqpConsumer::FLAG_NOACK ),
344
+ (bool ) ($ consumer ->getFlags () & InteropAmqpConsumer::FLAG_EXCLUSIVE ),
345
+ (bool ) ($ consumer ->getFlags () & InteropAmqpConsumer::FLAG_NOWAIT ),
346
+ $ libCallback
347
+ );
348
+
349
+ if (empty ($ consumerTag )) {
350
+ throw new Exception ('Got empty consumer tag ' );
351
+ }
352
+
353
+ $ consumer ->setConsumerTag ($ consumerTag );
354
+
355
+ $ this ->subscribers [$ consumerTag ] = [$ consumer , $ callback ];
323
356
}
324
357
325
358
/**
326
359
* {@inheritdoc}
327
360
*/
328
361
public function unsubscribe (InteropAmqpConsumer $ consumer )
329
362
{
330
- throw new \LogicException ('Not implemented ' );
363
+ if (false == $ consumer ->getConsumerTag ()) {
364
+ return ;
365
+ }
366
+
367
+ $ consumerTag = $ consumer ->getConsumerTag ();
368
+
369
+ $ this ->getChannel ()->basic_cancel ($ consumerTag );
370
+
371
+ $ consumer ->setConsumerTag (null );
372
+ unset($ this ->subscribers [$ consumerTag ], $ this ->getChannel ()->callbacks [$ consumerTag ]);
331
373
}
332
374
333
375
/**
@@ -339,7 +381,27 @@ public function consume($timeout = 0)
339
381
throw new \LogicException ('There is no subscribers. Consider calling basicConsumeSubscribe before consuming ' );
340
382
}
341
383
342
- throw new \LogicException ('Not implemented ' );
384
+ try {
385
+ while (true ) {
386
+ $ start = microtime (true );
387
+
388
+ $ this ->channel ->wait (null , false , $ timeout / 1000 );
389
+
390
+ if ($ timeout <= 0 ) {
391
+ continue ;
392
+ }
393
+
394
+ // compute remaining timeout and continue until time is up
395
+ $ stop = microtime (true );
396
+ $ timeout -= ($ stop - $ start ) * 1000 ;
397
+
398
+ if ($ timeout <= 0 ) {
399
+ break ;
400
+ }
401
+ }
402
+ } catch (AMQPTimeoutException $ e ) {
403
+ } catch (StopBasicConsumptionException $ e ) {
404
+ }
343
405
}
344
406
345
407
/**
@@ -358,4 +420,28 @@ private function getChannel()
358
420
359
421
return $ this ->channel ;
360
422
}
423
+
424
+ /**
425
+ * @param LibAMQPMessage $amqpMessage
426
+ *
427
+ * @return InteropAmqpMessage
428
+ */
429
+ private function convertMessage (LibAMQPMessage $ amqpMessage )
430
+ {
431
+ $ headers = new AMQPTable ($ amqpMessage ->get_properties ());
432
+ $ headers = $ headers ->getNativeData ();
433
+
434
+ $ properties = [];
435
+ if (isset ($ headers ['application_headers ' ])) {
436
+ $ properties = $ headers ['application_headers ' ];
437
+ }
438
+ unset($ headers ['application_headers ' ]);
439
+
440
+ $ message = new AmqpMessage ($ amqpMessage ->getBody (), $ properties , $ headers );
441
+ $ message ->setDeliveryTag ($ amqpMessage ->delivery_info ['delivery_tag ' ]);
442
+ $ message ->setRedelivered ($ amqpMessage ->delivery_info ['redelivered ' ]);
443
+ $ message ->setRoutingKey ($ amqpMessage ->delivery_info ['routing_key ' ]);
444
+
445
+ return $ message ;
446
+ }
361
447
}
0 commit comments