Skip to content

Commit 3e3e1c7

Browse files
committed
Arbitrary Bindings #281
2 parents 057bc63 + 4e3a582 commit 3e3e1c7

File tree

11 files changed

+409
-4
lines changed

11 files changed

+409
-4
lines changed

Command/SetupFabricCommand.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,11 @@ protected function execute(InputInterface $input, OutputInterface $output)
2828

2929
$partsHolder = $this->getContainer()->get('old_sound_rabbit_mq.parts_holder');
3030

31-
foreach ($partsHolder->getParts('old_sound_rabbit_mq.base_amqp') as $baseAmqp) {
32-
$baseAmqp->setupFabric();
31+
foreach (array('base_amqp', 'binding') as $key) {
32+
foreach ($partsHolder->getParts('old_sound_rabbit_mq.' . $key) as $baseAmqp) {
33+
$baseAmqp->setupFabric();
34+
}
3335
}
36+
3437
}
3538
}

DependencyInjection/Compiler/RegisterPartsPass.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public function process(ContainerBuilder $container)
1818

1919
$tags = array(
2020
'old_sound_rabbit_mq.base_amqp',
21+
'old_sound_rabbit_mq.binding',
2122
'old_sound_rabbit_mq.producer',
2223
'old_sound_rabbit_mq.consumer',
2324
'old_sound_rabbit_mq.multi_consumer',

DependencyInjection/Configuration.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ public function getConfigTreeBuilder()
2828
;
2929

3030
$this->addConnections($rootNode);
31+
$this->addBindings($rootNode);
3132
$this->addProducers($rootNode);
3233
$this->addConsumers($rootNode);
3334
$this->addMultipleConsumers($rootNode);
@@ -71,6 +72,7 @@ protected function addConnections(ArrayNodeDefinition $node)
7172
;
7273
}
7374

75+
7476
protected function addProducers(ArrayNodeDefinition $node)
7577
{
7678
$node
@@ -93,6 +95,30 @@ protected function addProducers(ArrayNodeDefinition $node)
9395
;
9496
}
9597

98+
protected function addBindings(ArrayNodeDefinition $node)
99+
{
100+
$node
101+
->fixXmlConfig('binding')
102+
->children()
103+
->arrayNode('bindings')
104+
->canBeUnset()
105+
->prototype('array')
106+
->children()
107+
->scalarNode('connection')->defaultValue('default')->end()
108+
->scalarNode('exchange')->defaultNull()->end()
109+
->scalarNode('destination')->defaultNull()->end()
110+
->scalarNode('routing_key')->defaultNull()->end()
111+
->booleanNode('nowait')->defaultFalse()->end()
112+
->booleanNode('destination_is_exchange')->defaultFalse()->end()
113+
->variableNode('arguments')->defaultNull()->end()
114+
->scalarNode('class')->defaultValue('%old_sound_rabbit_mq.binding.class%')->end()
115+
->end()
116+
->end()
117+
->end()
118+
->end()
119+
;
120+
}
121+
96122
protected function addConsumers(ArrayNodeDefinition $node)
97123
{
98124
$node

DependencyInjection/OldSoundRabbitMqExtension.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ public function load(array $configs, ContainerBuilder $container)
4646
$this->collectorEnabled = $this->config['enable_collector'];
4747

4848
$this->loadConnections();
49+
$this->loadBindings();
4950
$this->loadProducers();
5051
$this->loadConsumers();
5152
$this->loadMultipleConsumers();
@@ -96,6 +97,31 @@ protected function loadConnections()
9697
}
9798
}
9899

