Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Container not disposing transient components

I'm not sure whether this is more of an NServiceBus issue, a Windsor issue, or just my own stupidity problem - but I'm experiencing a memory leak which seems to point to lots of transient components still hanging around.

This is how I set up NServiceBus with Windsor, inside my IWantCustomInitialization.Init method:

var cont = new Castle.Windsor.WindsorContainer();
cont.Register(
    Component.For<IWindsorContainer>().Instance(cont));     

Configure.With()
    .CastleWindsorBuilder(cont)
    .DefiningCommandsAs(t => t.GetCustomAttributes(typeof(MyCommandAttribute), false).GetLength(0) > 0)
    .DefiningEventsAs(t => t.GetCustomAttributes(typeof(MyEventAttribute), false).GetLength(0) > 0)
    .DefiningMessagesAs(t => t.Namespace != null && t.Namespace.EndsWith(".LocalMessages"))
    .XmlSerializer()
    .Log4Net()
    .IsolationLevel(System.Transactions.IsolationLevel.ReadCommitted)
    .UseNHibernateTimeoutPersister()
    .RunTimeoutManager()
    .Sagas()
    .NHibernateSagaPersister()
    .DisableRavenInstall();

cont.Register(
    Component.For<ISessionFactory>().Named("ABC").LifeStyle.Singleton.UsingFactoryMethod(() =>
{
    return Fluently.Configure().Database(() =>
        {
            return MsSqlConfiguration.MsSql2005.UseOuterJoin()
            .ConnectionString(x => x.FromConnectionStringWithKey("ABCData"))
            .ShowSql();
        }
    ).Mappings((m) =>
        {
            AddABCMappingsOnly(m.FluentMappings);
        })
    .ExposeConfiguration(cfg =>
        {
            SchemaMetadataUpdater.QuoteTableAndColumns(cfg);
            var sv = new SchemaValidator(cfg);
            sv.Validate();
        })
    .BuildSessionFactory();
}));

cont.Register(
    Component.For(typeof(IClientLookup), typeof(ICountryLookup), typeof(IOtherLookupLookup)).LifeStyle.Transient.ImplementedBy<ABCDataLookup>().DependsOn(
Dependency.OnComponent(typeof(ISessionFactory), "ABC")));

What I find is that, after some period of uptime (say, 2 hours pushing through messages as much as possible), I have thousands of ABCDataLookup components lurking around, and so far as I can see, the only thing holding onto these components is the Windsor container (so, presumably, it still thinks something else is using these components?)

Some of my issues may arise from the fact that NServiceBus takes responsibility for registering some components in the container and/or performing resolution, so I'm not able to cleanly see whether the registrations look correct.

Is there something I've done wrong/stupid in my registration?

I'm already having to do one thing that looks wrong:

cont.Register(
    Component.For<IWindsorContainer>().Instance(cont));

because NServiceBus registers one ISessionFactory in the container for use by IFindSagas implementations. But I have another component that implements IWantToRunWhenTheBusStarts that wants to obtain the "ABC" ISessionFactory, and I couldn't work out how to make that work between NServiceBus and Windsor.

The other components that expect to have ABCDataLookup instances injected are Sagas, and again, I'm not able to really see how NServiceBus is registering/instantiating them.

If there's any extra code or config that needs to be shown, please shout.

My Packages.config:

<packages>
  <package id="Castle.Core" version="3.0.0.4001" targetFramework="net45" />
  <package id="Castle.Windsor" version="3.0.0.4001" targetFramework="net45" />
<!-- irrelevant -->
  <package id="FluentNHibernate" version="1.3.0.733" targetFramework="net45" />
  <package id="Iesi.Collections" version="3.2.0.4000" targetFramework="net45" />
  <package id="log4net" version="1.2.10" targetFramework="net45" />
<!-- irrelevant -->
  <package id="NHibernate" version="3.3.2.4000" targetFramework="net45" />
  <package id="NServiceBus" version="3.3.8" targetFramework="net45" />
  <package id="NServiceBus.CastleWindsor" version="3.3.8" targetFramework="net45" />
  <package id="NServiceBus.Host" version="3.3.8" targetFramework="net45" />
  <package id="NServiceBus.Interfaces" version="3.3.8" targetFramework="net45" />
  <package id="NServiceBus.NHibernate" version="3.3.8" targetFramework="net45" />
</packages>
like image 630
Damien_The_Unbeliever Avatar asked Sep 04 '26 11:09

Damien_The_Unbeliever


1 Answers

We have fixed quite a few things to do with disposing of components properly in v4, see https://github.com/NServiceBus/NServiceBus/commit/baa9624517d1083e3cfa681e8598f66ccfbf741b

Also the ISessionFactory should be implemented as a UoW, see our internal implementation for inspiration here

like image 90
John Simons Avatar answered Sep 05 '26 23:09

John Simons



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!