go-rabbitmq icon indicating copy to clipboard operation
go-rabbitmq copied to clipboard

Why is Exchange configuration driven by Consumers instead of Publishers

Open ghost opened this issue 2 years ago • 7 comments

This library seems to have Consumers drive the configuration of the Exchanges rather than the Publishers. For example, Consumers determine if an exchange should auto delete, be durable, or the kind (e.g. topic).

Sample:

	err = consumer.StartConsuming(
			func(d rmq.Delivery) rmq.Action {
				log.Printf("consumed: %v", string(d.Body))
				// true to ACK, false to NACK
				return rmq.Ack
			},
			QUEUE,
			[]string{TOPIC},
			rmq.WithConsumeOptionsBindingExchangeAutoDelete,
			rmq.WithConsumeOptionsBindingExchangeDurable,
			rmq.WithConsumeOptionsBindingExchangeName(""),
			rmq.WithConsumeOptionsBindingExchangeKind("topic"),
			rmq.WithConsumeOptionsQueueArgs(queueArgs),

Isn't this a bit backwards since Publishers are the ones who write to Exchanges and should therefore configure its settings, and then Consumers simply configure the queues that they use? Was this design selected out of personal preference or was there a technical reason for it?

ghost avatar Oct 01 '21 18:10 ghost

It's a good question, and I'm open to changing my mind, that said let me present my reasoning.

Primarily, this library is a "batteries included" library, the goal is sane defaults and such. It makes sense to me that you should be able to start a consumer and have it "just work", even if the exchange you're attaching to doesn't yet exist. If it doesn't your consumer will create it for you. That said, the default options WILL NOT create an exchange for you, you have to ask for that explicitly.

Additionally, this library will error out and alert you if you try to create an exchange that already exists and it doesn't have the parameters you expect:

ExchangeDeclare declares an exchange on the server. If the exchange does not already exist, the server will create it. If the exchange exists, the server verifies that it is of the provided type, durability and auto-delete flags.

wagslane avatar Dec 07 '21 15:12 wagslane

It's a good question, and I'm open to changing my mind, that said let me present my reasoning.

Primarily, this library is a "batteries included" library, the goal is sane defaults and such. It makes sense to me that you should be able to start a consumer and have it "just work", even if the exchange you're attaching to doesn't yet exist. If it doesn't your consumer will create it for you. That said, the default options WILL NOT create an exchange for you, you have to ask for that explicitly.

Additionally, this library will error out and alert you if you try to create an exchange that already exists and it doesn't have the parameters you expect:

ExchangeDeclare declares an exchange on the server. If the exchange does not already exist, the server will create it. If the exchange exists, the server verifies that it is of the provided type, durability and auto-delete flags.

understood, thanks for the explanation! logical and reasonable

i ended up forking the repository in order to have publisher-driven exchange creation and consumer-driven queue creation

ghost avatar Dec 07 '21 17:12 ghost

@wagslane what's your thoughts on also allowing publishers to create the exchange, not only the consumer?

The current behaviour caught me as a surprise. Having gone through the streadway/amqp examples, my brain was wired into the idea that both parties could create the exchange. Combined with the idea of go-rabbitmq handling the low-levels for us, I for some reason struggled badly understanding why on earth the exchange was not created when the publisher interacting with RabbitMQ.

Honestly didn't even think it might have helped to start a consumer at that point, we didn't have that service ready yet, but wanted to rollout the publishing part out first and verify the RabbitMQ mechanics were created as expected.

Steering away from a philosophical discussion about right or wrong, if we had the opportunity to choose if the exchange could be created by the publisher too, that would have been really helpful for our workflow & desire for independent rollouts.

phillipj avatar Feb 27 '22 12:02 phillipj

It would be really helpful if the publisher could create the exchange as well.

NicklasWallgren avatar May 12 '22 12:05 NicklasWallgren

I'm totally open to that idea. Feel free to open a PR or I'll get to it when I can

wagslane avatar May 12 '22 12:05 wagslane

Great, I might have a go at it later this week.

NicklasWallgren avatar May 12 '22 17:05 NicklasWallgren

I've started working on a PR in my local fork, if anyone is interested.

https://github.com/NicklasWallgren/go-rabbitmq/pull/1/files

NicklasWallgren avatar May 27 '22 11:05 NicklasWallgren

@h44z @wagslane If the design is finalized, Can I help?

Having configuration driven by either Publisher or Consumer would be good to have. Otherwise, One has to write the consumer first before publishing anything to the rabbitmq.

aaqaishtyaq avatar Oct 21 '22 18:10 aaqaishtyaq

@aaqaishtyaq Have a look at https://github.com/wagslane/go-rabbitmq/pull/91

NicklasWallgren avatar Oct 25 '22 05:10 NicklasWallgren

@NicklasWallgren Thanks for the PR. Can we please look into merging it?

aaqaishtyaq avatar Nov 10 '22 10:11 aaqaishtyaq

When considering merging this pr, our service environment consumers will restart the service, which will cause our publishers to be unable to publish messages

mijjjj avatar Nov 22 '22 07:11 mijjjj

Everyone concerned with this thread please read the new docs on the main branch. This issue should be resolved. Please let me know as soon as you can if this new API will work.

wagslane avatar Nov 30 '22 19:11 wagslane

Resolved in 0.11.0

wagslane avatar Dec 05 '22 18:12 wagslane