Where do safety checks go in startup lifecycle?

hosting
nservicebus

(Jeremy Peacock) #1

Bare with me on this question. We are using NServiceBus 5.2.3.

We are running services using the NServiceBus.Host. We are doing some safety checks in our code to make sure we have appropriate permissions to network folders and that databases exist and can be connected and such. We always do these safety checks in a class that implements “IWantToRunWhenTheBusStartsAndStops.Start”. I think we do this here because the first guy did it there and no one every questioned it. And it works… most of the time.

But the issue we are having and have finally traced down to this is the Handlers will start grabbing from the Queue as soon as the Bus is initialized. Which seems to happen at the same time our safety checks are still running. So a Handler will try and access a database to store something before we have confirmed that database is up and running. Because the safety check fails we end up shutting our service down with an error saying unable to reach database but we’ve already got a message in the error queue because it tried and couldn’t connect to the database.

The basic question is where do we put our safety checks in the startup lifecycle so that our safety check code runs before the handlers start processing messages that may already be waiting?

After looking into this a bit I’ve started doing our safety checks in a class that implements “INeedInitialization.Customize” but it feels like the wrong spot to be doing this. It seems to be working for now but I was wondering if there was somewhere more appropriate? Again we are using NServiceBus 5.2.3.

Thanks


(Tim Bussmann) #2

Hey @Peacock

Placing those checks in IWantToRunWhenTheBusStartsAndStops will run them after the endpoint has already started which results in the behavior you’re describing.

NServiceBus provides several extension points to hook into different stages of the endpoint lifecycle and those are documented here: https://docs.particular.net/nservicebus/lifecycle/. Additionally, when using the NServiceBus.Host package, there is also this extension point: https://docs.particular.net/nservicebus/hosting/nservicebus-host/#endpoint-configuration-initialization.

From what I understand, it would make sense to run those checks before the endpoint starts up, so INeedInitialization or IConfigureThisEndpoint sound like better approaches than IWantToRunWhenTheBusStartsAndStops. Is there a specific reason you feel this is the wrong spot to do this?
When using self-hosting, I’d recommend to not use any of the lifecycle hooks but just run the checks before starting the endpoint but using the NServiceBus host, you’d have to rely on one of the lifecycle extension points.


(Jeremy Peacock) #3

It just felt like the wrong spot because the name of the method was Customize, the bus configuration is being passed in, and I wasn’t using the bus configuration at all.

Thanks for confirming INeedInitialization is the correct spot for those.


(Tim Bussmann) #4

That’s a good argument. Unfortunately we don’t provide a hook before the endpoint configuration even starts in the NServiceBus.Host package, so using the mentioned extension points is fine.

As mentioned before, when using self-hosting you have more control of the order of invocations and it’s easier to run your custom code. You might want to check that option (see more here: https://docs.particular.net/nservicebus/hosting/#self-hosting).

Cheers!