100+
protected function loadBindings()
101+
{
102+
if ($this->config['sandbox']) {
103+
return;
104+
}
105+
foreach ($this->config['bindings'] as $binding) {
106+
ksort($binding);
107+
$definition = new Definition($binding['class']);
108+
$definition->addTag('old_sound_rabbit_mq.binding');
109+
$definition->addMethodCall('setArguments', array($binding['arguments']));
110+
$definition->addMethodCall('setDestination', array($binding['destination']));
111+
$definition->addMethodCall('setDestinationIsExchange', array($binding['destination_is_exchange']));
112+
$definition->addMethodCall('setExchange', array($binding['exchange']));
113+
$definition->addMethodCall('isNowait', array($binding['nowait']));
114+
$definition->addMethodCall('setRoutingKey', array($binding['routing_key']));
115+
$this->injectConnection($definition, $binding['connection']);
116+
$key = md5(json_encode($binding));
117+
if ($this->collectorEnabled) {
118+
// in the context of a binding, I don't thing logged channels are needed?
119+
$this->injectLoggedChannel($definition, $key, $binding['connection']);
120+
}
121+
$this->container->setDefinition(sprintf('old_sound_rabbit_mq.binding.%s', $key), $definition);
122+
}
123+
}
124+
99125
protected function loadProducers()
100126
{
101127
if ($this->config['sandbox'] == false) {

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,21 @@ Be aware that queues providers are responsible for the proper calls to `setDeque
516516
(not `ConsumerInterface`). In case service providing queues implements `DequeuerAwareInterface`, a call to
517517
`setDequeuer` is added to the definition of the service with a `DequeuerInterface` currently being a `MultipleConsumer`.
518518
519+
### Arbitrary Bindings ###
520+
521+
You may find that your application has a complex workflow and you you need to have arbitrary binding. Arbitrary
522+
binding scenarios might include exchange to exchange bindings via `destination_is_exchange` property.
523+
524+
```yaml
525+
bindings:
526+
- {exchange: foo, destination: bar, routing_key: 'baz.*' }
527+
- {exchange: foo1, destination: foo, routing_key: 'baz.*' destination_is_exchange: true}
528+
```
529+
530+
The rabbitmq:setup-fabric command will declare exchanges and queues as defined in your producer, consumer
531+
and multi consumer configurations before it creates your arbitrary bindings. However, the rabbitmq:setup-fabric will
532+
*NOT* declare addition queues and exchanges defined in the bindings. It's up to you to make sure exchanges/queues are declared.
533+
519534
### Dynamic Consumers ###
520535
521536
Sometimes you have to change the consumer's configuration on the fly.

RabbitMq/AmqpPartsHolder.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ public function addPart($type, BaseAmqp $part)
1818

1919
public function getParts($type)
2020
{
21-
return $this->parts[(string) $type];
21+
$type = (string) $type;
22+
return isset($this->parts[$type]) ? $this->parts[$type] : array();
2223
}
2324
}

RabbitMq/Binding.php

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
<?php
2+
/**
3+
* Created by PhpStorm.
4+
* User: brandon
5+
* Date: 6/24/15
6+
* Time: 3:49 PM
7+
*/
8+
9+
namespace OldSound\RabbitMqBundle\RabbitMq;
10+
11+
12+
class Binding extends BaseAmqp
13+
{
14+
/**
15+
* @var string
16+
*/
17+
protected $exchange;
18+
19+
/**
20+
* @var string
21+
*/
22+
protected $destination;
23+
24+
/**
25+
* @var bool
26+
*/
27+
protected $destinationIsExchange = false;
28+
29+
/**
30+
* @var string
31+
*/
32+
protected $routingKey;
33+
34+
/**
35+
* @var bool
36+
*/
37+
protected $nowait = false;
38+
39+
/**
40+
* @var array
41+
*/
42+
protected $arguments;
43+
44+
/**
45+
* @return string
46+
*/
47+
public function getExchange()
48+
{
49+
return $this->exchange;
50+
}
51+
52+
/**
53+
* @param string $exchange
54+
*/
55+
public function setExchange($exchange)
56+
{
57+
$this->exchange = $exchange;
58+
}
59+
60+
/**
61+
* @return string
62+
*/
63+
public function getDestination()
64+
{
65+
return $this->destination;
66+
}
67+
68+
/**
69+
* @param bool $destination
70+
*/
71+
public function setDestination($destination)
72+
{
73+
$this->destination = $destination;
74+
}
75+
76+
/**
77+
* @return bool
78+
*/
79+
public function getDestinationIsExchange()
80+
{
81+
return $this->destinationIsExchange;
82+
}
83+
84+
/**
85+
* @param string $destinationIsExchange
86+
*/
87+
public function setDestinationIsExchange($destinationIsExchange)
88+
{
89+
$this->destinationIsExchange = $destinationIsExchange;
90+
}
91+
92+
/**
93+
* @return string
94+
*/
95+
public function getRoutingKey()
96+
{
97+
return $this->routingKey;
98+
}
99+
100+
/**
101+
* @param string $routingKey
102+
*/
103+
public function setRoutingKey($routingKey)
104+
{
105+
$this->routingKey = $routingKey;
106+
}
107+
108+
/**
109+
* @return boolean
110+
*/
111+
public function isNowait()
112+
{
113+
return $this->nowait;
114+
}
115+
116+
/**
117+
* @param boolean $nowait
118+
*/
119+
public function setNowait($nowait)
120+
{
121+
$this->nowait = $nowait;
122+
}
123+
124+
/**
125+
* @return array
126+
*/
127+
public function getArguments()
128+
{
129+
return $this->arguments;
130+
}
131+
132+
/**
133+
* @param array $arguments
134+
*/
135+
public function setArguments($arguments)
136+
{
137+
$this->arguments = $arguments;
138+
}
139+
140+
141+
/**
142+
* create bindings
143+
*
144+
* @return void
145+
*/
146+
public function setupFabric()
147+
{
148+
$method = ($this->destinationIsExchange) ? 'exchange_bind' : 'queue_bind';
149+
$channel = $this->getChannel();
150+
call_user_func(
151+
array($channel, $method),
152+
$this->destination,
153+
$this->exchange,
154+
$this->routingKey,
155+
$this->nowait,
156+
$this->arguments
157+
);
158+
}
159+
}

Resources/config/rabbitmq.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
<parameter key="old_sound_rabbit_mq.connection.class">PhpAmqpLib\Connection\AMQPConnection</parameter>
88
<parameter key="old_sound_rabbit_mq.lazy.connection.class">PhpAmqpLib\Connection\AMQPLazyConnection</parameter>
99
<parameter key="old_sound_rabbit_mq.connection_factory.class">OldSound\RabbitMqBundle\RabbitMq\AMQPConnectionFactory</parameter>
10+
<parameter key="old_sound_rabbit_mq.binding.class">OldSound\RabbitMqBundle\RabbitMq\Binding</parameter>
1011
<parameter key="old_sound_rabbit_mq.producer.class">OldSound\RabbitMqBundle\RabbitMq\Producer</parameter>
1112
<parameter key="old_sound_rabbit_mq.consumer.class">OldSound\RabbitMqBundle\RabbitMq\Consumer</parameter>
1213
<parameter key="old_sound_rabbit_mq.multi_consumer.class">OldSound\RabbitMqBundle\RabbitMq\MultipleConsumer</parameter>

Tests/DependencyInjection/Fixtures/test.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,9 @@ old_sound_rabbit_mq:
138138
type: direct
139139
callback: bar.dynamic.callback
140140
queue_options_provider: bar.dynamic.provider
141-
141+
bindings:
142+
- {exchange: foo, destination: bar, routing_key: baz}
143+
- {exchange: moo, connection: default2, destination: cow, nowait: true, destination_is_exchange: true, arguments: {moo:cow}}
142144
anon_consumers:
143145
foo_anon_consumer:
144146
connection: foo_connection

0 commit comments

Comments
 (0)