Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Embracing NServiceBus - best practices

Embracing NServiceBus - best practices

Presentation delivered by Mark Taling and myself at NSBCon London, June 2014.

The video can be viewed on http://particular.net/nsbcon-2014

Roy Cornelissen

June 26, 2014
Tweet

More Decks by Roy Cornelissen

Other Decks in Programming

Transcript

  1. ~

  2. Where we started Discovering NServiceBus Multi tenancy Saga’s The evolution

    of NServiceBus Performance considerations Maintainability NServiceBus in a brownfield Wrap up Q&A
  3. Integration Layer Service Layer NIS Presentation Layer Planning UI Reporting

    UI customer external apps Employee Self Service Common Forecast Realization Payment Schedule
  4. Monitoring & Control Integration Layer Service Layer NIS Presentation Layer

    Planning UI Reporting UI Employee Self Service Common Forecast Payment Schedule Service Bus Integration Services IS HRM IS Payroll IS Budget IS Provisioning IS Time IS Point of Sale Realization
  5. public class BuildPrincipalFromHeaders : IMutateIncomingMessages { public object MutateIncoming(object message)

    { Thread.CurrentPrincipal = null; string tenantId = Headers.GetMessageHeader(message, “urn:dv:tenantid”); ICollection<Claim> claims = new List<Claim>(); … claims.Add(new Claim(SecurityConstants.TenantIdClaim, tenantId)); var principal = new ClaimsPrincipal( new ClaimsIdentityCollection { new ClaimsIdentity(claims) }); Thread.CurrentPrincipal = principal; return message; } …
  6. public class SetHeadersFromPrincipal : IMutateOutgoingMessages { public IBus Bus {

    get; set; } public object MutateOutgoing(object message) { IClaimsIdentity identity = Thread.CurrentPrincipal.Identity as IClaimsIdentity; string tenantId = identity.GetTenantId(); if (!string.IsNullOrWhiteSpace(tenantId)) { Bus.SetMessageHeader(message, “urn:dv:tenantid”, tenantId); } return message; } …
  7. public class AdvancedRavenSagaPersister : RavenSagaPersister, ISagaPersister { public AdvancedRavenSagaPersister(RavenSessionFactory sessionFactory):

    base(sessionFactory) { } public new void Save(IContainSagaData saga) { base.Save(saga); } public new void Complete(IContainSagaData saga) { base.Complete(saga); } void ISagaPersister.Save(IContainSagaData saga) { Save(saga); } void ISagaPersister.Complete(IContainSagaData saga) { Complete(saga); } }
  8. public class AdvancedRavenSagaPersister : RavenSagaPersister, ISagaPersister { public AdvancedRavenSagaPersister(RavenSessionFactory sessionFactory):

    base(sessionFactory) { } public new void Save(IContainSagaData saga) { base.Save(saga); } public new void Complete(IContainSagaData saga) { base.Complete(saga); } void ISagaPersister.Save(IContainSagaData saga) { Save(saga); } void ISagaPersister.Complete(IContainSagaData saga) { Complete(saga); } }
  9. public class AdvancedRavenSagaPersister : RavenSagaPersister, ISagaPersister { public AdvancedRavenSagaPersister(RavenSessionFactory sessionFactory):

    base(sessionFactory) { } public new void Save(IContainSagaData saga) { base.Save(saga); StoreMappingKeys(saga); } public new void Complete(IContainSagaData saga) { RemoveMappingKeys(saga); base.Complete(saga); } void ISagaPersister.Save(IContainSagaData saga) { Save(saga); } void ISagaPersister.Complete(IContainSagaData saga) { Complete(saga); } }
  10. public class AdvancedRavenSagaPersister : RavenSagaPersister, ISagaPersister { private readonly RavenSessionFactory

    _sessionFactory; public AdvancedRavenSagaPersister(RavenSessionFactory sessionFactory): base(sessionFactory) { _sessionFactory = sessionFactory; } public new void Save(IContainSagaData saga) { base.Save(saga); StoreMappingKeys(saga); } public new void Complete(IContainSagaData saga) { RemoveMappingKeys(saga); base.Complete(saga); } void ISagaPersister.Save(IContainSagaData saga) { Save(saga); } void ISagaPersister.Complete(IContainSagaData saga) { Complete(saga); } }
  11. public class AdvancedRavenSagaPersister : RavenSagaPersister, ISagaPersister { private readonly RavenSessionFactory

    _sessionFactory; public AdvancedRavenSagaPersister(RavenSessionFactory sessionFactory): base(sessionFactory) { _sessionFactory = sessionFactory; } public new void Save(IContainSagaData saga) { base.Save(saga); StoreMappingKeys(saga); } public new void Complete(IContainSagaData saga) { RemoveMappingKeys(saga); base.Complete(saga); } void ISagaPersister.Save(IContainSagaData saga) { Save(saga); } void ISagaPersister.Complete(IContainSagaData saga) { Complete(saga); } } var document = _sessionFactory.Session.Include("SagaDocId").Load<SagaMappingIdentity>(mappingId); return _sessionFactory.Session.Load<TSagaData>(document.SagaId);
  12. Keep your transactions on a diet Design with parallelism in

    mind {Tx} {Tx} [Unique] saga properties {Tx}
  13. NServiceBus is an opinionated framework If it fits, it fits

    like a glove Prepare to make concessions at first Clean up later Messaging makes totally different use cases possible Requires a new mindset for everyone
  14. NServiceBus is a great way to break open existing architectures

    Despite its flexibility and pluggability, always follow its design principles Go with the flow, it solves real life problems you might not know you have