{"action":"created","issue":{"url":"https://api.github.com/repos/Particular/NServiceBus/issues/3355","labels_url":"https://api.github.com/repos/Particular/NServiceBus/issues/3355/labels{/name}","comments_url":"https://api.github.com/repos/Particular/NServiceBus/issues/3355/comments","events_url":"https://api.github.com/repos/Particular/NServiceBus/issues/3355/events","html_url":"https://github.com/Particular/NServiceBus/pull/3355","id":128508861,"number":3355,"title":"[SPIKE] Unit of Work for bus session","user":{"login":"danielmarbach","id":174258,"avatar_url":"https://avatars.githubusercontent.com/u/174258?v=3","gravatar_id":"","url":"https://api.github.com/users/danielmarbach","html_url":"https://github.com/danielmarbach","followers_url":"https://api.github.com/users/danielmarbach/followers","following_url":"https://api.github.com/users/danielmarbach/following{/other_user}","gists_url":"https://api.github.com/users/danielmarbach/gists{/gist_id}","starred_url":"https://api.github.com/users/danielmarbach/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/danielmarbach/subscriptions","organizations_url":"https://api.github.com/users/danielmarbach/orgs","repos_url":"https://api.github.com/users/danielmarbach/repos","events_url":"https://api.github.com/users/danielmarbach/events{/privacy}","received_events_url":"https://api.github.com/users/danielmarbach/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/Particular/NServiceBus/labels/State:%20In%20Progress","name":"State: In Progress","color":"ededed"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2016-01-25T10:46:57Z","updated_at":"2016-01-25T11:36:50Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/Particular/NServiceBus/pulls/3355","html_url":"https://github.com/Particular/NServiceBus/pull/3355","diff_url":"https://github.com/Particular/NServiceBus/pull/3355.diff","patch_url":"https://github.com/Particular/NServiceBus/pull/3355.patch"},"body":"When flying back from Bangkok I started exploring the possibilities of making the `IBusSession` object a proper scoped unit of work style session. \r\n\r\n* _By default_ : Auto-dispatched session which automatically dispatches each transport operation to the underlying transport\r\n* _Opt-in_: Non-autodispatched session which only dispatches to the transport when the `Dispatch` method is called. All operations are provided to the `IDispatchMessages` implementation in a single call.\r\n\r\nHaving a proper unit of work which expands into the transport has the following\r\n\r\n## Benefits\r\n\r\n### Lifetime\r\n\r\n`IBusSession` has a lifetime on its own and it is clearer than having a `CreateBusSession`which returns an object without scope\r\n\r\n### Immediate vs. Batched dispatch\r\n\r\nThere is a behavior difference between handler context and sessions. A handler context always acts as a unit of work unless you specify `RequireImmediateDispatch`. Sessions in contrary always act as immediate dispatchers. The changes introduced here would remove that confusion. \r\n\r\nWith a non-autodispatch session the behavior is the same as in a handler except that the user is in charge of deciding when the prepared operations should be dispatched. It is also possible to use  `RequireImmediateDispatch` inside a non-autodispatched session.\r\n\r\n### Performance & Throughput\r\n\r\nCurrently we suffer from high costs involved when creating the necessary infrastructure for transport operations outside the scope of a handler. For example for RabbitMQ we need to create a channel everytime when a send, publish... is invoked. Other transports have the same issue. By introducing the scope session and the extension point to the transport it is possible to inject transport specific data into the created bus session. This data will be floated over the core into the dispatcher, thus allowing the transport cache channels, connections etc. for the lifetime of a bus session. \r\n\r\n### Latency\r\n\r\nThe transport can properly bundle the calls on a bus session and reduce the amount of infrastructure API calls. For example the Azure SDK batching APIs can now be used for bus sessions as well and therefore reduce the latency by a number of magnitude.\r\n\r\n## Drawbacks\r\n\r\n### Threadsafety\r\n`IBusSession` is no longer thread safe because it becomes stateful inside its scope. I'd argue this is not a problem since other libraries like NHibernate, RavenDB... have the concept of sessions as well and they are not thread safe either.\r\n\r\n## Discussions\r\n\r\n* A few types like `IWantToRunWhenTheBusStartsAndStops`, `FeatureStartupTask`... get a `IBusSession` object passed in. Should those types get a auto-dispatch session by default and a way to create a non-autodispatched session if really required (i.ex. a property of type `IBusSessionFactory`)\r\n* I previously used the terminology `Flush` but in discussions I decided to go with `Dispatch` because it is closer to the terminology we use and can't be confused with Streams or Files.\r\n\r\n## Breaking changes\r\n* If we want UoW for session we need to do it as part of V6 release or we can only do it in the next major version since adding `IDisposable` is an interface breaking change.\r\n* Changes the `TransportDefinition` --> Implications on down stream repos\r\n\r\nI haven't opened PRs against docs and transports because we need to get short term focus approval first.\r\n\r\n@Particular/tf-async-transport @Particular/tf-async-core @Particular/tf-handlercontext Thoughts on this?"},"comment":{"url":"https://api.github.com/repos/Particular/NServiceBus/issues/comments/174480627","html_url":"https://github.com/Particular/NServiceBus/pull/3355#issuecomment-174480627","issue_url":"https://api.github.com/repos/Particular/NServiceBus/issues/3355","id":174480627,"user":{"login":"mauroservienti","id":1325611,"avatar_url":"https://avatars.githubusercontent.com/u/1325611?v=3","gravatar_id":"","url":"https://api.github.com/users/mauroservienti","html_url":"https://github.com/mauroservienti","followers_url":"https://api.github.com/users/mauroservienti/followers","following_url":"https://api.github.com/users/mauroservienti/following{/other_user}","gists_url":"https://api.github.com/users/mauroservienti/gists{/gist_id}","starred_url":"https://api.github.com/users/mauroservienti/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mauroservienti/subscriptions","organizations_url":"https://api.github.com/users/mauroservienti/orgs","repos_url":"https://api.github.com/users/mauroservienti/repos","events_url":"https://api.github.com/users/mauroservienti/events{/privacy}","received_events_url":"https://api.github.com/users/mauroservienti/received_events","type":"User","site_admin":false},"created_at":"2016-01-25T11:36:50Z","updated_at":"2016-01-25T11:36:50Z","body":"We discussed this on the plane, I love it."}}