├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── doc ├── BIG.md ├── FAILURE.md ├── OLDSOUND.md ├── PARTITION.md ├── SETUP.md └── SWARROT.md ├── docker-compose.yml ├── docker └── php │ └── Dockerfile ├── img ├── big-cluster.png ├── ctop_start.png ├── rabbit-netpart-1.png ├── rabbit-netpart-2.png ├── rabbitmq-all-restart.png ├── rabbitmq-ha-policy-2.png ├── rabbitmq-netpart-ctop.png ├── rabbitmq-node1-restart.png ├── rabbitmq-node1-stop.png ├── rabbitmq-node2-stop.png ├── rabbitmq-node3-stop.png ├── rabbitmq-oldsound-consumers.png ├── rabbitmq-oldsound-run.png ├── rabbitmq-policy-oldsound.png ├── rabbitmq-policy-swarrot.png ├── rabbitmq-swarrot-ex-q.png ├── rabbitmq-swarrot-run.png ├── rabbitmq.png ├── rabbitmq_cluster_start.png ├── rabbitmq_netpart.png ├── retry-1.png ├── retry-2.png ├── retry-3.png ├── retry-4.png └── retry-5.png └── sf ├── app ├── AppKernel.php └── config │ ├── config.yml │ ├── config_dev.yml │ ├── config_prod.yml │ └── services.yml ├── bin └── console ├── composer.json ├── composer.lock ├── consume.sh ├── index.sh ├── produce.sh ├── src └── AppBundle │ ├── AppBundle.php │ ├── Command │ ├── OldSoundCommand.php │ └── TestCommand.php │ └── Processor │ ├── OldSoundProcessor.php │ └── TestConsumeQuicklyProcessor.php └── vhost.yml /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | sf/vendor/ 3 | sf/var/ 4 | var/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Yannick Pereira-Reis 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | project=rmq 3 | compose=docker-compose -p $(project) 4 | 5 | #################################################################################################################### 6 | # APP COMMANDS 7 | #################################################################################################################### 8 | 9 | install: network remove build composer-install start 10 | 11 | build: 12 | @echo "== Build App ==" 13 | @$(compose) build 14 | 15 | start: 16 | @echo "== Start App ==" 17 | @$(compose) up -d haproxy 18 | 19 | network: 20 | @echo "== Create networks ==" 21 | @docker network create rmq_1_2 || true 22 | @docker network create rmq_2_3 || true 23 | @docker network create rmq_3_1 || true 24 | 25 | state: 26 | @echo "== Print state of containers ==" 27 | @$(compose) ps 28 | 29 | remove: stop 30 | @echo "== Remove containers ==" 31 | @$(compose) rm -f 32 | 33 | stop: 34 | @echo "== Stop containers ==" 35 | @$(compose) stop 36 | 37 | logs: 38 | @echo "== Show containers logs ==" 39 | @$(compose) logs -f 40 | 41 | bash: 42 | @echo "== Connect into PHP container ==" 43 | @$(compose) run --rm php bash 44 | 45 | console: 46 | @echo "== Console command ==" 47 | @$(compose) run --rm php bin/console $(cmd) 48 | 49 | 50 | #################################################################################################################### 51 | # RABBITMQ COMMANDS 52 | #################################################################################################################### 53 | 54 | init-sw: 55 | @echo "== Rabbit init ==" 56 | @$(compose) run --rm php vendor/bin/rabbit vhost:mapping:create vhost.yml --host=haproxy -u guest -p guest 57 | 58 | cluster-sw: 59 | @echo "== SWARROT Rabbit Clustering ==" 60 | @$(compose) exec rmq1 rabbitmqctl set_policy ha-swarrot "^swarrot" \ '{"ha-mode":"all","ha-sync-mode":"automatic"}' 61 | 62 | cluster-os: 63 | @echo "== SWARROT Rabbit Clustering ==" 64 | @$(compose) exec rmq1 rabbitmqctl set_policy ha-oldsound "^oldsound" \ '{"ha-mode":"all","ha-sync-mode":"automatic"}' 65 | 66 | stop-node-1: 67 | @echo "== Stop rabbitmq node 1 from cluster ==" 68 | @docker stop rmq_rmq1_1 69 | 70 | resume-node-1: 71 | @echo "== Stop rabbitmq node 1 from cluster ==" 72 | @docker start rmq_rmq1_1 73 | 74 | stop-node-2: 75 | @echo "== Stop rabbitmq node 2 from cluster ==" 76 | @docker stop rmq_rmq2_1 77 | 78 | resume-node-2: 79 | @echo "== Stop rabbitmq node 2 from cluster ==" 80 | @docker start rmq_rmq2_1 81 | 82 | stop-node-3: 83 | @echo "== Stop rabbitmq node 3 from cluster ==" 84 | @docker stop rmq_rmq3_1 85 | 86 | resume-node-3: 87 | @echo "== Stop rabbitmq node 3 from cluster ==" 88 | @docker start rmq_rmq3_1 89 | 90 | exclude-node-1: 91 | @echo "== Exclude rabbitmq node 1 from cluster ==" 92 | @docker network disconnect rmq_1_2 rmq_rmq2_1 93 | @docker network disconnect rmq_3_1 rmq_rmq3_1 94 | 95 | restore-node-1: 96 | @echo "== Exclude rabbit node 1 from cluster ==" 97 | @docker network connect rmq_1_2 rmq_rmq2_1 98 | @docker network connect rmq_3_1 rmq_rmq3_1 99 | 100 | add-more-nodes: 101 | @echo "== Adding a lot of nodes ==" 102 | @$(compose) scale rmqN=10 103 | 104 | # -------------------------------------------------------- 105 | # COMPOSER 106 | # -------------------------------------------------------- 107 | 108 | composer-install: 109 | @$(compose) run --rm composer bash -c '\ 110 | composer install --ignore-platform-reqs --no-interaction --prefer-dist $(deps)' 111 | 112 | composer-update: 113 | @$(compose) run --rm composer bash -c '\ 114 | composer update --ignore-platform-reqs --no-interaction --prefer-dist $(deps)' 115 | 116 | composer-require: 117 | @$(compose) run --rm composer bash -c '\ 118 | composer require --ignore-platform-reqs --no-interaction --prefer-dist $(deps)' 119 | 120 | 121 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Docker RabbitMQ HA Cluster 2 | 3 | :warning: This project **IS NOT** swarm compatible, sorry... but PR welcome :warning: 4 | 5 | [Read the documentation](#documentation) 6 | 7 | A docker stack to create, test and benchmark a rabbitmq cluster in high availability configuration: 8 | 9 | | Tool | Version | 10 | | -------------: |:-----| 11 | | RabbitMQ | v3.6.5 | 12 | | HAProxy | v1.6.3 | 13 | | PHP | v7.1 | 14 | | Docker | v1.12+ | 15 | | Docker-compose | v1.8+ | 16 | 17 | * HAProxy as a load balancer 18 | * N nodes cluster 19 | * **Durable**, **Mirrored** and **Persistent** Exchanges, Queues and Messages 20 | * HA custom policies 21 | * Parallel producers and consumers 22 | * **Node failures** and **network partition** experiment 23 | 24 | If you have questions, comments or suggestions please just create issues. 25 | 26 | :warning: Tested (works well) on Linux but bad performance on OSX (docker for MAC) 27 | 28 | ## The architecture 29 | 30 | ![Rabbit cluster](./img/rabbitmq.png) 31 | 32 | * **3 RabbitMQ nodes** but we can add a lot more. 33 | * **3 docker networks** to be able to simulate network partition. 34 | * **1 HAProxy node** to load balance request and to be "failure proof". 35 | * **1 default network** for the consumers and producers to connect with nodes through HAProxy. 36 | 37 | ## The stack 38 | 39 | A lot of great tools (thanks to all awesome authors) 40 | 41 | * Make 42 | * Docker and docker-compose 43 | * Rabbitmq and Management Plugin (docker) 44 | * [HAProxy](https://github.com/docker/dockercloud-haproxy) 45 | * Shell scripts 46 | * Symfony MicroFramework (producers and consumers in docker containers) 47 | * [swarrot](https://github.com/swarrot/swarrot) / [swarrot-bundle](https://github.com/swarrot/SwarrotBundle) 48 | * [php-amqplib/rabbitmq-bundle](https://github.com/php-amqplib/RabbitMqBundle) 49 | * [odolbeau/rabbit-mq-admin-toolkit](https://github.com/odolbeau/rabbit-mq-admin-toolkit) 50 | 51 | ## Tests / Benchmark 52 | 53 | With this stack you will be able to experiment: 54 | 55 | * Load Balancing 56 | * Node failure 57 | * Network partition 58 | * Messages persistency 59 | * Message NO ACK and retries 60 | 61 | # Documentation 62 | 63 | ## Setup / Start / Stop the cluster 64 | 65 | [Read the documentation for Setup / start / stop](./doc/SETUP.md) 66 | 67 | ## Swarrot/SwarrotBundle 68 | 69 | [Read the documentation for Swarrot/SwarrotBundle](./doc/SWARROT.md) 70 | 71 | ## php-amqplib/RabbitMqBundle 72 | 73 | [Read the documentation for php-amqplib/RabbitMqBundle](./doc/OLDSOUND.md) 74 | 75 | ## Tests/Benckmark 76 | 77 | ### Node failures 78 | 79 | [Read the documentation for node failures](./doc/FAILURE.md) 80 | 81 | ### Network partition 82 | 83 | [Read the documentation for network partition](./doc/PARTITION.md) 84 | 85 | ## Big cluster 86 | 87 | [Read the documentation for big cluster](./doc/BIG.md) 88 | 89 | ## TODO 90 | 91 | * Tests 92 | 93 | ## Resources 94 | 95 | * http://blog.eleven-labs.com/fr/publier-consommer-reessayer-des-messages-rabbitmq/ 96 | * https://odolbeau.fr/blog/benchmark-php-amqp-lib-amqp-extension-swarrot.html 97 | * https://github.com/docker/dockercloud-haproxy 98 | * https://github.com/bijukunjummen/docker-rabbitmq-cluster 99 | * https://www.rabbitmq.com/ha.html 100 | * https://www.rabbitmq.com/persistence-conf.html 101 | * https://github.com/php-amqplib/RabbitMqBundle 102 | * https://github.com/swarrot 103 | * http://symfony.com/doc/current/configuration/micro_kernel_trait.html 104 | * https://docs.docker.com/engine/userguide/networking/ 105 | * https://www.nginx.com/resources/admin-guide/tcp-load-balancing/ 106 | * https://github.com/alanxz/rabbitmq-c 107 | 108 | ## License 109 | 110 | The MIT License (MIT) 111 | 112 | Copyright (c) 2017 Yannick Pereira-Reis 113 | 114 | Permission is hereby granted, free of charge, to any person obtaining a copy 115 | of this software and associated documentation files (the "Software"), to deal 116 | in the Software without restriction, including without limitation the rights 117 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 118 | copies of the Software, and to permit persons to whom the Software is 119 | furnished to do so, subject to the following conditions: 120 | 121 | The above copyright notice and this permission notice shall be included in all 122 | copies or substantial portions of the Software. 123 | 124 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 125 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 126 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 127 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 128 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 129 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 130 | SOFTWARE. 131 | -------------------------------------------------------------------------------- /doc/BIG.md: -------------------------------------------------------------------------------- 1 | # Big cluster 2 | 3 | You can easily create a lot of nodes in your cluster. 4 | 5 | ``` 6 | make add-more-nodes 7 | ``` 8 | 9 | ![Rabbit cluster](./../img/big-cluster.png) 10 | 11 | 12 | [Go to Index](../README.md#documentation) 13 | 14 | [Setup](./SETUP.md) 15 | [Swarrot/SwarrotBundle](./SWARROT.md) 16 | [OldSound/RabbitMqBundle](./OLDSOUND.md) 17 | [Node failures](./FAILURE.md) 18 | [Network partition](./PARTITION.md) 19 | [Big cluster](./BIG.md) 20 | -------------------------------------------------------------------------------- /doc/FAILURE.md: -------------------------------------------------------------------------------- 1 | # Tests/Benckmark 2 | 3 | ## Node failures 4 | 5 | ### Stop the first node 6 | 7 | ``` 8 | $ make stop-node-1 9 | == Stop rabbitmq node 1 from cluster == 10 | rmq_rmq1_1 11 | ``` 12 | 13 | ![Rabbit cluster](./../img/rabbitmq-node1-stop.png) 14 | 15 | ### Stop the second node 16 | 17 | ``` 18 | $ make stop-node-2 19 | == Stop rabbitmq node 2 from cluster == 20 | rmq_rmq2_1 21 | ``` 22 | 23 | ![Rabbit cluster](./../img/rabbitmq-node2-stop.png) 24 | 25 | ### Restart the first node 26 | 27 | ``` 28 | $ make resume-node-1 29 | == Stop rabbitmq node 1 from cluster == 30 | rmq_rmq1_1 31 | ``` 32 | 33 | ![Rabbit cluster](./../img/rabbitmq-node1-restart.png) 34 | 35 | ### Restart all nodes 36 | 37 | ``` 38 | $ make start 39 | == Start App == 40 | rmq_rmq1_1 is up-to-date 41 | Starting rmq_rmq2_1 42 | Starting rmq_rmq3_1 43 | rmq_haproxy_1 is up-to-date 44 | ``` 45 | 46 | ![Rabbit cluster](./../img/rabbitmq-all-restart.png) 47 | 48 | [Go to Index](../README.md#documentation) 49 | 50 | [Setup](./SETUP.md) 51 | [Swarrot/SwarrotBundle](./SWARROT.md) 52 | [OldSound/RabbitMqBundle](./OLDSOUND.md) 53 | [Node failures](./FAILURE.md) 54 | [Network partition](./PARTITION.md) 55 | [Big cluster](./BIG.md) 56 | -------------------------------------------------------------------------------- /doc/OLDSOUND.md: -------------------------------------------------------------------------------- 1 | # php-amqplib/RabbitMqBundle 2 | 3 | * Of course at this step, you must have followed the [startup instructions](https://github.com/ypereirareis/docker-rabbitmq-ha-cluster/tree/refacto-doc#setup--start--stop-the-cluster). 4 | * **With RabbitMqBundle we use a PUSH strategy, consumers are registered in RabbitMQ** 5 | 6 | > With the "push API", applications have to indicate interest in consuming messages from a particular queue. When they do so, we say that they register a consumer or, simply put, subscribe to a queue. It is possible to have more than one consumer per queue or to register an exclusive consumer (excludes all other consumers from the queue while it is consuming). 7 | 8 | ## Set the ha-policy 9 | 10 | ```shell 11 | $ make cluster-os 12 | == SWARROT Rabbit Clustering == 13 | Setting policy "ha-oldsound" for pattern "^oldsound" to " {\"ha-mode\":\"all\",\"ha-sync-mode\":\"automatic\"}" with priority "0" ... 14 | ``` 15 | 16 | ![Rabbit cluster](./../img/rabbitmq-policy-oldsound.png) 17 | 18 | ## Consumers 19 | 20 | ```shell 21 | $ make bash 22 | == Connect into PHP container == 23 | IMPORTANT : Waiting for nothing because no env var defined !!! 24 | bash-4.3# ./consume.sh oldsound 25 | --------------------------------------------------- 26 | > Type: oldsound 27 | > Info: 30 consumers running in parallel reading 100 messages each before finishing 28 | --------------------------------------------------- 29 | 30 consumers running... 30 | ``` 31 | 32 | ![Rabbit cluster](./../img/rabbitmq-oldsound-consumers.png) 33 | 34 | ## Producers 35 | 36 | ```shell 37 | $ make bash 38 | == Connect into PHP container == 39 | IMPORTANT : Waiting for nothing because no env var defined !!! 40 | bash-4.3# ./produce.sh oldsound 41 | --------------------------------------------------- 42 | > Type: oldsound 43 | > Info: 10 producers running in parallel 44 | --------------------------------------------------- 45 | 10 producers running... 46 | Process 582: 100 more messages added 47 | Process 591: 100 more messages added 48 | ``` 49 | 50 | Once consumers and producers are started you should see messages in the Rabbitmq Management Plugin interface for all nodes. 51 | 52 | ![Rabbit cluster](./../img/rabbitmq-oldsound-run.png) 53 | 54 | [Go to Index](../README.md#documentation) 55 | 56 | [Setup](./SETUP.md) 57 | [Swarrot/SwarrotBundle](./SWARROT.md) 58 | [OldSound/RabbitMqBundle](./OLDSOUND.md) 59 | [Node failures](./FAILURE.md) 60 | [Network partition](./PARTITION.md) 61 | [Big cluster](./BIG.md) 62 | -------------------------------------------------------------------------------- /doc/PARTITION.md: -------------------------------------------------------------------------------- 1 | # Tests/Benckmark 2 | 3 | ## Network partition 4 | 5 | ![Rabbit cluster](./../img/rabbitmq_netpart.png) 6 | 7 | ### Exclude node 1 from the network cluster 8 | 9 | ``` 10 | $ make exclude-node-1 11 | == Exclude rabbitmq node 1 from cluster == 12 | ``` 13 | 14 | ### Restore node 1 in the network cluster 15 | 16 | ``` 17 | $ make restore-node-1 18 | == Exclude rabbit node 1 from cluster == 19 | ``` 20 | 21 | **Partition between node 1 and node 2 and 3...** 22 | 23 | ![Rabbit cluster](./../img/rabbit-netpart-1.png) 24 | 25 | 26 | ![Rabbit cluster](./../img/rabbit-netpart-2.png) 27 | 28 | **...but all nodes are still running** 29 | 30 | ![Rabbit cluster](./../img/rabbitmq-netpart-ctop.png) 31 | 32 | 33 | [https://www.rabbitmq.com/partitions.html](https://www.rabbitmq.com/partitions.html) 34 | 35 | [Go to Index](../README.md#documentation) 36 | 37 | [Setup](./SETUP.md) 38 | [Swarrot/SwarrotBundle](./SWARROT.md) 39 | [OldSound/RabbitMqBundle](./OLDSOUND.md) 40 | [Node failures](./FAILURE.md) 41 | [Network partition](./PARTITION.md) 42 | [Big cluster](./BIG.md) 43 | -------------------------------------------------------------------------------- /doc/SETUP.md: -------------------------------------------------------------------------------- 1 | # Setup / Start the RabbitMQ cluster 2 | 3 | ```shell 4 | git clone git@github.com:ypereirareis/docker-rabbitmq-ha-cluster.git && cd docker-rabbitmq-ha-cluster 5 | make install && make start 6 | ``` 7 | 8 | # Stop the RabbitMQ cluster 9 | 10 | ```shell 11 | make stop 12 | ``` 13 | 14 | :broken_heart: **Do not set container names manually or the auto configuration of HAProxy will not work anymore.** 15 | :green_heart: You can change the `docker-compose -p` option (project variable) in [Makefile](../Makefile), but you will need to update some `make` targets: 16 | 17 | * https://github.com/ypereirareis/docker-rabbitmq-ha-cluster/blob/master/Makefile#L19-L23 18 | * https://github.com/ypereirareis/docker-rabbitmq-ha-cluster/blob/master/Makefile#L66-L98 19 | 20 | Once the setup process is over, check everything is ok (sometimes the startup process fails): 21 | 22 | ``` 23 | make stop && make start # To restart the cluster properly 24 | ``` 25 | 26 | ```shell 27 | $ make state 28 | == Print state of containers == 29 | Name Command State Ports 30 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 31 | rmq_haproxy_1 /sbin/tini -- dockercloud- ... Up 1936/tcp, 443/tcp, 0.0.0.0:5672->5672/tcp, 0.0.0.0:80->80/tcp 32 | rmq_rmq1_1 /pre-entrypoint.sh rabbitm ... Up 127.0.0.1:1234->15672/tcp, 25672/tcp, 4369/tcp, 5672/tcp, 9100/tcp, 9101/tcp, 9102/tcp, 9103/tcp, 9104/tcp, 9105/tcp 33 | rmq_rmq2_1 /pre-entrypoint.sh rabbitm ... Up 127.0.0.1:1235->15672/tcp, 25672/tcp, 4369/tcp, 5672/tcp, 9100/tcp, 9101/tcp, 9102/tcp, 9103/tcp, 9104/tcp, 9105/tcp 34 | rmq_rmq3_1 /pre-entrypoint.sh rabbitm ... Up 127.0.0.1:1236->15672/tcp, 25672/tcp, 4369/tcp, 5672/tcp, 9100/tcp, 9101/tcp, 9102/tcp, 9103/tcp, 9104/tcp, 9105/tcp 35 | ``` 36 | 37 | ![Rabbit cluster](./../img/ctop_start.png) 38 | 39 | Access the Management Plugin interface for nodes: 40 | 41 | * http://127.0.0.1:1234 42 | * http://127.0.0.1:1235 43 | * http://127.0.0.1:1236 44 | 45 | ![Rabbit cluster](./../img/rabbitmq_cluster_start.png) 46 | 47 | 48 | [Go to Index](../README.md#documentation) 49 | 50 | [Setup](./SETUP.md) 51 | [Swarrot/SwarrotBundle](./SWARROT.md) 52 | [OldSound/RabbitMqBundle](./OLDSOUND.md) 53 | [Node failures](./FAILURE.md) 54 | [Network partition](./PARTITION.md) 55 | [Big cluster](./BIG.md) 56 | -------------------------------------------------------------------------------- /doc/SWARROT.md: -------------------------------------------------------------------------------- 1 | # Swarrot/SwarrotBundle 2 | 3 | * Of course at this step, you must have followed the [startup instructions](https://github.com/ypereirareis/docker-rabbitmq-ha-cluster/tree/refacto-doc#setup--start--stop-the-cluster). 4 | * Check this blog post: http://blog.eleven-labs.com/fr/publier-consommer-reessayer-des-messages-rabbitmq/ 5 | * **With Swarrot we use a PULL/POLL strategy, consumers are not registered in RabbitMQ** 6 | 7 | ## Set the ha-policy 8 | 9 | ```shell 10 | $ make cluster-sw 11 | == SWARROT Rabbit Clustering == 12 | Setting policy "ha-swarrot" for pattern "^swarrot" to " {\"ha-mode\":\"all\",\"ha-sync-mode\":\"automatic\"}" with priority "0" ... 13 | ``` 14 | 15 | ![Rabbit cluster](./../img/rabbitmq-policy-swarrot.png) 16 | 17 | ## Exchanges/Queues 18 | 19 | With Swarrot, exchanges and queues are not created by the library or the bundle. 20 | YOu need to create everything manually or with command line. 21 | 22 | ```shell 23 | $ make init-sw 24 | == Rabbit init == 25 | IMPORTANT : Waiting for nothing because no env var defined !!! 26 | With DL: false 27 | With Unroutable: false 28 | Create exchange swarrot 29 | Create exchange dl 30 | Create queue swarrot 31 | Create queue swarrot_dl 32 | Create binding between exchange dl and queue swarrot_dl (with routing_key: swarrot) 33 | Create exchange retry 34 | Create queue swarrot_retry_1 35 | Create binding between exchange retry and queue swarrot_retry_1 (with routing_key: swarrot_retry_1) 36 | Create binding between exchange retry and queue swarrot (with routing_key: swarrot) 37 | Create exchange retry 38 | Create queue swarrot_retry_2 39 | Create binding between exchange retry and queue swarrot_retry_2 (with routing_key: swarrot_retry_2) 40 | Create binding between exchange retry and queue swarrot (with routing_key: swarrot) 41 | Create exchange retry 42 | Create queue swarrot_retry_3 43 | Create binding between exchange retry and queue swarrot_retry_3 (with routing_key: swarrot_retry_3) 44 | Create binding between exchange retry and queue swarrot (with routing_key: swarrot) 45 | Create binding between exchange swarrot and queue swarrot (with routing_key: swarrot) 46 | ``` 47 | 48 | ![Rabbit cluster](./../img/rabbitmq-swarrot-ex-q.png) 49 | 50 | 51 | ## Consumers 52 | 53 | ```shell 54 | $ make bash 55 | == Connect into PHP container == 56 | IMPORTANT : Waiting for nothing because no env var defined !!! 57 | bash-4.3# ./consume.sh 58 | --------------------------------------------------- 59 | > Type: swarrot 60 | > Info: 30 consumers running in parallel reading 100 messages each before finishing 61 | --------------------------------------------------- 62 | 30 consumers running... 63 | ``` 64 | 65 | ## Producers 66 | 67 | ```shell 68 | $ make bash 69 | == Connect into PHP container == 70 | IMPORTANT : Waiting for nothing because no env var defined !!! 71 | bash-4.3# ./produce.sh 72 | --------------------------------------------------- 73 | > Type: swarrot 74 | > Info: 10 producers running in parallel 75 | --------------------------------------------------- 76 | 10 producers running... 77 | Process 10: 100 more messages added 78 | Process 20: 100 more messages added 79 | ``` 80 | 81 | Once consumers and producers are started you should see messages in the Rabbitmq Management Plugin interface for all nodes. 82 | 83 | ![Rabbit cluster](./../img/rabbitmq-swarrot-run.png) 84 | 85 | ## Retry 86 | 87 | You must use a specific middleware configuration: 88 | 89 | ```yml 90 | middleware_stack: 91 | - configurator: swarrot.processor.exception_catcher 92 | - configurator: swarrot.processor.ack 93 | - configurator: swarrot.processor.retry 94 | extras: 95 | retry_exchange: 'retry' 96 | retry_attempts: 3 97 | retry_routing_key_pattern: 'swarrot_retry_%%attempt%%' 98 | ``` 99 | 100 | Then you need to throw an exception in the consumer (NO ACK): 101 | 102 | ```php 103 | public function process(Message $message, array $options) 104 | { 105 | throw new \Exception('NO ACK'); 106 | } 107 | ``` 108 | 109 | ![Rabbit cluster](./../img/retry-1.png) 110 | 111 | ![Rabbit cluster](./../img/retry-2.png) 112 | 113 | ![Rabbit cluster](./../img/retry-3.png) 114 | 115 | ![Rabbit cluster](./../img/retry-4.png) 116 | 117 | ![Rabbit cluster](./../img/retry-5.png) 118 | 119 | [Go to Index](../README.md#documentation) 120 | 121 | [Setup](./SETUP.md) 122 | [Swarrot/SwarrotBundle](./SWARROT.md) 123 | [OldSound/RabbitMqBundle](./OLDSOUND.md) 124 | [Node failures](./FAILURE.md) 125 | [Network partition](./PARTITION.md) 126 | [Big cluster](./BIG.md) 127 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: '2' 2 | services: 3 | 4 | composer: 5 | image: ypereirareis/composer:1.1.3-alpine 6 | working_dir: /src 7 | environment: 8 | COMPOSER_HOME: /tmp/.composer 9 | volumes: 10 | - ~/.composer:/tmp/.composer:rw 11 | - ./sf:/src:rw 12 | 13 | php: 14 | build: ./docker/php 15 | environment: 16 | SYMFONY_ENV: 17 | CUSTOM_UID: ${UID} 18 | volumes: 19 | - ./var/logs/app:/var/www/html/var/logs:rw 20 | - ./sf:/var/www/html:rw 21 | networks: 22 | - default 23 | 24 | rmq1: 25 | image: bijukunjummen/rabbitmq-server:3.6.5 26 | hostname: rmq1 27 | environment: 28 | ERLANG_COOKIE: 'ck8FC0uJ9vePIhLr' 29 | TCP_PORTS: "5672,15672" 30 | ports: 31 | - "127.0.0.1:1234:15672" 32 | networks: 33 | - rmq_1_2 34 | - rmq_3_1 35 | 36 | rmq2: 37 | image: bijukunjummen/rabbitmq-server:3.6.5 38 | hostname: rmq2 39 | environment: 40 | ERLANG_COOKIE: 'ck8FC0uJ9vePIhLr' 41 | CLUSTERED: 'true' 42 | CLUSTER_WITH: rmq1 43 | TCP_PORTS: "5672" 44 | ports: 45 | - "127.0.0.1:1235:15672" 46 | networks: 47 | - rmq_1_2 48 | - rmq_2_3 49 | 50 | rmq3: 51 | image: bijukunjummen/rabbitmq-server:3.6.5 52 | hostname: rmq3 53 | environment: 54 | ERLANG_COOKIE: 'ck8FC0uJ9vePIhLr' 55 | CLUSTERED: 'true' 56 | CLUSTER_WITH: rmq1 57 | TCP_PORTS: "5672" 58 | ports: 59 | - "127.0.0.1:1236:15672" 60 | networks: 61 | - rmq_3_1 62 | - rmq_2_3 63 | 64 | rmqN: 65 | image: bijukunjummen/rabbitmq-server:3.6.5 66 | environment: 67 | ERLANG_COOKIE: 'ck8FC0uJ9vePIhLr' 68 | CLUSTERED: 'true' 69 | CLUSTER_WITH: rmq1 70 | TCP_PORTS: "5672" 71 | networks: 72 | - rmq_3_1 73 | - rmq_2_3 74 | 75 | haproxy: 76 | image: dockercloud/haproxy:latest 77 | volumes: 78 | - /var/run/docker.sock:/var/run/docker.sock 79 | environment: 80 | MODE: tcp 81 | expose: 82 | - 5672 83 | links: 84 | - rmq1 85 | - rmq2 86 | - rmq3 87 | ports: 88 | - '80:80' 89 | - '5672:5672' 90 | networks: 91 | - default 92 | - rmq_1_2 93 | - rmq_2_3 94 | - rmq_3_1 95 | 96 | networks: 97 | rmq_1_2: 98 | external: 99 | name: rmq_1_2 100 | rmq_2_3: 101 | external: 102 | name: rmq_2_3 103 | rmq_3_1: 104 | external: 105 | name: rmq_3_1 106 | -------------------------------------------------------------------------------- /docker/php/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM zolweb/php7:2.2-alpine 2 | 3 | ENV RABBITMQ_C_VER 0.8.0 4 | 5 | RUN set -xe \ 6 | && apk add --update --no-cache \ 7 | wget \ 8 | cmake \ 9 | openssl-dev \ 10 | && rm -rf /var/cache/apk/* \ 11 | 12 | # RabbitMQ C client 13 | && wget -qO- https://github.com/alanxz/rabbitmq-c/releases/download/v${RABBITMQ_C_VER}/rabbitmq-c-${RABBITMQ_C_VER}.tar.gz | tar xz -C /tmp/ \ 14 | && cd /tmp/rabbitmq-c-${RABBITMQ_C_VER} \ 15 | && mkdir -p build \ 16 | && cd build \ 17 | && cmake .. \ 18 | -DCMAKE_INSTALL_PREFIX=/usr \ 19 | -DCMAKE_INSTALL_LIBDIR=lib \ 20 | -DCMAKE_C_FLAGS="$CFLAGS" \ 21 | && cmake --build . --target install \ 22 | && apk del \ 23 | wget \ 24 | cmake \ 25 | openssl-dev 26 | 27 | # Install tools... 28 | RUN set -x \ 29 | && docker-php-ext-install \ 30 | bcmath \ 31 | pcntl \ 32 | && pecl install \ 33 | amqp \ 34 | && docker-php-ext-enable amqp 35 | -------------------------------------------------------------------------------- /img/big-cluster.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ypereirareis/docker-rabbitmq-ha-cluster/60fd338704dcfd92548cb10f6079e1583571ca6d/img/big-cluster.png -------------------------------------------------------------------------------- /img/ctop_start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ypereirareis/docker-rabbitmq-ha-cluster/60fd338704dcfd92548cb10f6079e1583571ca6d/img/ctop_start.png -------------------------------------------------------------------------------- /img/rabbit-netpart-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ypereirareis/docker-rabbitmq-ha-cluster/60fd338704dcfd92548cb10f6079e1583571ca6d/img/rabbit-netpart-1.png -------------------------------------------------------------------------------- /img/rabbit-netpart-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ypereirareis/docker-rabbitmq-ha-cluster/60fd338704dcfd92548cb10f6079e1583571ca6d/img/rabbit-netpart-2.png -------------------------------------------------------------------------------- /img/rabbitmq-all-restart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ypereirareis/docker-rabbitmq-ha-cluster/60fd338704dcfd92548cb10f6079e1583571ca6d/img/rabbitmq-all-restart.png -------------------------------------------------------------------------------- /img/rabbitmq-ha-policy-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ypereirareis/docker-rabbitmq-ha-cluster/60fd338704dcfd92548cb10f6079e1583571ca6d/img/rabbitmq-ha-policy-2.png -------------------------------------------------------------------------------- /img/rabbitmq-netpart-ctop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ypereirareis/docker-rabbitmq-ha-cluster/60fd338704dcfd92548cb10f6079e1583571ca6d/img/rabbitmq-netpart-ctop.png -------------------------------------------------------------------------------- /img/rabbitmq-node1-restart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ypereirareis/docker-rabbitmq-ha-cluster/60fd338704dcfd92548cb10f6079e1583571ca6d/img/rabbitmq-node1-restart.png -------------------------------------------------------------------------------- /img/rabbitmq-node1-stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ypereirareis/docker-rabbitmq-ha-cluster/60fd338704dcfd92548cb10f6079e1583571ca6d/img/rabbitmq-node1-stop.png -------------------------------------------------------------------------------- /img/rabbitmq-node2-stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ypereirareis/docker-rabbitmq-ha-cluster/60fd338704dcfd92548cb10f6079e1583571ca6d/img/rabbitmq-node2-stop.png -------------------------------------------------------------------------------- /img/rabbitmq-node3-stop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ypereirareis/docker-rabbitmq-ha-cluster/60fd338704dcfd92548cb10f6079e1583571ca6d/img/rabbitmq-node3-stop.png -------------------------------------------------------------------------------- /img/rabbitmq-oldsound-consumers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ypereirareis/docker-rabbitmq-ha-cluster/60fd338704dcfd92548cb10f6079e1583571ca6d/img/rabbitmq-oldsound-consumers.png -------------------------------------------------------------------------------- /img/rabbitmq-oldsound-run.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ypereirareis/docker-rabbitmq-ha-cluster/60fd338704dcfd92548cb10f6079e1583571ca6d/img/rabbitmq-oldsound-run.png -------------------------------------------------------------------------------- /img/rabbitmq-policy-oldsound.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ypereirareis/docker-rabbitmq-ha-cluster/60fd338704dcfd92548cb10f6079e1583571ca6d/img/rabbitmq-policy-oldsound.png -------------------------------------------------------------------------------- /img/rabbitmq-policy-swarrot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ypereirareis/docker-rabbitmq-ha-cluster/60fd338704dcfd92548cb10f6079e1583571ca6d/img/rabbitmq-policy-swarrot.png -------------------------------------------------------------------------------- /img/rabbitmq-swarrot-ex-q.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ypereirareis/docker-rabbitmq-ha-cluster/60fd338704dcfd92548cb10f6079e1583571ca6d/img/rabbitmq-swarrot-ex-q.png -------------------------------------------------------------------------------- /img/rabbitmq-swarrot-run.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ypereirareis/docker-rabbitmq-ha-cluster/60fd338704dcfd92548cb10f6079e1583571ca6d/img/rabbitmq-swarrot-run.png -------------------------------------------------------------------------------- /img/rabbitmq.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ypereirareis/docker-rabbitmq-ha-cluster/60fd338704dcfd92548cb10f6079e1583571ca6d/img/rabbitmq.png -------------------------------------------------------------------------------- /img/rabbitmq_cluster_start.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ypereirareis/docker-rabbitmq-ha-cluster/60fd338704dcfd92548cb10f6079e1583571ca6d/img/rabbitmq_cluster_start.png -------------------------------------------------------------------------------- /img/rabbitmq_netpart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ypereirareis/docker-rabbitmq-ha-cluster/60fd338704dcfd92548cb10f6079e1583571ca6d/img/rabbitmq_netpart.png -------------------------------------------------------------------------------- /img/retry-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ypereirareis/docker-rabbitmq-ha-cluster/60fd338704dcfd92548cb10f6079e1583571ca6d/img/retry-1.png -------------------------------------------------------------------------------- /img/retry-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ypereirareis/docker-rabbitmq-ha-cluster/60fd338704dcfd92548cb10f6079e1583571ca6d/img/retry-2.png -------------------------------------------------------------------------------- /img/retry-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ypereirareis/docker-rabbitmq-ha-cluster/60fd338704dcfd92548cb10f6079e1583571ca6d/img/retry-3.png -------------------------------------------------------------------------------- /img/retry-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ypereirareis/docker-rabbitmq-ha-cluster/60fd338704dcfd92548cb10f6079e1583571ca6d/img/retry-4.png -------------------------------------------------------------------------------- /img/retry-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ypereirareis/docker-rabbitmq-ha-cluster/60fd338704dcfd92548cb10f6079e1583571ca6d/img/retry-5.png -------------------------------------------------------------------------------- /sf/app/AppKernel.php: -------------------------------------------------------------------------------- 1 | loadFromExtension('framework', array( 33 | 'secret' => 'S0ME_SECRET' 34 | )); 35 | 36 | $loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.yml'); 37 | $loader->load(__DIR__.'/config/services.yml'); 38 | } 39 | 40 | protected function configureRoutes(RouteCollectionBuilder $routes) 41 | { 42 | // kernel is a service that points to this class 43 | // optional 3rd argument is the route name 44 | $routes->add('/random/{limit}', 'kernel:randomAction'); 45 | } 46 | 47 | public function randomAction($limit) 48 | { 49 | return new JsonResponse(array( 50 | 'number' => rand(0, $limit) 51 | )); 52 | } 53 | 54 | public function getRootDir() 55 | { 56 | return __DIR__; 57 | } 58 | 59 | public function getCacheDir() 60 | { 61 | return dirname(__DIR__).'/var/cache/'.$this->environment; 62 | } 63 | 64 | public function getLogDir() 65 | { 66 | return dirname(__DIR__).'/var/logs'; 67 | } 68 | 69 | } -------------------------------------------------------------------------------- /sf/app/config/config.yml: -------------------------------------------------------------------------------- 1 | 2 | monolog: 3 | handlers: 4 | main: 5 | type: stream 6 | path: "%kernel.logs_dir%/%kernel.environment%.log" 7 | level: error 8 | 9 | swarrot: 10 | provider: pecl #amqp_lib 11 | default_connection: rabbitmq 12 | default_command: swarrot.command.base 13 | connections: 14 | rabbitmq: 15 | host: haproxy 16 | port: 5672 17 | login: guest 18 | password: guest 19 | vhost: '/' 20 | 21 | consumers: 22 | test_consume_quickly: # name of the consumer 23 | processor: processor.test_consume_quickly # name of the service 24 | extras: 25 | poll_interval: 500000 26 | requeue_on_error: false 27 | middleware_stack: 28 | - configurator: swarrot.processor.signal_handler 29 | - configurator: swarrot.processor.max_messages 30 | extras: 31 | max_messages: 100 32 | - configurator: swarrot.processor.max_execution_time 33 | extras: 34 | max_execution_time: 30 35 | - configurator: swarrot.processor.memory_limit 36 | extras: 37 | memory_limit: 50 38 | - configurator: swarrot.processor.exception_catcher 39 | - configurator: swarrot.processor.ack 40 | - configurator: swarrot.processor.retry 41 | extras: 42 | retry_exchange: 'retry' 43 | retry_attempts: 3 44 | retry_routing_key_pattern: 'swarrot_retry_%%attempt%%' 45 | 46 | messages_types: 47 | my_publisher_1: 48 | connection: rabbitmq 49 | exchange: swarrot 50 | routing_key: swarrot 51 | 52 | old_sound_rabbit_mq: 53 | connections: 54 | default: 55 | host: haproxy 56 | port: 5672 57 | user: 'guest' 58 | password: 'guest' 59 | vhost: '/' 60 | lazy: true 61 | connection_timeout: 3 62 | read_write_timeout: 3 63 | keepalive: false 64 | heartbeat: 0 65 | 66 | use_socket: false # default false 67 | # another: 68 | # # A different (unused) connection defined by an URL. One can omit all parts, 69 | # # except the scheme (amqp:). If both segment in the URL and a key value (see above) 70 | # # are given the value from the URL takes precedence. 71 | # # See https://www.rabbitmq.com/uri-spec.html on how to encode values. 72 | # url: 'amqp://guest:password@localhost:5672/vhost?lazy=1&connection_timeout=6' 73 | producers: 74 | oldsound: 75 | connection: default 76 | exchange_options: {name: 'oldsound', type: direct} 77 | service_alias: oldsound_producer 78 | 79 | consumers: 80 | oldsound: 81 | connection: default 82 | exchange_options: {name: 'oldsound', type: direct} 83 | queue_options: {name: 'oldsound', arguments: {'x-ha-policy': ['S', 'ha-oldsound']}} 84 | callback: oldsound_consumer 85 | -------------------------------------------------------------------------------- /sf/app/config/config_dev.yml: -------------------------------------------------------------------------------- 1 | imports: 2 | - { resource: config.yml } 3 | 4 | monolog: 5 | handlers: 6 | main: 7 | type: stream 8 | path: "%kernel.logs_dir%/%kernel.environment%.log" 9 | level: debug -------------------------------------------------------------------------------- /sf/app/config/config_prod.yml: -------------------------------------------------------------------------------- 1 | imports: 2 | - { resource: config.yml } 3 | 4 | monolog: 5 | handlers: 6 | main: 7 | type: stream 8 | path: "%kernel.logs_dir%/%kernel.environment%.log" 9 | level: warning -------------------------------------------------------------------------------- /sf/app/config/services.yml: -------------------------------------------------------------------------------- 1 | services: 2 | processor.test_consume_quickly: 3 | class: AppBundle\Processor\TestConsumeQuicklyProcessor 4 | 5 | oldsound_consumer: 6 | class: AppBundle\Processor\OldSoundProcessor 7 | -------------------------------------------------------------------------------- /sf/bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | getParameterOption(['--env', '-e'], getenv('SYMFONY_ENV') ?: 'dev'); 21 | $debug = getenv('SYMFONY_DEBUG') !== '0' && !$input->hasParameterOption(['--no-debug', '']) && $env !== 'prod'; 22 | 23 | if ($debug) { 24 | Debug::enable(); 25 | } 26 | 27 | $kernel = new AppKernel($env, $debug); 28 | $application = new Application($kernel); 29 | $application->run($input); 30 | -------------------------------------------------------------------------------- /sf/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "require": { 3 | "symfony/symfony": "^3.2", 4 | "symfony/console": "^3.2", 5 | "symfony/monolog-bundle": "^3.0", 6 | "swarrot/swarrot-bundle": "1.4.1", 7 | "odolbeau/rabbit-mq-admin-toolkit": "^3.2", 8 | "php-amqplib/rabbitmq-bundle": "^1.12" 9 | }, 10 | "autoload": { 11 | "psr-4": { 12 | "": "src/" 13 | }, 14 | "classmap": [ 15 | "app/AppKernel.php" 16 | ] 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /sf/composer.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_readme": [ 3 | "This file locks the dependencies of your project to a known state", 4 | "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", 5 | "This file is @generated automatically" 6 | ], 7 | "hash": "f49cb2f477b8cce8bddf137856d7a675", 8 | "content-hash": "668b9d4a9b1eda630ae8963fea07d09a", 9 | "packages": [ 10 | { 11 | "name": "doctrine/annotations", 12 | "version": "v1.4.0", 13 | "source": { 14 | "type": "git", 15 | "url": "https://github.com/doctrine/annotations.git", 16 | "reference": "54cacc9b81758b14e3ce750f205a393d52339e97" 17 | }, 18 | "dist": { 19 | "type": "zip", 20 | "url": "https://api.github.com/repos/doctrine/annotations/zipball/54cacc9b81758b14e3ce750f205a393d52339e97", 21 | "reference": "54cacc9b81758b14e3ce750f205a393d52339e97", 22 | "shasum": "" 23 | }, 24 | "require": { 25 | "doctrine/lexer": "1.*", 26 | "php": "^5.6 || ^7.0" 27 | }, 28 | "require-dev": { 29 | "doctrine/cache": "1.*", 30 | "phpunit/phpunit": "^5.7" 31 | }, 32 | "type": "library", 33 | "extra": { 34 | "branch-alias": { 35 | "dev-master": "1.4.x-dev" 36 | } 37 | }, 38 | "autoload": { 39 | "psr-4": { 40 | "Doctrine\\Common\\Annotations\\": "lib/Doctrine/Common/Annotations" 41 | } 42 | }, 43 | "notification-url": "https://packagist.org/downloads/", 44 | "license": [ 45 | "MIT" 46 | ], 47 | "authors": [ 48 | { 49 | "name": "Roman Borschel", 50 | "email": "roman@code-factory.org" 51 | }, 52 | { 53 | "name": "Benjamin Eberlei", 54 | "email": "kontakt@beberlei.de" 55 | }, 56 | { 57 | "name": "Guilherme Blanco", 58 | "email": "guilhermeblanco@gmail.com" 59 | }, 60 | { 61 | "name": "Jonathan Wage", 62 | "email": "jonwage@gmail.com" 63 | }, 64 | { 65 | "name": "Johannes Schmitt", 66 | "email": "schmittjoh@gmail.com" 67 | } 68 | ], 69 | "description": "Docblock Annotations Parser", 70 | "homepage": "http://www.doctrine-project.org", 71 | "keywords": [ 72 | "annotations", 73 | "docblock", 74 | "parser" 75 | ], 76 | "time": "2017-02-24 16:22:25" 77 | }, 78 | { 79 | "name": "doctrine/cache", 80 | "version": "v1.6.1", 81 | "source": { 82 | "type": "git", 83 | "url": "https://github.com/doctrine/cache.git", 84 | "reference": "b6f544a20f4807e81f7044d31e679ccbb1866dc3" 85 | }, 86 | "dist": { 87 | "type": "zip", 88 | "url": "https://api.github.com/repos/doctrine/cache/zipball/b6f544a20f4807e81f7044d31e679ccbb1866dc3", 89 | "reference": "b6f544a20f4807e81f7044d31e679ccbb1866dc3", 90 | "shasum": "" 91 | }, 92 | "require": { 93 | "php": "~5.5|~7.0" 94 | }, 95 | "conflict": { 96 | "doctrine/common": ">2.2,<2.4" 97 | }, 98 | "require-dev": { 99 | "phpunit/phpunit": "~4.8|~5.0", 100 | "predis/predis": "~1.0", 101 | "satooshi/php-coveralls": "~0.6" 102 | }, 103 | "type": "library", 104 | "extra": { 105 | "branch-alias": { 106 | "dev-master": "1.6.x-dev" 107 | } 108 | }, 109 | "autoload": { 110 | "psr-4": { 111 | "Doctrine\\Common\\Cache\\": "lib/Doctrine/Common/Cache" 112 | } 113 | }, 114 | "notification-url": "https://packagist.org/downloads/", 115 | "license": [ 116 | "MIT" 117 | ], 118 | "authors": [ 119 | { 120 | "name": "Roman Borschel", 121 | "email": "roman@code-factory.org" 122 | }, 123 | { 124 | "name": "Benjamin Eberlei", 125 | "email": "kontakt@beberlei.de" 126 | }, 127 | { 128 | "name": "Guilherme Blanco", 129 | "email": "guilhermeblanco@gmail.com" 130 | }, 131 | { 132 | "name": "Jonathan Wage", 133 | "email": "jonwage@gmail.com" 134 | }, 135 | { 136 | "name": "Johannes Schmitt", 137 | "email": "schmittjoh@gmail.com" 138 | } 139 | ], 140 | "description": "Caching library offering an object-oriented API for many cache backends", 141 | "homepage": "http://www.doctrine-project.org", 142 | "keywords": [ 143 | "cache", 144 | "caching" 145 | ], 146 | "time": "2016-10-29 11:16:17" 147 | }, 148 | { 149 | "name": "doctrine/collections", 150 | "version": "v1.4.0", 151 | "source": { 152 | "type": "git", 153 | "url": "https://github.com/doctrine/collections.git", 154 | "reference": "1a4fb7e902202c33cce8c55989b945612943c2ba" 155 | }, 156 | "dist": { 157 | "type": "zip", 158 | "url": "https://api.github.com/repos/doctrine/collections/zipball/1a4fb7e902202c33cce8c55989b945612943c2ba", 159 | "reference": "1a4fb7e902202c33cce8c55989b945612943c2ba", 160 | "shasum": "" 161 | }, 162 | "require": { 163 | "php": "^5.6 || ^7.0" 164 | }, 165 | "require-dev": { 166 | "doctrine/coding-standard": "~0.1@dev", 167 | "phpunit/phpunit": "^5.7" 168 | }, 169 | "type": "library", 170 | "extra": { 171 | "branch-alias": { 172 | "dev-master": "1.3.x-dev" 173 | } 174 | }, 175 | "autoload": { 176 | "psr-0": { 177 | "Doctrine\\Common\\Collections\\": "lib/" 178 | } 179 | }, 180 | "notification-url": "https://packagist.org/downloads/", 181 | "license": [ 182 | "MIT" 183 | ], 184 | "authors": [ 185 | { 186 | "name": "Roman Borschel", 187 | "email": "roman@code-factory.org" 188 | }, 189 | { 190 | "name": "Benjamin Eberlei", 191 | "email": "kontakt@beberlei.de" 192 | }, 193 | { 194 | "name": "Guilherme Blanco", 195 | "email": "guilhermeblanco@gmail.com" 196 | }, 197 | { 198 | "name": "Jonathan Wage", 199 | "email": "jonwage@gmail.com" 200 | }, 201 | { 202 | "name": "Johannes Schmitt", 203 | "email": "schmittjoh@gmail.com" 204 | } 205 | ], 206 | "description": "Collections Abstraction library", 207 | "homepage": "http://www.doctrine-project.org", 208 | "keywords": [ 209 | "array", 210 | "collections", 211 | "iterator" 212 | ], 213 | "time": "2017-01-03 10:49:41" 214 | }, 215 | { 216 | "name": "doctrine/common", 217 | "version": "v2.7.2", 218 | "source": { 219 | "type": "git", 220 | "url": "https://github.com/doctrine/common.git", 221 | "reference": "930297026c8009a567ac051fd545bf6124150347" 222 | }, 223 | "dist": { 224 | "type": "zip", 225 | "url": "https://api.github.com/repos/doctrine/common/zipball/930297026c8009a567ac051fd545bf6124150347", 226 | "reference": "930297026c8009a567ac051fd545bf6124150347", 227 | "shasum": "" 228 | }, 229 | "require": { 230 | "doctrine/annotations": "1.*", 231 | "doctrine/cache": "1.*", 232 | "doctrine/collections": "1.*", 233 | "doctrine/inflector": "1.*", 234 | "doctrine/lexer": "1.*", 235 | "php": "~5.6|~7.0" 236 | }, 237 | "require-dev": { 238 | "phpunit/phpunit": "^5.4.6" 239 | }, 240 | "type": "library", 241 | "extra": { 242 | "branch-alias": { 243 | "dev-master": "2.7.x-dev" 244 | } 245 | }, 246 | "autoload": { 247 | "psr-4": { 248 | "Doctrine\\Common\\": "lib/Doctrine/Common" 249 | } 250 | }, 251 | "notification-url": "https://packagist.org/downloads/", 252 | "license": [ 253 | "MIT" 254 | ], 255 | "authors": [ 256 | { 257 | "name": "Roman Borschel", 258 | "email": "roman@code-factory.org" 259 | }, 260 | { 261 | "name": "Benjamin Eberlei", 262 | "email": "kontakt@beberlei.de" 263 | }, 264 | { 265 | "name": "Guilherme Blanco", 266 | "email": "guilhermeblanco@gmail.com" 267 | }, 268 | { 269 | "name": "Jonathan Wage", 270 | "email": "jonwage@gmail.com" 271 | }, 272 | { 273 | "name": "Johannes Schmitt", 274 | "email": "schmittjoh@gmail.com" 275 | } 276 | ], 277 | "description": "Common Library for Doctrine projects", 278 | "homepage": "http://www.doctrine-project.org", 279 | "keywords": [ 280 | "annotations", 281 | "collections", 282 | "eventmanager", 283 | "persistence", 284 | "spl" 285 | ], 286 | "time": "2017-01-13 14:02:13" 287 | }, 288 | { 289 | "name": "doctrine/inflector", 290 | "version": "v1.1.0", 291 | "source": { 292 | "type": "git", 293 | "url": "https://github.com/doctrine/inflector.git", 294 | "reference": "90b2128806bfde671b6952ab8bea493942c1fdae" 295 | }, 296 | "dist": { 297 | "type": "zip", 298 | "url": "https://api.github.com/repos/doctrine/inflector/zipball/90b2128806bfde671b6952ab8bea493942c1fdae", 299 | "reference": "90b2128806bfde671b6952ab8bea493942c1fdae", 300 | "shasum": "" 301 | }, 302 | "require": { 303 | "php": ">=5.3.2" 304 | }, 305 | "require-dev": { 306 | "phpunit/phpunit": "4.*" 307 | }, 308 | "type": "library", 309 | "extra": { 310 | "branch-alias": { 311 | "dev-master": "1.1.x-dev" 312 | } 313 | }, 314 | "autoload": { 315 | "psr-0": { 316 | "Doctrine\\Common\\Inflector\\": "lib/" 317 | } 318 | }, 319 | "notification-url": "https://packagist.org/downloads/", 320 | "license": [ 321 | "MIT" 322 | ], 323 | "authors": [ 324 | { 325 | "name": "Roman Borschel", 326 | "email": "roman@code-factory.org" 327 | }, 328 | { 329 | "name": "Benjamin Eberlei", 330 | "email": "kontakt@beberlei.de" 331 | }, 332 | { 333 | "name": "Guilherme Blanco", 334 | "email": "guilhermeblanco@gmail.com" 335 | }, 336 | { 337 | "name": "Jonathan Wage", 338 | "email": "jonwage@gmail.com" 339 | }, 340 | { 341 | "name": "Johannes Schmitt", 342 | "email": "schmittjoh@gmail.com" 343 | } 344 | ], 345 | "description": "Common String Manipulations with regard to casing and singular/plural rules.", 346 | "homepage": "http://www.doctrine-project.org", 347 | "keywords": [ 348 | "inflection", 349 | "pluralize", 350 | "singularize", 351 | "string" 352 | ], 353 | "time": "2015-11-06 14:35:42" 354 | }, 355 | { 356 | "name": "doctrine/lexer", 357 | "version": "v1.0.1", 358 | "source": { 359 | "type": "git", 360 | "url": "https://github.com/doctrine/lexer.git", 361 | "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c" 362 | }, 363 | "dist": { 364 | "type": "zip", 365 | "url": "https://api.github.com/repos/doctrine/lexer/zipball/83893c552fd2045dd78aef794c31e694c37c0b8c", 366 | "reference": "83893c552fd2045dd78aef794c31e694c37c0b8c", 367 | "shasum": "" 368 | }, 369 | "require": { 370 | "php": ">=5.3.2" 371 | }, 372 | "type": "library", 373 | "extra": { 374 | "branch-alias": { 375 | "dev-master": "1.0.x-dev" 376 | } 377 | }, 378 | "autoload": { 379 | "psr-0": { 380 | "Doctrine\\Common\\Lexer\\": "lib/" 381 | } 382 | }, 383 | "notification-url": "https://packagist.org/downloads/", 384 | "license": [ 385 | "MIT" 386 | ], 387 | "authors": [ 388 | { 389 | "name": "Roman Borschel", 390 | "email": "roman@code-factory.org" 391 | }, 392 | { 393 | "name": "Guilherme Blanco", 394 | "email": "guilhermeblanco@gmail.com" 395 | }, 396 | { 397 | "name": "Johannes Schmitt", 398 | "email": "schmittjoh@gmail.com" 399 | } 400 | ], 401 | "description": "Base library for a lexer that can be used in Top-Down, Recursive Descent Parsers.", 402 | "homepage": "http://www.doctrine-project.org", 403 | "keywords": [ 404 | "lexer", 405 | "parser" 406 | ], 407 | "time": "2014-09-09 13:34:57" 408 | }, 409 | { 410 | "name": "monolog/monolog", 411 | "version": "1.22.1", 412 | "source": { 413 | "type": "git", 414 | "url": "https://github.com/Seldaek/monolog.git", 415 | "reference": "1e044bc4b34e91743943479f1be7a1d5eb93add0" 416 | }, 417 | "dist": { 418 | "type": "zip", 419 | "url": "https://api.github.com/repos/Seldaek/monolog/zipball/1e044bc4b34e91743943479f1be7a1d5eb93add0", 420 | "reference": "1e044bc4b34e91743943479f1be7a1d5eb93add0", 421 | "shasum": "" 422 | }, 423 | "require": { 424 | "php": ">=5.3.0", 425 | "psr/log": "~1.0" 426 | }, 427 | "provide": { 428 | "psr/log-implementation": "1.0.0" 429 | }, 430 | "require-dev": { 431 | "aws/aws-sdk-php": "^2.4.9 || ^3.0", 432 | "doctrine/couchdb": "~1.0@dev", 433 | "graylog2/gelf-php": "~1.0", 434 | "jakub-onderka/php-parallel-lint": "0.9", 435 | "php-amqplib/php-amqplib": "~2.4", 436 | "php-console/php-console": "^3.1.3", 437 | "phpunit/phpunit": "~4.5", 438 | "phpunit/phpunit-mock-objects": "2.3.0", 439 | "ruflin/elastica": ">=0.90 <3.0", 440 | "sentry/sentry": "^0.13", 441 | "swiftmailer/swiftmailer": "~5.3" 442 | }, 443 | "suggest": { 444 | "aws/aws-sdk-php": "Allow sending log messages to AWS services like DynamoDB", 445 | "doctrine/couchdb": "Allow sending log messages to a CouchDB server", 446 | "ext-amqp": "Allow sending log messages to an AMQP server (1.0+ required)", 447 | "ext-mongo": "Allow sending log messages to a MongoDB server", 448 | "graylog2/gelf-php": "Allow sending log messages to a GrayLog2 server", 449 | "mongodb/mongodb": "Allow sending log messages to a MongoDB server via PHP Driver", 450 | "php-amqplib/php-amqplib": "Allow sending log messages to an AMQP server using php-amqplib", 451 | "php-console/php-console": "Allow sending log messages to Google Chrome", 452 | "rollbar/rollbar": "Allow sending log messages to Rollbar", 453 | "ruflin/elastica": "Allow sending log messages to an Elastic Search server", 454 | "sentry/sentry": "Allow sending log messages to a Sentry server" 455 | }, 456 | "type": "library", 457 | "extra": { 458 | "branch-alias": { 459 | "dev-master": "2.0.x-dev" 460 | } 461 | }, 462 | "autoload": { 463 | "psr-4": { 464 | "Monolog\\": "src/Monolog" 465 | } 466 | }, 467 | "notification-url": "https://packagist.org/downloads/", 468 | "license": [ 469 | "MIT" 470 | ], 471 | "authors": [ 472 | { 473 | "name": "Jordi Boggiano", 474 | "email": "j.boggiano@seld.be", 475 | "homepage": "http://seld.be" 476 | } 477 | ], 478 | "description": "Sends your logs to files, sockets, inboxes, databases and various web services", 479 | "homepage": "http://github.com/Seldaek/monolog", 480 | "keywords": [ 481 | "log", 482 | "logging", 483 | "psr-3" 484 | ], 485 | "time": "2017-03-13 07:08:03" 486 | }, 487 | { 488 | "name": "odolbeau/rabbit-mq-admin-toolkit", 489 | "version": "v3.2.0", 490 | "source": { 491 | "type": "git", 492 | "url": "https://github.com/odolbeau/rabbit-mq-admin-toolkit.git", 493 | "reference": "ebb2416e64d448a47d43b3d9f1046b3d13e40702" 494 | }, 495 | "dist": { 496 | "type": "zip", 497 | "url": "https://api.github.com/repos/odolbeau/rabbit-mq-admin-toolkit/zipball/ebb2416e64d448a47d43b3d9f1046b3d13e40702", 498 | "reference": "ebb2416e64d448a47d43b3d9f1046b3d13e40702", 499 | "shasum": "" 500 | }, 501 | "require": { 502 | "php": ">=5.4", 503 | "swarrot/swarrot": "~2.0", 504 | "symfony/console": "^2.7|^3.0", 505 | "symfony/yaml": "^2.4|^3.0" 506 | }, 507 | "require-dev": { 508 | "friendsofphp/php-cs-fixer": "~1.12", 509 | "phpunit/phpunit": ">=4.8" 510 | }, 511 | "bin": [ 512 | "rabbit" 513 | ], 514 | "type": "library", 515 | "extra": { 516 | "branch-alias": { 517 | "dev-master": "3.3.x-dev" 518 | } 519 | }, 520 | "autoload": { 521 | "psr-0": { 522 | "Bab\\RabbitMq": "src" 523 | } 524 | }, 525 | "notification-url": "https://packagist.org/downloads/", 526 | "license": [ 527 | "MIT" 528 | ], 529 | "description": "RabbitMQ administration toolkit", 530 | "keywords": [ 531 | "AMQP", 532 | "admin", 533 | "rabbitmq", 534 | "toolkit" 535 | ], 536 | "time": "2016-11-15 16:29:18" 537 | }, 538 | { 539 | "name": "paragonie/random_compat", 540 | "version": "v2.0.10", 541 | "source": { 542 | "type": "git", 543 | "url": "https://github.com/paragonie/random_compat.git", 544 | "reference": "634bae8e911eefa89c1abfbf1b66da679ac8f54d" 545 | }, 546 | "dist": { 547 | "type": "zip", 548 | "url": "https://api.github.com/repos/paragonie/random_compat/zipball/634bae8e911eefa89c1abfbf1b66da679ac8f54d", 549 | "reference": "634bae8e911eefa89c1abfbf1b66da679ac8f54d", 550 | "shasum": "" 551 | }, 552 | "require": { 553 | "php": ">=5.2.0" 554 | }, 555 | "require-dev": { 556 | "phpunit/phpunit": "4.*|5.*" 557 | }, 558 | "suggest": { 559 | "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." 560 | }, 561 | "type": "library", 562 | "autoload": { 563 | "files": [ 564 | "lib/random.php" 565 | ] 566 | }, 567 | "notification-url": "https://packagist.org/downloads/", 568 | "license": [ 569 | "MIT" 570 | ], 571 | "authors": [ 572 | { 573 | "name": "Paragon Initiative Enterprises", 574 | "email": "security@paragonie.com", 575 | "homepage": "https://paragonie.com" 576 | } 577 | ], 578 | "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", 579 | "keywords": [ 580 | "csprng", 581 | "pseudorandom", 582 | "random" 583 | ], 584 | "time": "2017-03-13 16:27:32" 585 | }, 586 | { 587 | "name": "php-amqplib/php-amqplib", 588 | "version": "v2.6.3", 589 | "source": { 590 | "type": "git", 591 | "url": "https://github.com/php-amqplib/php-amqplib.git", 592 | "reference": "fa2f0d4410a11008cb36b379177291be7ee9e4f6" 593 | }, 594 | "dist": { 595 | "type": "zip", 596 | "url": "https://api.github.com/repos/php-amqplib/php-amqplib/zipball/fa2f0d4410a11008cb36b379177291be7ee9e4f6", 597 | "reference": "fa2f0d4410a11008cb36b379177291be7ee9e4f6", 598 | "shasum": "" 599 | }, 600 | "require": { 601 | "ext-bcmath": "*", 602 | "ext-mbstring": "*", 603 | "php": ">=5.3.0" 604 | }, 605 | "replace": { 606 | "videlalvaro/php-amqplib": "self.version" 607 | }, 608 | "require-dev": { 609 | "phpunit/phpunit": "^4.8", 610 | "scrutinizer/ocular": "^1.1", 611 | "squizlabs/php_codesniffer": "^2.5" 612 | }, 613 | "suggest": { 614 | "ext-sockets": "Use AMQPSocketConnection" 615 | }, 616 | "type": "library", 617 | "extra": { 618 | "branch-alias": { 619 | "dev-master": "2.7-dev" 620 | } 621 | }, 622 | "autoload": { 623 | "psr-4": { 624 | "PhpAmqpLib\\": "PhpAmqpLib/" 625 | } 626 | }, 627 | "notification-url": "https://packagist.org/downloads/", 628 | "license": [ 629 | "LGPL-2.1" 630 | ], 631 | "authors": [ 632 | { 633 | "name": "Alvaro Videla", 634 | "role": "Original Maintainer" 635 | }, 636 | { 637 | "name": "John Kelly", 638 | "email": "johnmkelly86@gmail.com", 639 | "role": "Maintainer" 640 | }, 641 | { 642 | "name": "Raúl Araya", 643 | "email": "nubeiro@gmail.com", 644 | "role": "Maintainer" 645 | } 646 | ], 647 | "description": "Formerly videlalvaro/php-amqplib. This library is a pure PHP implementation of the AMQP protocol. It's been tested against RabbitMQ.", 648 | "homepage": "https://github.com/php-amqplib/php-amqplib/", 649 | "keywords": [ 650 | "message", 651 | "queue", 652 | "rabbitmq" 653 | ], 654 | "time": "2016-04-11 14:30:01" 655 | }, 656 | { 657 | "name": "php-amqplib/rabbitmq-bundle", 658 | "version": "v1.12.0", 659 | "source": { 660 | "type": "git", 661 | "url": "https://github.com/php-amqplib/RabbitMqBundle.git", 662 | "reference": "0bb11edec0abdf6dc28eac0144c0a673dddba28f" 663 | }, 664 | "dist": { 665 | "type": "zip", 666 | "url": "https://api.github.com/repos/php-amqplib/RabbitMqBundle/zipball/0bb11edec0abdf6dc28eac0144c0a673dddba28f", 667 | "reference": "0bb11edec0abdf6dc28eac0144c0a673dddba28f", 668 | "shasum": "" 669 | }, 670 | "require": { 671 | "php": ">=5.3.0", 672 | "php-amqplib/php-amqplib": "~2.6", 673 | "psr/log": "~1.0", 674 | "symfony/config": "~2.3 || ~3.0", 675 | "symfony/console": "~2.3 || ~3.0", 676 | "symfony/dependency-injection": "~2.3 || ~3.0", 677 | "symfony/event-dispatcher": "~2.3 || ~3.0", 678 | "symfony/yaml": "~2.3 || ~3.0" 679 | }, 680 | "replace": { 681 | "oldsound/rabbitmq-bundle": "self.version" 682 | }, 683 | "require-dev": { 684 | "phpunit/phpunit": "~4.8 || ~5.0", 685 | "symfony/debug": "~2.3 || ~3.0", 686 | "symfony/serializer": "~2.3 || ~3.0" 687 | }, 688 | "suggest": { 689 | "symfony/framework-bundle": "To use this lib as a full Symfony Bundle and to use the profiler data collector" 690 | }, 691 | "type": "symfony-bundle", 692 | "extra": { 693 | "branch-alias": { 694 | "dev-master": "1.10.x-dev" 695 | } 696 | }, 697 | "autoload": { 698 | "psr-4": { 699 | "OldSound\\RabbitMqBundle\\": "" 700 | } 701 | }, 702 | "notification-url": "https://packagist.org/downloads/", 703 | "license": [ 704 | "MIT" 705 | ], 706 | "authors": [ 707 | { 708 | "name": "Alvaro Videla" 709 | } 710 | ], 711 | "description": "Integrates php-amqplib with Symfony2|3 and RabbitMq. Formerly oldsound/rabbitmq-bundle.", 712 | "keywords": [ 713 | "AMQP", 714 | "Symfony2", 715 | "message", 716 | "queue", 717 | "rabbitmq" 718 | ], 719 | "time": "2016-12-09 12:58:28" 720 | }, 721 | { 722 | "name": "psr/cache", 723 | "version": "1.0.1", 724 | "source": { 725 | "type": "git", 726 | "url": "https://github.com/php-fig/cache.git", 727 | "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8" 728 | }, 729 | "dist": { 730 | "type": "zip", 731 | "url": "https://api.github.com/repos/php-fig/cache/zipball/d11b50ad223250cf17b86e38383413f5a6764bf8", 732 | "reference": "d11b50ad223250cf17b86e38383413f5a6764bf8", 733 | "shasum": "" 734 | }, 735 | "require": { 736 | "php": ">=5.3.0" 737 | }, 738 | "type": "library", 739 | "extra": { 740 | "branch-alias": { 741 | "dev-master": "1.0.x-dev" 742 | } 743 | }, 744 | "autoload": { 745 | "psr-4": { 746 | "Psr\\Cache\\": "src/" 747 | } 748 | }, 749 | "notification-url": "https://packagist.org/downloads/", 750 | "license": [ 751 | "MIT" 752 | ], 753 | "authors": [ 754 | { 755 | "name": "PHP-FIG", 756 | "homepage": "http://www.php-fig.org/" 757 | } 758 | ], 759 | "description": "Common interface for caching libraries", 760 | "keywords": [ 761 | "cache", 762 | "psr", 763 | "psr-6" 764 | ], 765 | "time": "2016-08-06 20:24:11" 766 | }, 767 | { 768 | "name": "psr/log", 769 | "version": "1.0.2", 770 | "source": { 771 | "type": "git", 772 | "url": "https://github.com/php-fig/log.git", 773 | "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" 774 | }, 775 | "dist": { 776 | "type": "zip", 777 | "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", 778 | "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", 779 | "shasum": "" 780 | }, 781 | "require": { 782 | "php": ">=5.3.0" 783 | }, 784 | "type": "library", 785 | "extra": { 786 | "branch-alias": { 787 | "dev-master": "1.0.x-dev" 788 | } 789 | }, 790 | "autoload": { 791 | "psr-4": { 792 | "Psr\\Log\\": "Psr/Log/" 793 | } 794 | }, 795 | "notification-url": "https://packagist.org/downloads/", 796 | "license": [ 797 | "MIT" 798 | ], 799 | "authors": [ 800 | { 801 | "name": "PHP-FIG", 802 | "homepage": "http://www.php-fig.org/" 803 | } 804 | ], 805 | "description": "Common interface for logging libraries", 806 | "homepage": "https://github.com/php-fig/log", 807 | "keywords": [ 808 | "log", 809 | "psr", 810 | "psr-3" 811 | ], 812 | "time": "2016-10-10 12:19:37" 813 | }, 814 | { 815 | "name": "swarrot/swarrot", 816 | "version": "v2.3.0", 817 | "source": { 818 | "type": "git", 819 | "url": "https://github.com/swarrot/swarrot.git", 820 | "reference": "52d0ef764fdd0dc934cab1077822b6c3f08d8051" 821 | }, 822 | "dist": { 823 | "type": "zip", 824 | "url": "https://api.github.com/repos/swarrot/swarrot/zipball/52d0ef764fdd0dc934cab1077822b6c3f08d8051", 825 | "reference": "52d0ef764fdd0dc934cab1077822b6c3f08d8051", 826 | "shasum": "" 827 | }, 828 | "require": { 829 | "php": "^5.4 || ^7.0", 830 | "psr/log": "^1.0", 831 | "symfony/options-resolver": "^2.3 || ^3.0" 832 | }, 833 | "require-dev": { 834 | "aws/aws-sdk-php": "^2.8", 835 | "doctrine/common": "^2.3", 836 | "doctrine/dbal": "^2.2", 837 | "php-amqplib/php-amqplib": "^2.1", 838 | "phpunit/phpunit": "^4.8.27 || ^5.0" 839 | }, 840 | "suggest": { 841 | "aws/aws-sdk-php": "^2.8", 842 | "pecl-amqp": "*", 843 | "php-amqplib/php-amqplib": "^2.1", 844 | "symfony/console": "^2.4 || ^3.0" 845 | }, 846 | "type": "library", 847 | "extra": { 848 | "branch-alias": { 849 | "dev-master": "2.4.x-dev" 850 | } 851 | }, 852 | "autoload": { 853 | "psr-4": { 854 | "Swarrot\\": "src/Swarrot" 855 | } 856 | }, 857 | "notification-url": "https://packagist.org/downloads/", 858 | "license": [ 859 | "MIT" 860 | ], 861 | "authors": [ 862 | { 863 | "name": "Olivier Dolbeau", 864 | "homepage": "http://odolbeau.fr/" 865 | } 866 | ], 867 | "description": "A simple lib to consume RabbitMQ queues", 868 | "keywords": [ 869 | "AMQP", 870 | "queue", 871 | "swarrot", 872 | "worker" 873 | ], 874 | "time": "2016-12-28 14:53:53" 875 | }, 876 | { 877 | "name": "swarrot/swarrot-bundle", 878 | "version": "v1.4.1", 879 | "source": { 880 | "type": "git", 881 | "url": "https://github.com/swarrot/SwarrotBundle.git", 882 | "reference": "ab3021ab8e61c6a74771e6ad79c323981a632bec" 883 | }, 884 | "dist": { 885 | "type": "zip", 886 | "url": "https://api.github.com/repos/swarrot/SwarrotBundle/zipball/ab3021ab8e61c6a74771e6ad79c323981a632bec", 887 | "reference": "ab3021ab8e61c6a74771e6ad79c323981a632bec", 888 | "shasum": "" 889 | }, 890 | "require": { 891 | "php": ">=5.4", 892 | "psr/log": "~1.0", 893 | "swarrot/swarrot": "^2.1.1", 894 | "symfony/console": "~2.4|~3.0", 895 | "symfony/framework-bundle": "~2.4|~3.0" 896 | }, 897 | "require-dev": { 898 | "doctrine/common": "~2.2", 899 | "doctrine/dbal": "~2.2", 900 | "phpunit/phpunit": "~4.5", 901 | "symfony/phpunit-bridge": "~2.8|~3.0" 902 | }, 903 | "suggest": { 904 | "php-amqplib/php-amqplib": "Required if using amqp_lib" 905 | }, 906 | "type": "library", 907 | "extra": { 908 | "branch-alias": { 909 | "dev-master": "1.5-dev" 910 | } 911 | }, 912 | "autoload": { 913 | "psr-4": { 914 | "Swarrot\\SwarrotBundle\\": "" 915 | } 916 | }, 917 | "notification-url": "https://packagist.org/downloads/", 918 | "license": [ 919 | "MIT" 920 | ], 921 | "authors": [ 922 | { 923 | "name": "Olivier Dolbeau", 924 | "homepage": "http://odolbeau.fr/" 925 | } 926 | ], 927 | "description": "SwarrotBundle", 928 | "keywords": [ 929 | "bundle", 930 | "swarrot" 931 | ], 932 | "time": "2016-07-19 09:36:09" 933 | }, 934 | { 935 | "name": "symfony/monolog-bundle", 936 | "version": "v3.0.3", 937 | "source": { 938 | "type": "git", 939 | "url": "https://github.com/symfony/monolog-bundle.git", 940 | "reference": "ebce76a39a65495a66c34eb1574cc4b9e35a4e64" 941 | }, 942 | "dist": { 943 | "type": "zip", 944 | "url": "https://api.github.com/repos/symfony/monolog-bundle/zipball/ebce76a39a65495a66c34eb1574cc4b9e35a4e64", 945 | "reference": "ebce76a39a65495a66c34eb1574cc4b9e35a4e64", 946 | "shasum": "" 947 | }, 948 | "require": { 949 | "monolog/monolog": "~1.22", 950 | "php": ">=5.3.2", 951 | "symfony/config": "~2.7|~3.0", 952 | "symfony/dependency-injection": "~2.7|~3.0", 953 | "symfony/http-kernel": "~2.7|~3.0", 954 | "symfony/monolog-bridge": "~2.7|~3.0" 955 | }, 956 | "require-dev": { 957 | "phpunit/phpunit": "^4.8", 958 | "symfony/console": "~2.3|~3.0", 959 | "symfony/yaml": "~2.3|~3.0" 960 | }, 961 | "type": "symfony-bundle", 962 | "extra": { 963 | "branch-alias": { 964 | "dev-master": "3.x-dev" 965 | } 966 | }, 967 | "autoload": { 968 | "psr-4": { 969 | "Symfony\\Bundle\\MonologBundle\\": "" 970 | } 971 | }, 972 | "notification-url": "https://packagist.org/downloads/", 973 | "license": [ 974 | "MIT" 975 | ], 976 | "authors": [ 977 | { 978 | "name": "Symfony Community", 979 | "homepage": "http://symfony.com/contributors" 980 | }, 981 | { 982 | "name": "Fabien Potencier", 983 | "email": "fabien@symfony.com" 984 | } 985 | ], 986 | "description": "Symfony MonologBundle", 987 | "homepage": "http://symfony.com", 988 | "keywords": [ 989 | "log", 990 | "logging" 991 | ], 992 | "time": "2017-01-10 20:01:51" 993 | }, 994 | { 995 | "name": "symfony/polyfill-intl-icu", 996 | "version": "v1.3.0", 997 | "source": { 998 | "type": "git", 999 | "url": "https://github.com/symfony/polyfill-intl-icu.git", 1000 | "reference": "2d6e2b20d457603eefb6e614286c22efca30fdb4" 1001 | }, 1002 | "dist": { 1003 | "type": "zip", 1004 | "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/2d6e2b20d457603eefb6e614286c22efca30fdb4", 1005 | "reference": "2d6e2b20d457603eefb6e614286c22efca30fdb4", 1006 | "shasum": "" 1007 | }, 1008 | "require": { 1009 | "php": ">=5.3.3", 1010 | "symfony/intl": "~2.3|~3.0" 1011 | }, 1012 | "suggest": { 1013 | "ext-intl": "For best performance" 1014 | }, 1015 | "type": "library", 1016 | "extra": { 1017 | "branch-alias": { 1018 | "dev-master": "1.3-dev" 1019 | } 1020 | }, 1021 | "autoload": { 1022 | "files": [ 1023 | "bootstrap.php" 1024 | ] 1025 | }, 1026 | "notification-url": "https://packagist.org/downloads/", 1027 | "license": [ 1028 | "MIT" 1029 | ], 1030 | "authors": [ 1031 | { 1032 | "name": "Nicolas Grekas", 1033 | "email": "p@tchwork.com" 1034 | }, 1035 | { 1036 | "name": "Symfony Community", 1037 | "homepage": "https://symfony.com/contributors" 1038 | } 1039 | ], 1040 | "description": "Symfony polyfill for intl's ICU-related data and classes", 1041 | "homepage": "https://symfony.com", 1042 | "keywords": [ 1043 | "compatibility", 1044 | "icu", 1045 | "intl", 1046 | "polyfill", 1047 | "portable", 1048 | "shim" 1049 | ], 1050 | "time": "2016-11-14 01:06:16" 1051 | }, 1052 | { 1053 | "name": "symfony/polyfill-mbstring", 1054 | "version": "v1.3.0", 1055 | "source": { 1056 | "type": "git", 1057 | "url": "https://github.com/symfony/polyfill-mbstring.git", 1058 | "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4" 1059 | }, 1060 | "dist": { 1061 | "type": "zip", 1062 | "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/e79d363049d1c2128f133a2667e4f4190904f7f4", 1063 | "reference": "e79d363049d1c2128f133a2667e4f4190904f7f4", 1064 | "shasum": "" 1065 | }, 1066 | "require": { 1067 | "php": ">=5.3.3" 1068 | }, 1069 | "suggest": { 1070 | "ext-mbstring": "For best performance" 1071 | }, 1072 | "type": "library", 1073 | "extra": { 1074 | "branch-alias": { 1075 | "dev-master": "1.3-dev" 1076 | } 1077 | }, 1078 | "autoload": { 1079 | "psr-4": { 1080 | "Symfony\\Polyfill\\Mbstring\\": "" 1081 | }, 1082 | "files": [ 1083 | "bootstrap.php" 1084 | ] 1085 | }, 1086 | "notification-url": "https://packagist.org/downloads/", 1087 | "license": [ 1088 | "MIT" 1089 | ], 1090 | "authors": [ 1091 | { 1092 | "name": "Nicolas Grekas", 1093 | "email": "p@tchwork.com" 1094 | }, 1095 | { 1096 | "name": "Symfony Community", 1097 | "homepage": "https://symfony.com/contributors" 1098 | } 1099 | ], 1100 | "description": "Symfony polyfill for the Mbstring extension", 1101 | "homepage": "https://symfony.com", 1102 | "keywords": [ 1103 | "compatibility", 1104 | "mbstring", 1105 | "polyfill", 1106 | "portable", 1107 | "shim" 1108 | ], 1109 | "time": "2016-11-14 01:06:16" 1110 | }, 1111 | { 1112 | "name": "symfony/polyfill-php56", 1113 | "version": "v1.3.0", 1114 | "source": { 1115 | "type": "git", 1116 | "url": "https://github.com/symfony/polyfill-php56.git", 1117 | "reference": "1dd42b9b89556f18092f3d1ada22cb05ac85383c" 1118 | }, 1119 | "dist": { 1120 | "type": "zip", 1121 | "url": "https://api.github.com/repos/symfony/polyfill-php56/zipball/1dd42b9b89556f18092f3d1ada22cb05ac85383c", 1122 | "reference": "1dd42b9b89556f18092f3d1ada22cb05ac85383c", 1123 | "shasum": "" 1124 | }, 1125 | "require": { 1126 | "php": ">=5.3.3", 1127 | "symfony/polyfill-util": "~1.0" 1128 | }, 1129 | "type": "library", 1130 | "extra": { 1131 | "branch-alias": { 1132 | "dev-master": "1.3-dev" 1133 | } 1134 | }, 1135 | "autoload": { 1136 | "psr-4": { 1137 | "Symfony\\Polyfill\\Php56\\": "" 1138 | }, 1139 | "files": [ 1140 | "bootstrap.php" 1141 | ] 1142 | }, 1143 | "notification-url": "https://packagist.org/downloads/", 1144 | "license": [ 1145 | "MIT" 1146 | ], 1147 | "authors": [ 1148 | { 1149 | "name": "Nicolas Grekas", 1150 | "email": "p@tchwork.com" 1151 | }, 1152 | { 1153 | "name": "Symfony Community", 1154 | "homepage": "https://symfony.com/contributors" 1155 | } 1156 | ], 1157 | "description": "Symfony polyfill backporting some PHP 5.6+ features to lower PHP versions", 1158 | "homepage": "https://symfony.com", 1159 | "keywords": [ 1160 | "compatibility", 1161 | "polyfill", 1162 | "portable", 1163 | "shim" 1164 | ], 1165 | "time": "2016-11-14 01:06:16" 1166 | }, 1167 | { 1168 | "name": "symfony/polyfill-php70", 1169 | "version": "v1.3.0", 1170 | "source": { 1171 | "type": "git", 1172 | "url": "https://github.com/symfony/polyfill-php70.git", 1173 | "reference": "13ce343935f0f91ca89605a2f6ca6f5c2f3faac2" 1174 | }, 1175 | "dist": { 1176 | "type": "zip", 1177 | "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/13ce343935f0f91ca89605a2f6ca6f5c2f3faac2", 1178 | "reference": "13ce343935f0f91ca89605a2f6ca6f5c2f3faac2", 1179 | "shasum": "" 1180 | }, 1181 | "require": { 1182 | "paragonie/random_compat": "~1.0|~2.0", 1183 | "php": ">=5.3.3" 1184 | }, 1185 | "type": "library", 1186 | "extra": { 1187 | "branch-alias": { 1188 | "dev-master": "1.3-dev" 1189 | } 1190 | }, 1191 | "autoload": { 1192 | "psr-4": { 1193 | "Symfony\\Polyfill\\Php70\\": "" 1194 | }, 1195 | "files": [ 1196 | "bootstrap.php" 1197 | ], 1198 | "classmap": [ 1199 | "Resources/stubs" 1200 | ] 1201 | }, 1202 | "notification-url": "https://packagist.org/downloads/", 1203 | "license": [ 1204 | "MIT" 1205 | ], 1206 | "authors": [ 1207 | { 1208 | "name": "Nicolas Grekas", 1209 | "email": "p@tchwork.com" 1210 | }, 1211 | { 1212 | "name": "Symfony Community", 1213 | "homepage": "https://symfony.com/contributors" 1214 | } 1215 | ], 1216 | "description": "Symfony polyfill backporting some PHP 7.0+ features to lower PHP versions", 1217 | "homepage": "https://symfony.com", 1218 | "keywords": [ 1219 | "compatibility", 1220 | "polyfill", 1221 | "portable", 1222 | "shim" 1223 | ], 1224 | "time": "2016-11-14 01:06:16" 1225 | }, 1226 | { 1227 | "name": "symfony/polyfill-util", 1228 | "version": "v1.3.0", 1229 | "source": { 1230 | "type": "git", 1231 | "url": "https://github.com/symfony/polyfill-util.git", 1232 | "reference": "746bce0fca664ac0a575e465f65c6643faddf7fb" 1233 | }, 1234 | "dist": { 1235 | "type": "zip", 1236 | "url": "https://api.github.com/repos/symfony/polyfill-util/zipball/746bce0fca664ac0a575e465f65c6643faddf7fb", 1237 | "reference": "746bce0fca664ac0a575e465f65c6643faddf7fb", 1238 | "shasum": "" 1239 | }, 1240 | "require": { 1241 | "php": ">=5.3.3" 1242 | }, 1243 | "type": "library", 1244 | "extra": { 1245 | "branch-alias": { 1246 | "dev-master": "1.3-dev" 1247 | } 1248 | }, 1249 | "autoload": { 1250 | "psr-4": { 1251 | "Symfony\\Polyfill\\Util\\": "" 1252 | } 1253 | }, 1254 | "notification-url": "https://packagist.org/downloads/", 1255 | "license": [ 1256 | "MIT" 1257 | ], 1258 | "authors": [ 1259 | { 1260 | "name": "Nicolas Grekas", 1261 | "email": "p@tchwork.com" 1262 | }, 1263 | { 1264 | "name": "Symfony Community", 1265 | "homepage": "https://symfony.com/contributors" 1266 | } 1267 | ], 1268 | "description": "Symfony utilities for portability of PHP codes", 1269 | "homepage": "https://symfony.com", 1270 | "keywords": [ 1271 | "compat", 1272 | "compatibility", 1273 | "polyfill", 1274 | "shim" 1275 | ], 1276 | "time": "2016-11-14 01:06:16" 1277 | }, 1278 | { 1279 | "name": "symfony/symfony", 1280 | "version": "v3.2.6", 1281 | "source": { 1282 | "type": "git", 1283 | "url": "https://github.com/symfony/symfony.git", 1284 | "reference": "b0f8a7fa4b8baadf9db299cb6ac87c96a8977dbe" 1285 | }, 1286 | "dist": { 1287 | "type": "zip", 1288 | "url": "https://api.github.com/repos/symfony/symfony/zipball/b0f8a7fa4b8baadf9db299cb6ac87c96a8977dbe", 1289 | "reference": "b0f8a7fa4b8baadf9db299cb6ac87c96a8977dbe", 1290 | "shasum": "" 1291 | }, 1292 | "require": { 1293 | "doctrine/common": "~2.4", 1294 | "php": ">=5.5.9", 1295 | "psr/cache": "~1.0", 1296 | "psr/log": "~1.0", 1297 | "symfony/polyfill-intl-icu": "~1.0", 1298 | "symfony/polyfill-mbstring": "~1.0", 1299 | "symfony/polyfill-php56": "~1.0", 1300 | "symfony/polyfill-php70": "~1.0", 1301 | "symfony/polyfill-util": "~1.0", 1302 | "twig/twig": "~1.28|~2.0" 1303 | }, 1304 | "conflict": { 1305 | "phpdocumentor/reflection-docblock": "<3.0", 1306 | "phpdocumentor/type-resolver": "<0.2.0", 1307 | "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0" 1308 | }, 1309 | "provide": { 1310 | "psr/cache-implementation": "1.0" 1311 | }, 1312 | "replace": { 1313 | "symfony/asset": "self.version", 1314 | "symfony/browser-kit": "self.version", 1315 | "symfony/cache": "self.version", 1316 | "symfony/class-loader": "self.version", 1317 | "symfony/config": "self.version", 1318 | "symfony/console": "self.version", 1319 | "symfony/css-selector": "self.version", 1320 | "symfony/debug": "self.version", 1321 | "symfony/debug-bundle": "self.version", 1322 | "symfony/dependency-injection": "self.version", 1323 | "symfony/doctrine-bridge": "self.version", 1324 | "symfony/dom-crawler": "self.version", 1325 | "symfony/event-dispatcher": "self.version", 1326 | "symfony/expression-language": "self.version", 1327 | "symfony/filesystem": "self.version", 1328 | "symfony/finder": "self.version", 1329 | "symfony/form": "self.version", 1330 | "symfony/framework-bundle": "self.version", 1331 | "symfony/http-foundation": "self.version", 1332 | "symfony/http-kernel": "self.version", 1333 | "symfony/inflector": "self.version", 1334 | "symfony/intl": "self.version", 1335 | "symfony/ldap": "self.version", 1336 | "symfony/monolog-bridge": "self.version", 1337 | "symfony/options-resolver": "self.version", 1338 | "symfony/process": "self.version", 1339 | "symfony/property-access": "self.version", 1340 | "symfony/property-info": "self.version", 1341 | "symfony/proxy-manager-bridge": "self.version", 1342 | "symfony/routing": "self.version", 1343 | "symfony/security": "self.version", 1344 | "symfony/security-bundle": "self.version", 1345 | "symfony/security-core": "self.version", 1346 | "symfony/security-csrf": "self.version", 1347 | "symfony/security-guard": "self.version", 1348 | "symfony/security-http": "self.version", 1349 | "symfony/serializer": "self.version", 1350 | "symfony/stopwatch": "self.version", 1351 | "symfony/templating": "self.version", 1352 | "symfony/translation": "self.version", 1353 | "symfony/twig-bridge": "self.version", 1354 | "symfony/twig-bundle": "self.version", 1355 | "symfony/validator": "self.version", 1356 | "symfony/var-dumper": "self.version", 1357 | "symfony/web-profiler-bundle": "self.version", 1358 | "symfony/workflow": "self.version", 1359 | "symfony/yaml": "self.version" 1360 | }, 1361 | "require-dev": { 1362 | "cache/integration-tests": "dev-master", 1363 | "doctrine/cache": "~1.6", 1364 | "doctrine/data-fixtures": "1.0.*", 1365 | "doctrine/dbal": "~2.4", 1366 | "doctrine/doctrine-bundle": "~1.4", 1367 | "doctrine/orm": "~2.4,>=2.4.5", 1368 | "egulias/email-validator": "~1.2,>=1.2.8|~2.0", 1369 | "monolog/monolog": "~1.11", 1370 | "ocramius/proxy-manager": "~0.4|~1.0|~2.0", 1371 | "phpdocumentor/reflection-docblock": "^3.0", 1372 | "predis/predis": "~1.0", 1373 | "sensio/framework-extra-bundle": "^3.0.2", 1374 | "symfony/phpunit-bridge": "~3.2", 1375 | "symfony/polyfill-apcu": "~1.1", 1376 | "symfony/security-acl": "~2.8|~3.0" 1377 | }, 1378 | "type": "library", 1379 | "extra": { 1380 | "branch-alias": { 1381 | "dev-master": "3.2-dev" 1382 | } 1383 | }, 1384 | "autoload": { 1385 | "psr-4": { 1386 | "Symfony\\Bridge\\Doctrine\\": "src/Symfony/Bridge/Doctrine/", 1387 | "Symfony\\Bridge\\Monolog\\": "src/Symfony/Bridge/Monolog/", 1388 | "Symfony\\Bridge\\ProxyManager\\": "src/Symfony/Bridge/ProxyManager/", 1389 | "Symfony\\Bridge\\Swiftmailer\\": "src/Symfony/Bridge/Swiftmailer/", 1390 | "Symfony\\Bridge\\Twig\\": "src/Symfony/Bridge/Twig/", 1391 | "Symfony\\Bundle\\": "src/Symfony/Bundle/", 1392 | "Symfony\\Component\\": "src/Symfony/Component/" 1393 | }, 1394 | "classmap": [ 1395 | "src/Symfony/Component/Intl/Resources/stubs" 1396 | ], 1397 | "exclude-from-classmap": [ 1398 | "**/Tests/" 1399 | ] 1400 | }, 1401 | "notification-url": "https://packagist.org/downloads/", 1402 | "license": [ 1403 | "MIT" 1404 | ], 1405 | "authors": [ 1406 | { 1407 | "name": "Fabien Potencier", 1408 | "email": "fabien@symfony.com" 1409 | }, 1410 | { 1411 | "name": "Symfony Community", 1412 | "homepage": "https://symfony.com/contributors" 1413 | } 1414 | ], 1415 | "description": "The Symfony PHP framework", 1416 | "homepage": "https://symfony.com", 1417 | "keywords": [ 1418 | "framework" 1419 | ], 1420 | "time": "2017-03-10 18:35:48" 1421 | }, 1422 | { 1423 | "name": "twig/twig", 1424 | "version": "v2.2.0", 1425 | "source": { 1426 | "type": "git", 1427 | "url": "https://github.com/twigphp/Twig.git", 1428 | "reference": "29bb02dde09ff56291d30f7687eb8696918023af" 1429 | }, 1430 | "dist": { 1431 | "type": "zip", 1432 | "url": "https://api.github.com/repos/twigphp/Twig/zipball/29bb02dde09ff56291d30f7687eb8696918023af", 1433 | "reference": "29bb02dde09ff56291d30f7687eb8696918023af", 1434 | "shasum": "" 1435 | }, 1436 | "require": { 1437 | "php": "^7.0", 1438 | "symfony/polyfill-mbstring": "~1.0" 1439 | }, 1440 | "require-dev": { 1441 | "psr/container": "^1.0", 1442 | "symfony/debug": "~2.7", 1443 | "symfony/phpunit-bridge": "~3.2" 1444 | }, 1445 | "type": "library", 1446 | "extra": { 1447 | "branch-alias": { 1448 | "dev-master": "2.2-dev" 1449 | } 1450 | }, 1451 | "autoload": { 1452 | "psr-0": { 1453 | "Twig_": "lib/" 1454 | } 1455 | }, 1456 | "notification-url": "https://packagist.org/downloads/", 1457 | "license": [ 1458 | "BSD-3-Clause" 1459 | ], 1460 | "authors": [ 1461 | { 1462 | "name": "Fabien Potencier", 1463 | "email": "fabien@symfony.com", 1464 | "homepage": "http://fabien.potencier.org", 1465 | "role": "Lead Developer" 1466 | }, 1467 | { 1468 | "name": "Armin Ronacher", 1469 | "email": "armin.ronacher@active-4.com", 1470 | "role": "Project Founder" 1471 | }, 1472 | { 1473 | "name": "Twig Team", 1474 | "homepage": "http://twig.sensiolabs.org/contributors", 1475 | "role": "Contributors" 1476 | } 1477 | ], 1478 | "description": "Twig, the flexible, fast, and secure template language for PHP", 1479 | "homepage": "http://twig.sensiolabs.org", 1480 | "keywords": [ 1481 | "templating" 1482 | ], 1483 | "time": "2017-02-27 00:16:20" 1484 | } 1485 | ], 1486 | "packages-dev": [], 1487 | "aliases": [], 1488 | "minimum-stability": "stable", 1489 | "stability-flags": [], 1490 | "prefer-stable": false, 1491 | "prefer-lowest": false, 1492 | "platform": [], 1493 | "platform-dev": [] 1494 | } 1495 | -------------------------------------------------------------------------------- /sf/consume.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | TYPE=$1 5 | TYPE=${TYPE:-swarrot} 6 | 7 | echo "---------------------------------------------------" 8 | echo "> Type: $TYPE" 9 | echo "> Info: 30 consumers running in parallel reading 100 messages each before finishing" 10 | echo "---------------------------------------------------" 11 | echo "30 consumers running..." 12 | 13 | 14 | while true 15 | do 16 | for i in {1..10} 17 | do 18 | 19 | if [ "$TYPE" = "oldsound" ] 20 | then 21 | { bin/console rabbitmq:consumer oldsound -m 100; } & 22 | { bin/console rabbitmq:consumer oldsound -m 100; } & 23 | { bin/console rabbitmq:consumer oldsound -m 100; } & 24 | else 25 | { bin/console swarrot:consume:test_consume_quickly swarrot rabbitmq; } & 26 | { bin/console swarrot:consume:test_consume_quickly swarrot rabbitmq; } & 27 | { bin/console swarrot:consume:test_consume_quickly swarrot rabbitmq; } & 28 | fi 29 | 30 | usleep 100000 31 | done 32 | wait 33 | echo "30 new consumers running..." 34 | done 35 | -------------------------------------------------------------------------------- /sf/index.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | INDEX_NAME=$1 5 | [ -z $INDEX_NAME ] && echo "ERROR - You must define INDEX_NAME as first parameter !!!" && exit 1; 6 | 7 | LOOP_ITERATION=$2 8 | [ -z $LOOP_ITERATION ] && echo "ERROR - You must define LOOP_ITERATION as second parameter !!!" && exit 1; 9 | 10 | 11 | echo "Indexation into '${INDEX_NAME}' with '${LOOP_ITERATION}' iterations" 12 | 13 | for j in $(eval echo "{1..$LOOP_ITERATION}") 14 | do 15 | 16 | for i in {1..10} 17 | do 18 | { bin/console sirene:index:index "${INDEX_NAME}" -e prod --no-debug; } & # Index 100 000 element 19 | sleep 1 20 | done 21 | wait 22 | 23 | echo "[ $j, $i ] 100 000 Finished !!" 24 | sleep 1 25 | done 26 | 27 | echo "All Finished !!" -------------------------------------------------------------------------------- /sf/produce.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | TYPE=$1 5 | TYPE=${TYPE:-swarrot} 6 | 7 | echo "---------------------------------------------------" 8 | echo "> Type: $TYPE" 9 | echo "> Info: 10 producers running in parallel" 10 | echo "---------------------------------------------------" 11 | echo "10 producers running..." 12 | 13 | 14 | while true 15 | do 16 | for i in {1..10} 17 | do 18 | if [ "$TYPE" == "oldsound" ] 19 | then 20 | { bin/console rb:oldsound; } & 21 | else 22 | { bin/console rb:test; } & 23 | fi 24 | usleep 100000 25 | done 26 | wait 27 | echo "10 new producers running..." 28 | done 29 | -------------------------------------------------------------------------------- /sf/src/AppBundle/AppBundle.php: -------------------------------------------------------------------------------- 1 | setName('rb:oldsound_produce'); 29 | } 30 | 31 | 32 | /** 33 | * {@inheritdoc} 34 | */ 35 | protected function execute(InputInterface $input, OutputInterface $output) 36 | { 37 | 38 | $io = new SymfonyStyle($input, $output); 39 | 40 | $messagePublisher = $this->getContainer() 41 | ->get('old_sound_rabbit_mq.oldsound_producer'); 42 | $messagePublisher->setContentType('application/json'); 43 | $messagePublisher->setDeliveryMode(AMQPMessage::DELIVERY_MODE_PERSISTENT); 44 | 45 | $i = 0; 46 | $bulk = 100; 47 | $connectionRetry = 0; 48 | $exceptionRetry = 0; 49 | while(true) { 50 | try { 51 | $messagePublisher->publish(serialize("My first message with the awesome swarrot lib :)")); 52 | } catch (\AMQPConnectionException $ex) { 53 | if ($connectionRetry++ < 5) { 54 | $io->note('Trying to reconnect => '.$connectionRetry); 55 | sleep(2); 56 | continue; 57 | } 58 | $io->warning("Exit with error: ".$ex->getMessage()); 59 | break; 60 | } catch (\Exception $exception) { 61 | if ($exceptionRetry++ < 5) { 62 | $io->note('Skipping exception => '.$exceptionRetry); 63 | sleep(2); 64 | continue; 65 | } 66 | $io->warning("Exit with error: ".$exception->getMessage()); 67 | break; 68 | } 69 | 70 | usleep(10000); 71 | ++$i; 72 | if ($i === $bulk) { 73 | $io->writeln('Process ' .getmypid() . ': '.$bulk.' more messages added'); 74 | break; 75 | } 76 | } 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /sf/src/AppBundle/Command/TestCommand.php: -------------------------------------------------------------------------------- 1 | setName('rb:test'); 28 | } 29 | 30 | 31 | /** 32 | * {@inheritdoc} 33 | */ 34 | protected function execute(InputInterface $input, OutputInterface $output) 35 | { 36 | 37 | $io = new SymfonyStyle($input, $output); 38 | 39 | $message = new Message('"My first message with the awesome swarrot lib :)"', ['delivery_mode' => 2]); 40 | $messagePublisher = $this->getContainer()->get('swarrot.publisher'); 41 | 42 | $i = 0; 43 | $bulk = 100; 44 | $connectionRetry = 0; 45 | $exceptionRetry = 0; 46 | while(true) { 47 | try { 48 | $publisherString = 'my_publisher_1'; 49 | $messagePublisher->publish($publisherString, $message); 50 | } catch (\AMQPConnectionException $ex) { 51 | if ($connectionRetry++ < 5) { 52 | $io->note('Trying to reconnect => '.$connectionRetry); 53 | sleep(2); 54 | continue; 55 | } 56 | $io->warning("Exit with error: ".$ex->getMessage()); 57 | break; 58 | } catch (\Exception $exception) { 59 | if ($exceptionRetry++ < 5) { 60 | $io->note('Skipping exception => '.$exceptionRetry); 61 | sleep(2); 62 | continue; 63 | } 64 | $io->warning("Exit with error: ".$exception->getMessage()); 65 | break; 66 | } 67 | 68 | usleep(10000); 69 | ++$i; 70 | if ($i === $bulk) { 71 | $io->writeln('Process ' .getmypid() . ': '.$bulk.' more messages added'); 72 | break; 73 | } 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /sf/src/AppBundle/Processor/OldSoundProcessor.php: -------------------------------------------------------------------------------- 1 | getBody()."\n"; 12 | // throw new \Exception('NO ACK'); 13 | } 14 | } -------------------------------------------------------------------------------- /sf/vhost.yml: -------------------------------------------------------------------------------- 1 | # default_vhost.yml 2 | '/': 3 | parameters: 4 | with_dl: false # If true, all queues will have a dl and the corresponding mapping with the exchange "dl" 5 | with_unroutable: false # If true, all exchange will be declared with an unroutable config 6 | 7 | exchanges: 8 | swarrot: 9 | type: direct 10 | durable: true 11 | queues: 12 | swarrot: 13 | durable: true 14 | retries: [5, 10, 30] 15 | bindings: 16 | - exchange: swarrot 17 | routing_key: swarrot --------------------------------------------------------------------------------