Azure / azure-functions-servicebus-extension

Service Bus extension for Azure Functions
MIT License
65 stars 36 forks source link

Injecting MessageReceiver/IMessageReceiver associated with ServiceBusTrigger #120

Closed SeanFeldman closed 3 years ago

SeanFeldman commented 3 years ago

Is your question related to a specific version? If so, please specify:

Functions v3

What language does your question apply to? (e.g. C#, JavaScript, Java, All)

C#

Question

The documentation states that

Functions-specific types like BindingContext and ExecutionContext aren't available during setup or as injectable types

What about MessageReceiver/IMessageReceiver associated with ServiceBusTrigger? It works when a static function declares a parameter but wasn't able to get it injected with the Startup approach and non-static function.

SeanFeldman commented 3 years ago

@brettsam any information on this one?

brettsam commented 3 years ago

Transferring this to the SB extension repo and pinging @alrod as the expert.

But I don't believe this is supported. The extension would need to register these types with DI during startup and I don't see that happening here: https://github.com/Azure/azure-functions-servicebus-extension/blob/dev/src/Microsoft.Azure.WebJobs.Extensions.ServiceBus/Config/ServiceBusWebJobsBuilderExtensions.cs#L28

SeanFeldman commented 3 years ago

The extension would need to register these types with DI during startup and I don't see that happening

Just like MessageProvider is registered, could there be another type that is CurrentMessageReceiver be registered that would return the message receiver for the current context? Or perhaps a service that would return the MessageReceiver for a given input/trigger queue?

Looking forward to @alrod's thoughts on this.

SeanFeldman commented 3 years ago

@alrod any thoughts on this?

SeanFeldman commented 3 years ago

@brettsam, as @alrod might not be around or available to answer this question, perhaps someone else is?

alrod commented 3 years ago

@SeanFeldman, It's not supported in startup, MessageReceiver is a function specific type (you need to specify connection string and entity path to create new object).

You can get MessageReceiverassociated to specific SB trigger by static param: https://github.com/Azure/azure-functions-servicebus-extension/blob/dev/test/Microsoft.Azure.WebJobs.Extensions.ServiceBus.Tests/ServiceBusEndToEndTests.cs#L672

Or use the method of MessageProvider: https://github.com/Azure/azure-functions-servicebus-extension/blob/dev/src/Microsoft.Azure.WebJobs.Extensions.ServiceBus/MessagingProvider.cs#L63

SeanFeldman commented 3 years ago

@alrod, do I understand correctly that MessagingProvider.CreateMessageSender(string entityPath, string connectionString) will look up an existing message sender by using entity path and connection string as the key? That would work as long as MessagingProvider is available via DI container.

I do have an additional question about CreateMessageSender. It applies the same logic as CreateMessageReceiver but it doesn't validate that there's a message receiver already in place with the same key to create a MessageSender using the same service bus connection rather than creating a new connection. What's the reason to create another connection for an already established entity path/connection string combo?

alrod commented 3 years ago

@SeanFeldman, I am not sure if MessagingProvider is fully initialized by the time of OnStart execution. You need to verify this. We need MessageReceiverfor ServiceBus trigger and MessageSenderfor ServiceBus output. There is no one class that supports receiving and sending operations.

SeanFeldman commented 3 years ago

I am not sure if MessagingProvider is fully initialized by the time of OnStart execution. You need to verify this.

I'll validate and let you know.

We need MessageReceiver for ServiceBus trigger and MessageSender for ServiceBus output. There is no one class that supports receiving and sending operations.

I'm aware that there's no single class. What I'm saying is that a message receiver/sender can be constructed using the same connection object (not connection string). That way the connection is shared. This is especially useful for connection pooling when receiving and sending to the same namespace using the same connection string. It also reduces the number of TCP connections established to the broker. And one could say the maximum of 5,000 concurrent connections is more than enough, a system can use a namespace for more than just functions and those connections go fast.

alrod commented 3 years ago

What I'm saying is that a message receiver/sender can be constructing using the same connection object (not connection string)

Agree, we can improve this. Created an item to track.

SeanFeldman commented 3 years ago

@alrod, I can confirm that MessagingProvider is getting injected.