Replies: 3 comments
-
I've been having a think about this over the weekend (just submitted a PR for discussion #1622 ), I think we can have the Base CommandProcessor registered as a Singleton and use a Scoped Wrapper to pass in any scoped dependencies (This works for the Sending (Processing) side but still a bit more to do for the Service Activator (Receiving) Side) However when we talk about outbox with Request Reply Queues things get a little more interesting. As in the Scope of a web Request its all well and good to use that scope to create a connection to the DB (Passing the Connection Provider), however on the call-back (and the Outstanding Message Check) we can not rely on this scoped (Or its dependencies) not being disposed as yet, but this does raise the following question for me, Do we care if these Post Request Checks are in the same scope? I would assume that you don't want these things rolled back (If there is an issue) as this is after (potentially) all the work is done, thinking about I could look into a way to create a new scope (if using scoped) for these operations. However this still a fairly fresh thought and I haven't had a chance to Drive it through in my mind as yet |
Beta Was this translation helpful? Give feedback.
-
@preardon I saw that PR and commented. For here, I think it has merit, but I suspect a split into CommandProcessor and CommandProcessorService where the latter is the singleton dependency of the former, and contains anything we want to have greater than scope lifetime may be an improvement. On the latter, we don't care if the clear uses it's own connection. I think that we just need to be able to have a TransactionConnection property on the Outbox you can set. An option to set might be middleware? I assume that if the middleware took a dependency on IServiceProvider it would get the one for the scope, as the middleware itself would be scoped? |
Beta Was this translation helpful? Give feedback.
-
This PR tracks one approach to this problem, separating out an EventServiceBus as a singleton used by CommandProcessor for its external bus dependencies that have a non-scoped lifetime: #1628 |
Beta Was this translation helpful? Give feedback.
-
We have some issues with how we work with ASP.NET Scopes.
ASP.NET Scopes assume all dependencies in a request=response are scoped to that request-response. That seems very straightforward from a web frameworks perspective, but we have state that needs to persist outside that now.
Because the confirmation of a Post to an external bus can happen via a callback, it may occur after the request-response is done. We have to be able to respond to that callback and update the Outbox when that happens.
The Outbox itself is a singleton when in memory as we want it to persist beyond the lifetime of a request-response. Obviously if it is external it is persistent outside of the request-response scope.
But it we want it to participate the appropriate transaction if external so I need to use the same connection that we use to persist to the database. Now usually, that connection is scoped to the request-response.
But a singleton can't depend on a scoped service (it would create a captive dependency) so how do we obtain it?
The only practical answer would seem to be that an external outbox has to ask for its connection, when we need to persist, not have that connection given to it at startup.
This implies that we need to use the ServiceProvider pattern to lookup the connection. So in theory, create a static service provider, have it ask for the connection, and then take a dependency from the Outbox on this ServiceProvider. But this doesn't work, because we have no way to access an ambient service provider.
So what are our options - without taking a hard dependency on ServiceCollection in Brighter, which we don't want to do, as we have customers on other DI frameworks.
Some thoughts right now:
Drop support for Scopes, just allow Transient or Singleton. I don't think this is great.
Use middleware. Add an attribute that injects the connection string which can use DI to obtain the scoped instance.
In essence the middleware option allows us an extension point to work with scopes; if we get it working, we could consider allowing you to set it globally similar to UseInbox to remove the boiler plate.
@preardon @holytshirt @penderi Thoughts?
Beta Was this translation helpful? Give feedback.
All reactions