Skip to content
This repository has been archived by the owner on May 29, 2024. It is now read-only.

Commit

Permalink
fixed #42
Browse files Browse the repository at this point in the history
  • Loading branch information
asgerhallas committed Jan 13, 2015
1 parent ebd2078 commit aca05fa
Show file tree
Hide file tree
Showing 13 changed files with 247 additions and 225 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ public static class AzureServiceBusConfigurationExtensions
{
public static void UseAzureServiceBusEventDispatcher(this EventDispatcherConfigurationBuilder builder, string connectionString, string topicName)
{
builder.AddEventDispatcher(context => new AzureServiceBusEventDispatcherSender(connectionString, topicName));
builder.UseEventDispatcher(context => new AzureServiceBusEventDispatcherSender(connectionString, topicName));
}

/// <summary>
/// Installs an event dispatcher that can be contacted from anywhere
/// </summary>
public static void UseAzureServiceBusRelayEventDispatcher(this EventDispatcherConfigurationBuilder builder, string serviceNamespace, string servicePath, string keyName, string sharesAccessKey, NetTcpRelayBinding netTcpRelayBinding = null)
{
builder.AddEventDispatcher(context =>
builder.UseEventDispatcher(context =>
{
var eventStore = context.Get<IEventStore>();

Expand Down
2 changes: 1 addition & 1 deletion d60.Cirqus.Tests/Commands/TestCommandProcessing.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ protected override void DoSetUp()

_cirqus = CommandProcessor.With()
.EventStore(e => _eventStore = e.UseInMemoryEventStore())
.EventDispatcher(e => e.AddEventDispatcher(c => new ConsoleOutEventDispatcher()))
.EventDispatcher(e => e.UseEventDispatcher(c => new ConsoleOutEventDispatcher()))
.Options(o =>
{
o.AddDomainExceptionType<InvalidOperationException>();
Expand Down
16 changes: 16 additions & 0 deletions d60.Cirqus.Tests/Config/TestConfigurationApi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
using d60.Cirqus.Views.ViewManagers.Locators;
using MongoDB.Driver.Builders;
using NUnit.Framework;
using TestContext = d60.Cirqus.Testing.TestContext;

namespace d60.Cirqus.Tests.Config
{
Expand Down Expand Up @@ -168,6 +169,21 @@ public void CanDoTheConfigThing()
Assert.That(someCommand.WasProcessed, Is.EqualTo(true));
}

[Test]
public void CanDecorateAggregateRootRepositoryForTestContext()
{
var decorated = true;
TestContext.With()
.AggregateRootRepository(x => x.Decorate(c =>
{
decorated = true;
return c.Get<IAggregateRootRepository>();
}))
.Create();

Assert.True(decorated);
}

public class SomeCommand : ExecutableCommand
{
public bool WasProcessed { get; set; }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,56 @@
using System;
using d60.Cirqus.Aggregates;
using d60.Cirqus.Events;
using d60.Cirqus.Serialization;
using d60.Cirqus.Snapshotting;

namespace d60.Cirqus.Config.Configurers
{
public class AggregateRootRepositoryConfigurationBuilder : ConfigurationBuilder<IAggregateRootRepository>
{
public AggregateRootRepositoryConfigurationBuilder(IRegistrar registrar) : base(registrar) { }

/// <summary>
/// Registers a <see cref="DefaultAggregateRootRepository"/> as the <see cref="IAggregateRootRepository"/> implementation. Since this is the
/// default, there's no need to call this method explicitly.
/// </summary>
public void UseDefault()
{
Register(context =>
new DefaultAggregateRootRepository(
context.Get<IEventStore>(),
context.Get<IDomainEventSerializer>(),
context.Get<IDomainTypeNameMapper>()));
}

/// <summary>
/// Registers a <see cref="FactoryBasedAggregateRootRepository"/> as the <see cref="IAggregateRootRepository"/> implementation.
/// </summary>
public void UseFactoryMethod(Func<Type, AggregateRoot> factoryMethod)
{
Register(context =>
new FactoryBasedAggregateRootRepository(
context.Get<IEventStore>(),
context.Get<IDomainEventSerializer>(),
context.Get<IDomainTypeNameMapper>(),
factoryMethod));
}

/// <summary>
/// Registers a <see cref="IAggregateRootRepository"/> as a decorator in front of the existing <see cref="InMemorySnapshotCache"/>
/// which will use an <see cref="CachingAggregateRootRepositoryDecorator"/> to cache aggregate roots.
/// </summary>
public void EnableInMemorySnapshotCaching(int approximateMaxNumberOfCacheEntries)
{
Decorate(context =>
new CachingAggregateRootRepositoryDecorator(
context.Get<IAggregateRootRepository>(),
new InMemorySnapshotCache
{
ApproximateMaxNumberOfCacheEntries = approximateMaxNumberOfCacheEntries
},
context.Get<IEventStore>(),
context.Get<IDomainEventSerializer>()));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,15 @@
using d60.Cirqus.Aggregates;
using d60.Cirqus.Commands;
using d60.Cirqus.Events;
using d60.Cirqus.Logging;
using d60.Cirqus.Serialization;
using d60.Cirqus.Views;

namespace d60.Cirqus.Config.Configurers
{
class CommandProcessorConfigurationBuilder : ILoggingAndEventStoreConfiguration, IOptionalConfiguration<ICommandProcessor>
internal class CommandProcessorConfigurationBuilder : ILoggingAndEventStoreConfiguration, IOptionalConfiguration<ICommandProcessor>
{
static Logger _logger;

readonly ConfigurationContainer _container = new ConfigurationContainer();

static CommandProcessorConfigurationBuilder()
{
CirqusLoggerFactory.Changed += f => _logger = f.GetCurrentClassLogger();
}

public IEventStoreConfiguration Logging(Action<LoggingConfigurationBuilder> configure)
{
configure(new LoggingConfigurationBuilder(_container));
Expand Down
34 changes: 29 additions & 5 deletions d60.Cirqus/Config/Configurers/ConfigurationBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,33 +2,33 @@

namespace d60.Cirqus.Config.Configurers
{
public abstract class ConfigurationBuilder : IRegistrar
public abstract class ConfigurationBuilder
{
readonly IRegistrar _registrar;
protected IRegistrar _registrar;

protected ConfigurationBuilder(IRegistrar registrar)
{
_registrar = registrar;
}

/// <summary>
/// Registers a factory method for the given service
/// Registers a factory method for <typeparamref name="TService"/>
/// </summary>
public void Register<TService>(Func<ResolutionContext, TService> serviceFactory)
{
_registrar.Register(serviceFactory);
}

/// <summary>
/// Registers a specific instance (which by definition is not a decorator)
/// Registers a specific instance (which by definition is not a decorator) for <typeparamref name="TService"/>
/// </summary>
public void RegisterInstance<TService>(TService instance, bool multi = false)
{
_registrar.RegisterInstance(instance, multi);
}

/// <summary>
/// Registers a factory method for decorating the given type
/// Registers a factory method for decorating <typeparamref name="TService"/>
/// </summary>
public void Decorate<TService>(Func<ResolutionContext, TService> serviceFactory)
{
Expand All @@ -47,5 +47,29 @@ public bool HasService<TService>(bool checkForPrimary = false)
public abstract class ConfigurationBuilder<TService> : ConfigurationBuilder
{
protected ConfigurationBuilder(IRegistrar registrar) : base(registrar) {}

/// <summary>
/// Registers a factory method for <typeparamref name="TService"/>
/// </summary>
public void Register(Func<ResolutionContext, TService> serviceFactory)
{
_registrar.Register(serviceFactory);
}

/// <summary>
/// Registers a specific instance (which by definition is not a decorator) for <typeparamref name="TService"/>
/// </summary>
public void RegisterInstance(TService instance, bool multi = false)
{
_registrar.RegisterInstance(instance, multi);
}

/// <summary>
/// Registers a factory method for decorating <typeparamref name="TService"/>
/// </summary>
public void Decorate(Func<ResolutionContext, TService> serviceFactory)
{
_registrar.Decorate(serviceFactory);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,24 +1,79 @@
using System;
using d60.Cirqus.Aggregates;
using d60.Cirqus.Events;
using d60.Cirqus.Serialization;
using d60.Cirqus.Views;
using d60.Cirqus.Views.ViewManagers;

namespace d60.Cirqus.Config.Configurers
{
public class EventDispatcherConfigurationBuilder : ConfigurationBuilder<IEventDispatcher>
{
public EventDispatcherConfigurationBuilder(IRegistrar registrar) : base(registrar) { }

public void AddEventDispatcher(Func<ResolutionContext, IEventDispatcher> eventDispatcherFunc)
/// <summary>
/// Registers a <see cref="Views.ViewManagerEventDispatcher"/> to manage the given views. Can be called multiple times in order to register
/// multiple "pools" of views (each will be managed by a dedicated worker thread).
/// </summary>
public ViewManagerEventDispatcherConfiguationBuilder UseViewManagerEventDispatcher(params IViewManager[] viewManagers)
{
var viewManagerConfigurationContainer = new ConfigurationContainer();

UseEventDispatcher(context =>
{
var viewManagerContext = viewManagerConfigurationContainer.CreateContext();

context.AddChildContext(viewManagerContext);

var eventDispatcher = new ViewManagerEventDispatcher(
context.Get<IAggregateRootRepository>(),
context.Get<IEventStore>(),
context.Get<IDomainEventSerializer>(),
context.Get<IDomainTypeNameMapper>(),
viewManagers);

var waitHandle = viewManagerContext.GetOrDefault<ViewManagerWaitHandle>();
if (waitHandle != null)
{
waitHandle.Register(eventDispatcher);
}

var maxDomainEventsPerBatch = viewManagerContext.GetOrDefault<int>();
if (maxDomainEventsPerBatch > 0)
{
eventDispatcher.MaxDomainEventsPerBatch = maxDomainEventsPerBatch;
}

return eventDispatcher;
});

return new ViewManagerEventDispatcherConfiguationBuilder(viewManagerConfigurationContainer);
}

/// <summary>
/// Registers the given event dispatcher. Can be called multiple times.
/// </summary>
public void UseEventDispatcher(IEventDispatcher eventDispatcher)
{
UseEventDispatcher(context => eventDispatcher);
}

/// <summary>
/// Registers the given <see cref="IEventDispatcher"/> func, using a <see cref="CompositeEventDispatcher"/> to compose with
/// previously registered event dispatchers.
/// </summary>
public void UseEventDispatcher(Func<ResolutionContext, IEventDispatcher> factory)
{
if (HasService<IEventDispatcher>())
{
Decorate<IEventDispatcher>(context =>
Decorate(context =>
new CompositeEventDispatcher(
context.Get<IEventDispatcher>(),
eventDispatcherFunc(context)));
factory(context)));
}
else
{
Register(eventDispatcherFunc);
Register(factory);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,14 @@ namespace d60.Cirqus.Config.Configurers
public class EventStoreConfigurationBuilder : ConfigurationBuilder<IEventStore>
{
public EventStoreConfigurationBuilder(IRegistrar registrar) : base(registrar) { }

/// <summary>
/// Enables an in-memory event cache that caches the most recently used events. <see cref="maxCacheEntries"/> specifies
/// the approximate number of events to be held in the cache
/// </summary>
public void EnableCaching(int maxCacheEntries)
{
Decorate(context => new CachingEventStoreDecorator(context.Get<IEventStore>()));
}
}
}
30 changes: 29 additions & 1 deletion d60.Cirqus/Config/Configurers/LoggingConfigurationBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,35 @@
namespace d60.Cirqus.Config.Configurers
using d60.Cirqus.Logging;
using d60.Cirqus.Logging.Console;
using d60.Cirqus.Logging.Null;

namespace d60.Cirqus.Config.Configurers
{
public class LoggingConfigurationBuilder : ConfigurationBuilder
{
public LoggingConfigurationBuilder(IRegistrar registrar) : base(registrar) { }

/// <summary>
/// Configures Cirqus to log using the console.
/// </summary>
public void UseConsole(Logger.Level minLevel = Logger.Level.Info)
{
Use(new ConsoleLoggerFactory(minLevel: minLevel));
}

/// <summary>
/// Configures Cirqus to not log anything at all.
/// </summary>
public void None()
{
Use(new NullLoggerFactory());
}

/// <summary>
/// Configures Cirqus get its logger using specified factory.
/// </summary>
public void Use(CirqusLoggerFactory factory)
{
CirqusLoggerFactory.Current = factory;
}
}
}
Loading

0 comments on commit aca05fa

Please sign in to comment.