Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
rasmus committed Oct 19, 2015
2 parents 7f42c6d + f99c792 commit 6c757db
Show file tree
Hide file tree
Showing 33 changed files with 985 additions and 26 deletions.
105 changes: 105 additions & 0 deletions Documentation/Configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Configure EventFlow

To get EventFlow up and running, you need an instance of `IEventFlowOptions`
which is created using the `EventFlowOptions.New` static property. From here
you use extension methods and extension methods to setup EventFlow to your
needs.

## Basic example

Here's the very minimum that you will need to get EventFlow up and running
with a in-memory configuration.

```csharp
using (var resolver = EventFlowOptions.New
.AddDefaults(typeof(YouApplication).Assembly)
.CreateResolver())
{
// Do stuff
// Don't dispose the 'resolver' until application shutdown!
}
```

First the default types and services are registered from your application using
the `AddDefaults(...)` method.

Versioned types, types that might exist in multiple versions as the application
evolves, are loaded into EventFlow.

* [Event types](./ValueObjects.md) are loaded into the `IEventDefinitionService`
* [Command types](./Commands.md) are loaded into the `ICommandDefinitionService`
* [Job types](./Jobs.md) are loaded into the `IJobDefinitionService`

Services with known interfaces are registered in the built-in IoC container.

* Command handlers, i.e., `ICommandHandler<,,>` implementations
* Meta data providers, i.e., `IMetadataProvider` implementations
* Subscribers, i.e., `ISubscribeSynchronousTo<,,>` and `ISubscribeSynchronousToAll` implementations
* Event upgraders, i.e., `IEventUpgrader<,>` implementations
* Query handlers, i.e., `IQueryHandler<,>` implementations

Note that you can use another IoC container, e.g. Autofac using the
`EventFlow.Autofac` NuGet package. If using this package, you can even skip
the `CreateResolver()` call, as EventFlow will automatically configure itself
when the container is ready.

The final step of configuring EventFlow, is to call `CreateResolver()` which
configures the IoC container and its through this that you can access e.g.
the `ICommandBus` which allows you to publish commands.

## Configuration methods

Note that almost every single one of the configuration methods on
`IEventFlowOptions` is implemented as extension methods and you will need
to add the appropriate namespace, e.g. `EventFlow.Extensions`.

### Versioned types

* `AddEvents`
* `AddCommands`
* `AddJobs`

### Services

**General**
* `RegisterServices`, configure other services or override existing
* `UseServiceRegistration`, use an alternative IoC container
* `UseAutofacContainerBuilder` in NuGet package `EventFlow.Autofac`
* `RegisterModule`, register modules

**Aggregates**
* `UseResolverAggregateRootFactory`
* `UseAutofacAggregateRootFactory` in the NuGet package `EventFlow.Autofac`

* `AddAggregateRoots`, add aggregates if using the
`UseResolverAggregateRootFactory` or `UseAutofacAggregateRootFactory`
**Command handlers**
* `AddCommandHandlers`

**Subscribers**
* `AddSubscribers`

**Event upgraders**
* `AddEventUpgraders`

**Metadata providers**
* `AddMetadataProviders`

**Event stores**
* `UseEventStore`
* `UseFilesEventStore`
* `UseEventStoreEventStore` in NuGet package `EventFlow.EventStores.EventStore`
* `UseMssqlEventStore` in NuGet package `EventFlow.EventStores.MsSql`

**Read models and stores**
* `UseReadStoreFor<TReadStore, TReadModel>`
* `UseReadStoreFor<TReadStore, TReadModel, TReadModelLocator>>`
* `UseInMemoryReadStoreFor<TReadModel>`
* `UseInMemoryReadStoreFor<TReadModel, TReadModelLocator>`

**Jobs and schedulers**
* `UseHangfireJobScheduler` in the NuGet package `EventFlow.Hangfire`

