Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for setting up publisher confirms for Rabbit MQ #153

Closed
wants to merge 8 commits into from
Closed

Conversation

eswann
Copy link

@eswann eswann commented Nov 15, 2012

Did the following to enable publisher confirms with external tracking:

  1. Added publisher-confirm ack/nack support to RabbitMqProducer
  2. Added PublisherConfirmSettings class to store the following:
  • UsePublisherConfirms - Determines whether or not publisher confirms are used.
  • RegisterMessageAction - Action called before a publish so that external app can register the message in the buffer of their choice. Provides the Rabbit publish/confirm sequence number.
  • Acktion - Action called when a publisher confirm Ack is returned by the broker.
  • Nacktion - Action called when a publisher confirm Nack is returned by the broker.
    3) Updated RabbitMqTransportFactoryBuilder and Impl to allow setting of publisher confirm settings.
    4) Added PublisherConfirmFactoryConfigurator and Impl to configure these settings
    5) Updated RabbitMqTransportFactoryExtensions to add "UsePublisherConfirms" extension method.
    6) Updated OutboundRabbitMqTransport send method to assign a message ID from the header so that it is accessible in the RabbitMqProducer.Publish method.

Configure as follows:
builder.Register(c => ServiceBusFactory.New(sbc =>
{
sbc.UseRabbitMq(conf => conf.UsePublisherConfirms(RegisterMessageAction, Acktion, Nacktion));

        })).SingleInstance();
    }

    public void RegisterMessageAction(ulong sequenceNumber, string correlationId)
    {
        //TODO: store in buffer
    }

    public void Acktion(ulong sequenceNumber, bool isMultiple)
    {
        //TODO: Remove from buffer
    }

    public void Nacktion(ulong sequenceNumber, bool isMultiple)
    {
        //TODO: Store unacked messages to a more permanent place for reprocessing
    }

Please let me know if there's a better way to accomplish this. Thanks,
Eric

@drusellers
Copy link
Member

@eswann sorry for the very long delay but I wanted to get a note back to you. The publisher confirms are already in place for the latest ga release. They are just immediate and always on. I hope that this is helpful to you.

@drusellers drusellers closed this Jun 9, 2013
@eswann
Copy link
Author

eswann commented Aug 2, 2013

@drusellers Hey, I've looked at the implementation, the main issue i have with the current implementation is that I didn't see a way to pass a delegate to execute when an ack/nack happens. For Rabbit, this is very important because unlike MSMQ, the publisher doesn't have a local place to store messages if a nack happens. If they just sit in memory, you'll eventually overwhelm the system (if you publish the number of messages that we do). After talking to the Rabbit guys, if you ever get a Nack from Rabbit, it essentially means that Rabbit has completely crapped its pants and most probably won't become available without manual intervention, although this should be rare you risk huge message loss if it does happen.
What we do is wrap our publisher with a backup mechanism where it can write messages to disk or DB if Rabbit has issues (nacks or connectivity issues). If the system starts storing locally, it occasionally tries to send a message and if it gets an ack, the system knows it's ok to start publishing all messages again. If we don't have a way to communicate out the ack/nack, we can't take action. So I created the PublisherConfirmSettings that take an ack/nack delegate.
If there's a better way that you can see to approach that, definitely let me know.

Thanks!
Eric

@phatboyg
Copy link
Member

phatboyg commented Aug 3, 2013

The communication method between MT and the transports will be revisited in 3.0 (and likely changed) to support fully asynchronous operation using the TPL. Until then, the code put into place was a short-term solution. The 3.0 level solution will have several extensions points along the path to inject behaviors (all using TPL continuations) to handle things like failing to send to the broker, waiting for ack, handling immediate and mandatory failures via select, etc.

This will also include an entirely new high-availability client for RabbitMQ and Azure Service Bus.

An unfortunately consequence is that .NET 4.0 and later is all that will be supported, leaving support for .NET 3.5 in the MT 2.x lineage (which will be completely serializer compatible allowing interop with older solutions).

@eswann
Copy link
Author

eswann commented Aug 3, 2013

Thanks sounds great. Any idea when that will be ready for primetime?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants