rabbitmq-bundle - symfony3 - how to configure a topic exchange and queues? - symfony

I can't find a great configuration for old sound rabbitmq bundle to deal with topics and wildcard.
All I want is a unique exchange that post to multiple queue using wildcard.
Let says for example, i have my exchange name user.update, and i want to post the same message on user.update.address, user.update.profile for a microservice strategy.
do you know how to configure in the configuration file ?
Thx for reading.

Just because you are looking for
... great configuration for old sound rabbitmq bundle ...
visit http://www.inanzzz.com/ and search for "rabbitmq" which will give you what you wish for.
To address your question, you can use config below (I haven't tested it but it should be fine). However, you still need to write whole functionality/classes/consumers/producers etc. so follow this example: RabbitMQ topic example with symfony including 1 Producer & 1 Exchange & 2 Queue & N Worker & 2 Consumer
old_sound_rabbit_mq:
connections:
default:
host: %rabbitmq.host%
port: %rabbitmq.port%
user: %rabbitmq.user%
password: %rabbitmq.pswd%
vhost: /
lazy: true
producers:
user_update_producer:
connection: default
exchange_options: { name: user.update, type: topic }
consumers:
user_update_consumer:
connection: default
exchange_options: { name: user.update, type: topic }
queue_options:
name: user_update_queue
routing_keys:
- 'user.update.address'
- 'user.update.profile'
callback: your_application.consumer.user_update_consumer
It's flow: user.update (P) -> user.update (E) -> [user.update.address & user.update.profile] -> user_update_queue (Q)

Related

Flyway to update two databases

I have micrnaut based java application. which uses two databases, i have set up the two datasources
but how can i use flyway to load different data into the two databases
directory is as follows, which works for single db as following examples:
resources -> db->migration -> V1__data.sql
Assuming you have two datasources as below:
datasources:
default:
url: 'jdbc:h2:mem:flywayDb1;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE'
username: 'sa'
password: ''
driverClassName: 'org.h2.Driver'
other:
url: 'jdbc:h2:mem:flywayDb2;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE'
username: 'sa'
password: ''
driverClassName: 'org.h2.Driver'
You can configure Flyway as below:
flyway:
datasources:
default:
enabled: true
locations:
- classpath:db/migrations/default
other:
enabled: true
locations:
- classpath:db/migrations/other
Check the micronaut Flyway manual for more information.

symfony messenger multiple bus

I need to have multiple bus in my application written on Symfony. To do so I'm using messenger bundle.
So I need to have:
external_events_bus - which receiving messages from external systems, which using sqs transport
application_events_bus - for application events (using database driver for now)
domain_events_bus - for domain events (using database driver for now)
command_bus - for commands and queries (CQRS) (currently sync)
so in my messenger.yaml I have:
framework:
messenger:
default_bus: command.bus
buses:
command.bus: ~
domain_event.bus: ~
application_event.bus: ~
external_event.bus: ~
transports:
command_bus: '%env(COMMAND_BUS_DSN)%'
internal_event_bus: '%env(INTERNAL_EVENT_BUS_DSN)%'
external_event_bus: '%(EXTERNAL_EVENT_BUS_DSN)%'
routing:
'App\Application\CommandBus\Command': command_bus
'App\Domain\EventBus\DomainEvent': internal_event_bus
'App\Application\EventBus\ApplicationEvent': internal_event_bus
'App\Infrastructure\ExternalEventBus\ExternalEvent': external_event_bus
and in my services.yaml
services:
_defaults:
autowire: true
autoconfigure: true subscribers, etc.
public: false
_instanceof:
# use tags to avoid coupling handler classes to Messenger's interface
App\Application\CommandBus\CommandHandler:
tags: [ { name: messenger.message_handler, bus: command.bus } ]
App\Interfaces\ExternalEventBus\ExternalEventHandler:
tags: [ { name: messenger.message_handler, bus: external_event.bus } ]
App\Domain\EventBus\DomainEventHandler:
tags: [ { name: messenger.message_handler, bus: domain_event.bus } ]
App\Application\EventBus\ApplicationEventHandler:
tags: [ { name: messenger.message_handler, bus: application_event.bus } ]
... // some other services here
App\Application\CommandBus\CommandBus:
class: App\Infrastructure\CommandBus\CommandBus
arguments: [ "#command.bus" ]
App\Domain\EventBus\DomainEventBus:
class: App\Infrastructure\DomainEventBus\DomainEventBus
arguments: [ "#domain_event.bus" ]
App\Application\EventBus\ApplicationEventBus:
class: App\Infrastructure\ApplicationEventBus\ApplicationEventBus
arguments: [ "#application_event.bus" ]
App\Infrastructure\ExternalEventBus\ExternalEventBus:
class: App\Infrastructure\ExternalEventBus\ExternalEventBus
arguments: [ "#external_event.bus" ]
Want to clarify before I had only command bus and external bus and all was fine, but after I added domain and application bus, somethinkg went wrong.
When in tests I'm using ExternalEventBus, to test if external event handled correctly, like this:
$this->eventBus = self::$container->get(PlatformEventBus::class);
$this->eventBus->dispatch(new SomeExternalEvent());
I'm getting error like
Symfony\Component\Messenger\Exception\NoHandlerForMessageException: No handler for message "SomeExternalEvent".
but when I'm running bin/console debug:messenger for both dev and test env, I can see correct mapping between all events and their handlers.
But when I'm debugging it can see that HandlersLocator::getHandlers() for that SomeExternalEvent for some reason returning list of handlers related to command bus instead of external event bus (maybe because command bus set as a default bus)
I know it's a bit hard to explaing and show topic, but I spend already whole day truing to find what is wrong with it. Any help appreciated, thank you!!!
Sorry for any kind of typos, I'm a bit change name of classes for this example and may did some typos
okay, I figured it out, messenger using autowiryng when you injecting MessageBusInterface depends on variable name, so in case of external event bus it should be $externalEventBus and same for other buses. But I do not understand how it worked before, as I mentioned I have command and external bus for a while and it stop working only when I add more buses...

Using Codeception with Wordpress: During page load an outside http request is made, how do i check the response of that request?

I'm using Codeception/WP Browser to write tests for Wordpress. I had a method on a class that was making an outside http request whenever it was being loaded up and this was incorrect behavior. It's only supposed to make that request on a certain page, and on others it is not. I have rewritten the code so its fixed, but I dont know how to go about testing it. I've tried loading up the acceptance, functional and wpunit tester helpers but none of them seem to have anything that lets me grab a response from an outside http request on page load. Can anyone help?
Ive tried using the different modules, but I cant seem to find the magic combination or I am just lost.
heres some of my acceptance code that isnt doing it
<?php
// $ codecept run acceptance exampleExpectLoginByAdminCest
class expectLoginByAdminCest {
public function _before( AcceptanceTester $I ) {
}
public function _after( AcceptanceTester $I ) {
}
public function expectsAdminToLogin( AcceptanceTester $I ) {
// ARRANGE
$I->wantTo( 'log in as an Admin' );
$I->amGoingTo( 'log in as Admin' );
// ACT
$I->loginAsAdmin();
$I->amOnPage( "/wp-admin/admin.php?page=advisor-dashboard&course=8927" );
// ASSERT
// tokens shouldnt be available so bad response
$I->seeResponseCodeIs(401);
}
}
Heres a copy of my acceptance config
# Suite for acceptance tests.
actor: AcceptanceTester
modules:
enabled:
- WPDb
- WPWebDriver
- \Helper\Acceptance
config:
WPDb:
dsn: 'mysql:host=%TEST_SITE_DB_HOST%;dbname=%TEST_SITE_DB_NAME%'
user: '%TEST_SITE_DB_USER%'
password: '%TEST_SITE_DB_PASSWORD%'
dump: 'tests/_data/rwa-dump.sql'
#import the dump before the tests; this means the test site database will be repopulated before the tests.
populate: true
# re-import the dump between tests; this means the test site database will be repopulated between the tests.
cleanup: true
waitlock: 10
url: '%TEST_SITE_WP_URL%'
urlReplacement: true #replace the hardcoded dump URL with the one above
tablePrefix: '%TEST_SITE_TABLE_PREFIX%'
WPWebDriver:
url: '%CHROMEDRIVER_WP_URL%'
adminUsername: 'admin'
adminPassword: 'admin'
adminPath: '/wp-admin'
browser: chrome
host: %CHROMEDRIVER_HOST%
port: %CHROMEDRIVER_PORT%
capabilities:
# Used in more recent releases of Selenium.
"goog:chromeOptions":
args: ["--no-sandbox", "--disable-gpu", "--user-agent=wp-browser"]
w3c: false
# Support the old format for back-compatibility purposes.
"chromeOptions":
args: ["--no-sandbox", "--disable-gpu", "--user-agent=wp-browser"]
w3c: false
The api call should fail, and get a 401 because no token should be available to authenticate, but its getting a 200

issue with queue priority on RabbitMqBundle

I am trying to setup a priority queue. Without priority, it is working just fine but I need to prioritize messages.
I am using RabbitMqBundle 1.14 and rabbitmq-supervisor-bundle 3.1 with RabbitMQ 3.5.7 (Erlang 18.3)
Here is the config.yml :
old_sound_rabbit_mq:
connections:
default:
host: '127.0.0.1'
port: 5672
user: 'xxx'
password: 'xxx'
vhost: '/'
lazy: false
connection_timeout: 3
read_write_timeout: 3
# requires php-amqplib v2.4.1+ and PHP5.4+
keepalive: false
# requires php-amqplib v2.4.1+
heartbeat: 0
#requires php_sockets.dll
use_socket: true # default false
producers:
global:
connection: default
exchange_options: {name: 'global', type: direct}
queue_options:
name: global
consumers:
global:
connection: default
exchange_options: {name: 'global', type: direct}
queue_options: {name: 'global', arguments: {'x-max-priority': ['I', 10]} }
callback: rabbitmq_simu_service
And the message sent to queue :
$msg = array();
$msg['id'] = $id;
$msg['action'] = 'simu';
$additionalProperties = ['priority' => 4] ;
$routing_key = '';
$this->container->get('old_sound_rabbit_mq.global_producer')->publish(serialize($msg), $routing_key , $additionalProperties);
I get the following error when sending the message :
PRECONDITION_FAILED - inequivalent arg 'x-max-priority' for queue 'global' in vhost '/': received none but current is the value '10' of type 'signedint'
I also tried in the config.yml :
queue_options: {name: 'global', arguments: {'x-max-priority': 10} }
In this case, I got no error but messages are not consumed.
Does anyone know how to send priority message ?
The message you have received is the error message for what happens when you try to create a queue, but the queue already exists with different parameters. You must delete the queue first, then try running your program.
PRECONDITION_FAILED - inequivalent arg 'x-max-priority' for queue 'global' in vhost '/': received none but current is the value '10' of type 'signedint'
That message means that you have already created the global queue with a max priority of 10, but something else is trying to declare it with no priority. You must review your code for both your producer and consumer to ensure that if they declare this priority queue they use exactly the same x-max-priority argument.
NOTE: the RabbitMQ team monitors rabbitmq-users mailing list and only sometimes answers questions on StackOverflow.

Sonata Media CDN Rackspace

I have the next problem with Sonata Media:
I'm trying to use the Rackspace CDN for uploading images:
My config file looks like this based on current documentation:
cdn:
server:
path: %cdn_url%
filesystem:
local:
directory: %kernel.root_dir%/../web/uploads/media
create: false
rackspace:
url: %rackspace.opencloud.host%
secret:
username: %rackspace.opencloud.username%
apiKey: %rackspace.opencloud.api_key%
region: LON
containerName: projectName
create_container: false
replicate:
master: sonata.media.adapter.filesystem.opencloud
slave: sonata.media.adapter.filesystem.local
And on providers config:
providers:
image:
filesystem: sonata.media.filesystem.replicate
cdn: sonata.media.cdn.server
resizer: sonata.media.resizer.square
allowed_extensions: ['jpg', 'png', 'gif', 'jpeg']
allowed_mime_types: ['image/pjpeg','image/jpeg','image/png','image/x-png', 'image/gif']
The problem is(how I discovered this bug)if Rackspace is down or incorrect username/password are provided on every page of the app I'm getting this answer:
Client error response [status code] 401 [reason phrase] Unauthorized [url] https://lon.auth.api.rackspacecloud.com/v2.0/tokens
This is because Gaufrette Opencloud tries to create a connection on Kernel load.
The quickest solution as a temporary fix was to create a compiler pass and check if the authenticate method returns false then replace argument 0 for replicate definition with the local filesystem adaptor.
My questions are:
How can I avoid creating the Rackspace connection on Kernel Load?
In case Rackspace is down how can I swap between Rackspace or other adapter(local or other ftp server)
Thank you in advance and please in case there are not sufficient information provided please leave a comment.
Apparently there is a solution for lazy loading implemented in Gaufrette: https://github.com/KnpLabs/KnpGaufretteBundle/issues/72
All I had to do is:
sonata.media.adapter.open_stack:
class: OpenCloud\Rackspace
arguments: [ %rackspace.opencloud.host%, { username: %rackspace.opencloud.username%, apiKey: %rackspace.opencloud.api_key% }]
sonata.media.adapter.object_store_factory:
class: Gaufrette\Adapter\OpenStackCloudFiles\ObjectStoreFactory
arguments: [ #sonata.media.adapter.open_stack, "LON", ""]
sonata.media.adapter.filesystem.lazyopencloud:
class: Gaufrette\Adapter\LazyOpenCloud
arguments: [ #sonata.media.adapter.object_store_factory, %rackspace.opencloud.container_name%]
And change replicate master to sonata.media.adapter.filesystem.lazyopencloud
Hope it helps :)

Resources