**Queries and handlers**
* `AddQueryHandlers`
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@ the [dos and don'ts](./Documentation/DoesAndDonts.md) and the
### Features

* **CQRS+ES framework**
* **Async/await first:** Every part of EventFlow is written using async/await. In
some places EventFlow exposes sync methods like e.g. the `ICommandBus`, but these
merely _try_ to do the right thing using an async bridge
* **Async/await first:** Every part of EventFlow is written using async/await.
* **Highly configurable and extendable**
* **Easy to use**
* **No use of threads or background workers making it "web friendly"**
Expand Down Expand Up @@ -158,7 +156,7 @@ several areas that you could help out with.

## Thanks

![ReSharper](./Documentation/Images/logo_resharper.png)
[![ReSharper](./Documentation/Images/logo_resharper.png)](https://www.jetbrains.com/resharper/)


## License
Expand Down
16 changes: 15 additions & 1 deletion RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
### New in 0.18 (not released yet)
### New in 0.19 (not released yet)

* Breaking: `AddDefaults` now also adds the job type definition to the
`IJobsDefinitonService`
* New: Implemented a basic specification pattern by providing
`ISpecification<T>`, an easy-to-use `Specificaion<T>` and a set of extension
methods. Look at the EventFlow specification tests to get started
* Fixed: `IEventDefinitionService`, `ICommandDefinitonService` and
`IJobsDefinitonService` now longer throw an exception if an existing
event is loaded, i.e., multiple calls to `AddEvents(...)`, `AddCommand(...)`
and `AddJobs(...)` no longer throws an exception
* Fixed: `DomainError.With(...)` no longer executes `string.format` if only
one argument is parsed

### New in 0.18.1181 (released 2015-10-07)

* POTENTIAL DATA LOSS for the **files event store**: The EventFlow
internal functionality regarding event stores has been refactored resulting
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ public class MsSqlTestAggregateReadModel : MssqlReadModel, ITestAggregateReadMod
public bool DomainErrorAfterFirstReceived { get; set; }
public int PingsReceived { get; set; }

public void Apply(IReadModelContext context, IDomainEvent<TestAggregate, TestId, PingEvent> e)
public void Apply(IReadModelContext context, IDomainEvent<TestAggregate, TestId, PingEvent> domainEvent)
{
PingsReceived++;
}

public void Apply(IReadModelContext context, IDomainEvent<TestAggregate, TestId, DomainErrorAfterFirstEvent> e)
public void Apply(IReadModelContext context, IDomainEvent<TestAggregate, TestId, DomainErrorAfterFirstEvent> domainEvent)
{
DomainErrorAfterFirstReceived = true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ public class InMemoryTestAggregateReadModel : IReadModel, ITestAggregateReadMode
public bool DomainErrorAfterFirstReceived { get; private set; }
public int PingsReceived { get; private set; }

public void Apply(IReadModelContext context, IDomainEvent<TestAggregate, TestId, DomainErrorAfterFirstEvent> e)
public void Apply(IReadModelContext context, IDomainEvent<TestAggregate, TestId, DomainErrorAfterFirstEvent> domainEvent)
{
DomainErrorAfterFirstReceived = true;
}

public void Apply(IReadModelContext context, IDomainEvent<TestAggregate, TestId, PingEvent> e)
public void Apply(IReadModelContext context, IDomainEvent<TestAggregate, TestId, PingEvent> domainEvent)
{
PingsReceived++;
}
Expand Down
4 changes: 4 additions & 0 deletions Source/EventFlow.Tests/EventFlow.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
<Compile Include="UnitTests\Extensions\AggregatesExtensionsTests.cs" />
<Compile Include="UnitTests\Extensions\StringExtensionsTests.cs" />
<Compile Include="UnitTests\Jobs\JobsFlowTests.cs" />
<Compile Include="UnitTests\Provided\Specifications\AtLeastSpecificationTests.cs" />
<Compile Include="UnitTests\Queries\QueryProcessorTests.cs" />
<Compile Include="UnitTests\ReadStores\ReadModelDomainEventApplierTests.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
Expand All @@ -106,6 +107,9 @@
<Compile Include="UnitTests\EventStores\EventUpgradeManagerTests.cs" />
<Compile Include="UnitTests\ReadStores\ReadModelPopulatorTests.cs" />
<Compile Include="UnitTests\ReadStores\ReadStoreManagerTests.cs" />
<Compile Include="UnitTests\Specifications\SpecificationTests.cs" />
<Compile Include="UnitTests\Specifications\TestSpecifications.cs" />
<Compile Include="UnitTests\Specifications\TestSpecificationsTests.cs" />
<Compile Include="UnitTests\Subscribers\DispatchToEventSubscribersTests.cs" />
<Compile Include="UnitTests\ValueObjects\SingleValueObjectConverterTests.cs" />
<Compile Include="UnitTests\ValueObjects\SingleValueObjectTests.cs" />
Expand Down
4 changes: 2 additions & 2 deletions Source/EventFlow.Tests/IntegrationTests/DomainTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,9 @@ public class PingReadModel :
{
public PingId Id { get; private set; }

public void Apply(IReadModelContext context, IDomainEvent<TestAggregate, TestId, PingEvent> e)
public void Apply(IReadModelContext context, IDomainEvent<TestAggregate, TestId, PingEvent> domainEvent)
{
Id = e.AggregateEvent.PingId;
Id = domainEvent.AggregateEvent.PingId;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,16 @@ public void LoadEventsFollowedByGetEventDefinition_ReturnsCorrectAnswer(string e
eventDefinition.Type.Should().Be(expectedEventType);
}

[Test]
public void CanLoadSameEventMultipleTimes()
{
Assert.DoesNotThrow(() =>
{
Sut.LoadEvents(new[] { typeof(TestEvent), typeof(TestEvent) });
Sut.LoadEvents(new[] { typeof(TestEvent) });
});
}

[Test]
public void CanLoadNull()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
// The MIT License (MIT)
//
// Copyright (c) 2015 Rasmus Mikkelsen
// https://github.com/rasmus/EventFlow
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

using EventFlow.Extensions;
using EventFlow.Tests.UnitTests.Specifications;
using FluentAssertions;
using NUnit.Framework;

namespace EventFlow.Tests.UnitTests.Provided.Specifications
{
public class AtLeastSpecificationTests
{
[TestCase(1, 1, false)]
[TestCase(1, 2, true)]
[TestCase(1, 3, true)]
[TestCase(1, 4, true)]
[TestCase(1, 5, true)]
[TestCase(3, 1, false)]
[TestCase(3, 2, false)]
[TestCase(3, 3, false)]
[TestCase(3, 4, true)]
[TestCase(3, 5, true)]
public void AtLeast_Returns_Correctly(int requiredSpecifications, int obj, bool expectedIsSatisfiedBy)
{
// Arrange
var isAbove1 = new TestSpecifications.IsAboveSpecification(1);
var isAbove2 = new TestSpecifications.IsAboveSpecification(2);
var isAbove3 = new TestSpecifications.IsAboveSpecification(3);
var isAbove4 = new TestSpecifications.IsAboveSpecification(4);
var atLeast = new[] { isAbove1, isAbove2, isAbove3, isAbove4 }.AtLeast(requiredSpecifications);

// Act
var isSatisfiedBy = atLeast.IsSatisfiedBy(obj);

// Assert
isSatisfiedBy.Should().Be(expectedIsSatisfiedBy, string.Join(", ", atLeast.WhyIsNotStatisfiedBy(obj)));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public class PingReadModel : IReadModel,
{
public bool PingEventsReceived { get; private set; }

public void Apply(IReadModelContext context, IDomainEvent<TestAggregate, TestId, PingEvent> e)
public void Apply(IReadModelContext context, IDomainEvent<TestAggregate, TestId, PingEvent> domainEvent)
{
PingEventsReceived = true;
}
Expand All @@ -50,7 +50,7 @@ public class TheOtherPingReadModel : IReadModel,
{
public bool PingEventsReceived { get; private set; }

public void Apply(IReadModelContext context, IDomainEvent<TestAggregate, TestId, PingEvent> e)
public void Apply(IReadModelContext context, IDomainEvent<TestAggregate, TestId, PingEvent> domainEvent)
{
PingEventsReceived = true;
}
Expand All @@ -61,7 +61,7 @@ public class DomainErrorAfterFirstReadModel : IReadModel,
{
public bool DomainErrorAfterFirstEventsReceived { get; private set; }

public void Apply(IReadModelContext context, IDomainEvent<TestAggregate, TestId, DomainErrorAfterFirstEvent> e)
public void Apply(IReadModelContext context, IDomainEvent<TestAggregate, TestId, DomainErrorAfterFirstEvent> domainEvent)
{
DomainErrorAfterFirstEventsReceived = true;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public class ReadModelPopulatorTests : TestsFor<ReadModelPopulator>
public class TestReadModel : IReadModel,
IAmReadModelFor<TestAggregate, TestId, PingEvent>
{
public void Apply(IReadModelContext context, IDomainEvent<TestAggregate, TestId, PingEvent> e)
public void Apply(IReadModelContext context, IDomainEvent<TestAggregate, TestId, PingEvent> domainEvent)
{
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public class ReadStoreManagerTests : TestsFor<SingleAggregateReadStoreManager<IR
public class TestReadModel : IReadModel,
IAmReadModelFor<TestAggregate, TestId, PingEvent>
{
public void Apply(IReadModelContext context, IDomainEvent<TestAggregate, TestId, PingEvent> e)
public void Apply(IReadModelContext context, IDomainEvent<TestAggregate, TestId, PingEvent> domainEvent)
{
}
}
Expand Down
Loading

0 comments on commit 6c757db

Please sign in to comment.