Recommended migration approach for shared logic and components using IBus

Apologies in advance as I know there are posts on the migration necessary from IBus to IMessageSession and IMessageHandlerContext and some of the decisions leading to the separation of these interfaces.

Background, we have a well established mature system built on NSB v5.x, we have numerous logical services and components shared across self-hosted endpoints (i.e. ASP.NET, WebAPI etc.) and NSB hosted handlers. We typically injected ISendOnlyBus into these logical services and shared components where there is a need for them to send bus messages.

Migrating all of these numerous shared services and components away from ISendOnlyBus to is not without considerable effort. Whilst I’ve read some of the decisions for deprecating IBus I am wondering if the true extent of this change on customer implementations was realised.

Ultimately it does mean a lot of refactoring and I’m not clear on the effects or the behaviour of shared components, services and libraries which previously used ISendOnlyBus or IBus as it seems such code now needs to know the context in which it is being called/used (i.e. directly from a handler or outside of a handler - self-hosted).

Apologies if I’ve misunderstood but it does seem like the established shared code, services, components etc. can no longer be truly shared and must be separated to accommodate IMessageSession and IMessageHandlerContext.

There certainly seems to be a point being made of not blindly converting IBus references to IMessageSession as its not a safe operation.

I came across the unified sessions extension which looks like it could be used in our scenario for migration purposes. But what I haven’t found yet is a recommended or definitive long term approach to utilising these separate interfaces and the implications from an overall system design perspective.

Any suggestions, general advice or migration lessons would be appreciated.

Thanks

Steve

Hi @WilkoSki

UniformSession is definitely a way to go for most major upgrade scenarios. There is no downside of using it i.e. the system is going to behave in the same way as if you used these segregated interfaces and will remain correct.

The IMessageSession and IMessageHandlerContext were designed to make it easier to write new handlers starting with NServiceBus 6. You might find it beneficial for at least some of the components to replace the UniformSession with IMessageHandlerContext in order to improve the clarity of code (who can send messages and where?) but that can be done after the migration.

Hope it helps,
Szymon

Hi @SzymonPobiega,

Thanks for the reply.

The situation we currently have is numerous logical components, services etc which currently use IBus, these can currently be used in the context of a self-hosted WebAPI or from within handlers because of their dependency on IBus (or ISendOnlyBus).

UniformSession as I understand is a drop in replacement for IBus but its intended for migration purposes only.

The recommendation from Particular as I understand it is to split the design and use IMessageSession and IMessageHandlerContext separately.

My concern here is what happens to these existing logical components, services etc which can currently be used in either a WebAPI or from a handler? If my understanding is correct you can no longer use or create new logical components, services etc which can be used either from the context of a WebAPI or handler due to the different interfaces, is this correct?

If my understanding is correct then it feels counter productive and results in an element of duplication for new systems or a large refactoring/re-design exercise for existing systems.

Consider this very simple example, we have a component which is responsible for constructing and sending notification commands to a service which pushes out notifications to physical devices via Apple or Google push services. There are numerous places where a system might wish to send a push notification message e.g. a simple test message triggered from a WebAPI call or an order completion message triggered from a saga. The component responsible for constructing and sending the bus command includes additional logic beyond just sending a bus command. Currently this component uses ISendOnlyBus, it could be modified to use UniformSession. But what happens for a full migration? Do we end up with 2 flavours of the component (for IMessageSession and IMessageHandlerContext)? or do we duplicate the logic contained within this component everywhere in the system when we need to send a message to a push device?

This example is the what I’m looking for in terms of recommended approach to migration of an established system and for new use cases.

Please correct me if I’ve misunderstood anything.

Thanks

Steve

Let me try to give you some more context. The IMessageSession and IMessageHandlerContext distinction has been created in order to make sure messages are actually sent from the handler and not from components the handler uses. The idea was that by forcing a central place where you sent out messages, it will make it easier to figure out the transaction management strategies, especially when using transports that don’t allow for atomic transactions between the queue and the database.

The idea is that a given component returns the messages that are going to be sent from a method call and then the handler actually sends them.

We realize that this design might not suite everybody and depending on the architecture, it might be perfectly OK to just send messages in the nested components, especially when using high consistency transport/persistence combos.

Long story short, you can continue using the UniformSession after you migrate and observe if it does not create friction in your project. If you notice that ability to send messages from every place in your code hinders you ability to evolve the code, consider trying to migrate part of your solution to the IMessageSession / IMessageHandlerContext approach and see if it works better for your team.

Szymon