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 26, 2015
2 parents 96e7f90 + 8c5043c commit 876228f
Show file tree
Hide file tree
Showing 111 changed files with 4,067 additions and 100 deletions.
6 changes: 6 additions & 0 deletions Documentation/FAQ.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# FAQ - frequently asked questions

#### How can I ensure that only specific users can execute commands?

You should implement a _decorator_ for the `ICommadBus` that does the authentication.
Have a look at the [decorator](./Customize.md#decorating-implementations) documentation
to see how this can be achieved.

#### Why isn't there a "global sequence number" on domain events?

While this is easy to support in some event stores like MSSQL, it doesn't
Expand Down
23 changes: 23 additions & 0 deletions EventFlow.sln
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventFlow.ReadStores.Elasti
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventFlow.ReadStores.Elasticsearch.Tests", "Source\EventFlow.ReadStores.Elasticsearch.Tests\EventFlow.ReadStores.Elasticsearch.Tests.csproj", "{D4D7E41C-1473-4449-A128-CA4383783E6C}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{7F20CC09-6988-40BC-8693-80E0F7022926}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventFlow.Examples.Shipping", "Source\EventFlow.Examples.Shipping\EventFlow.Examples.Shipping.csproj", "{B07DD7F2-68EE-4BC7-8E37-E84BFA3F5B39}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventFlow.Examples.Shipping.Queries.InMemory", "Source\EventFlow.Examples.Shipping.Queries.InMemory\EventFlow.Examples.Shipping.Queries.InMemory.csproj", "{079DC9A6-7740-476A-BC4F-D74D8D7A32AC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EventFlow.Examples.Shipping.Tests", "Source\EventFlow.Examples.Shipping.Tests\EventFlow.Examples.Shipping.Tests.csproj", "{A6F9C84B-27F6-4179-9768-4AA2099405FC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -137,6 +145,18 @@ Global
{D4D7E41C-1473-4449-A128-CA4383783E6C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D4D7E41C-1473-4449-A128-CA4383783E6C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D4D7E41C-1473-4449-A128-CA4383783E6C}.Release|Any CPU.Build.0 = Release|Any CPU
{B07DD7F2-68EE-4BC7-8E37-E84BFA3F5B39}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B07DD7F2-68EE-4BC7-8E37-E84BFA3F5B39}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B07DD7F2-68EE-4BC7-8E37-E84BFA3F5B39}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B07DD7F2-68EE-4BC7-8E37-E84BFA3F5B39}.Release|Any CPU.Build.0 = Release|Any CPU
{079DC9A6-7740-476A-BC4F-D74D8D7A32AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{079DC9A6-7740-476A-BC4F-D74D8D7A32AC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{079DC9A6-7740-476A-BC4F-D74D8D7A32AC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{079DC9A6-7740-476A-BC4F-D74D8D7A32AC}.Release|Any CPU.Build.0 = Release|Any CPU
{A6F9C84B-27F6-4179-9768-4AA2099405FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A6F9C84B-27F6-4179-9768-4AA2099405FC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A6F9C84B-27F6-4179-9768-4AA2099405FC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A6F9C84B-27F6-4179-9768-4AA2099405FC}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -158,5 +178,8 @@ Global
{35180FC7-9135-4E79-8643-0FB825B40871} = {4741A405-DA64-40CC-A726-A2C48CA49DA3}
{404C6099-E82F-4433-8505-5479D76660CD} = {D6F5FF86-C3F3-443D-BEC4-11BDEC5E34FB}
{D4D7E41C-1473-4449-A128-CA4383783E6C} = {D6F5FF86-C3F3-443D-BEC4-11BDEC5E34FB}
{B07DD7F2-68EE-4BC7-8E37-E84BFA3F5B39} = {7F20CC09-6988-40BC-8693-80E0F7022926}
{079DC9A6-7740-476A-BC4F-D74D8D7A32AC} = {7F20CC09-6988-40BC-8693-80E0F7022926}
{A6F9C84B-27F6-4179-9768-4AA2099405FC} = {7F20CC09-6988-40BC-8693-80E0F7022926}
EndGlobalSection
EndGlobal
51 changes: 46 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,29 @@
# EventFlow

[![Join the chat at https://gitter.im/rasmus/EventFlow](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/rasmus/EventFlow?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)

[![NuGet Status](http://img.shields.io/nuget/v/EventFlow.svg?style=flat)](https://www.nuget.org/packages/EventFlow/)
[![Build status](https://ci.appveyor.com/api/projects/status/51yvhvbd909e4o82/branch/develop?svg=true)](https://ci.appveyor.com/project/rasmusnu/eventflow)
<table border="0" cellpadding="0" cellspacing="0">
<tr>
<td>
<img src="./icon-128.png" />
</td>
<td>
<p>
<a href="https://gitter.im/rasmus/EventFlow?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge">
<img src="https://badges.gitter.im/Join%20Chat.svg" />
</a>
</p>
<p>
<a href="https://www.nuget.org/packages/EventFlow/">
<img src="http://img.shields.io/nuget/v/EventFlow.svg?style=flat" />
</a>
</p>
<p>
<a href="https://ci.appveyor.com/project/rasmusnu/eventflow">
<img src="https://ci.appveyor.com/api/projects/status/51yvhvbd909e4o82/branch/develop?svg=true" />
</a>
</p>
</td>
</tr>
</table>

EventFlow is a basic CQRS+ES framework designed to be easy to use.

Expand All @@ -21,6 +41,18 @@ the [dos and don'ts](./Documentation/DoesAndDonts.md) and the
* **Cancellation:** All methods that does IO work or might delay execution (due to
retries), takes a `CancellationToken` argument to allow you to cancel the operation

### Examples

* **[Simple](#simple example):** Shows the key concepts of EventFlow in a few
lines of code
* **Shipping:** To get a more complete example of how EventFlow _could_ be used,
have a look at the shipping example found here in the code base. The example
is based on the shipping example from the book "Domain-Driven Design -
Tackling Complexity in the Heart of Software" by Eric Evans. Its
_in-progress_, but should provide inspiration on how to use EventFlow on a
larger scale. If you have ideas and/or comments, create a pull request or
an issue

### Overview

Here is a list of the EventFlow concepts. Use the links to navigate
Expand Down Expand Up @@ -64,7 +96,7 @@ to the documentation.
EventFlow can be swapped with a custom implementation through the embedded
IoC container.

## Full example
## Simple example
Here's an example on how to use the in-memory event store (default)
and a in-memory read model store.

Expand Down Expand Up @@ -113,6 +145,8 @@ Many of the technical design decisions in EventFlow is based on articles. This
section lists some of them. If you have a link with a relevant article, please
share it by creating an issue with the link.

* **Domain-Driven Design**
- [Domain-Driven Design Reference](https://domainlanguage.com/ddd/reference/) by Eric Evans
* **General CQRS+ES**
- [CQRS Journey by Microsoft](https://msdn.microsoft.com/en-us/library/jj554200.aspx)
published by Microsoft
Expand Down Expand Up @@ -153,6 +187,13 @@ several areas that you could help out with.
across articles that might be relevant for EventFlow, or even better, can
point to specfic EventFlow functionality that might be done better, then
please create an issue or ask in the Gitter chat
* **Expand the shipping example:** If you have ideas on how to expand the
shipping example found in the code base, the please create a pull request
or create an issue
* Give a good understanding of how to use EventFlow
* Give a better understanding of how API changes in EventFlow affect
existing applications
* Provide a platform for DDD discussions

## Thanks

Expand Down
13 changes: 12 additions & 1 deletion RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
### New in 0.20 (not released yet)
### New in 0.21 (not released yet)

* New: Added `Identity<>.NewComb()` that creates sequential unique IDs which can
be used to minimize database fragmentation
* New: Added `IReadModelContext.Resolver` to allow read models to fetch
additional resources when events are applied
* New: The `PrettyPrint()` type extension method, mostly used for verbose
logging, now prints even prettier type names, e.g.
`KeyValuePair<Boolean,Int64>` instead of merely `KeyValuePair'2`, making log
messages slightly more readable

### New in 0.20.1274 (released 2015-10-22)

* Breaking: `Entity<T>` now inherits from `ValueObject` but uses only the `Id`
field as equality component. Override `GetEqualityComponents()` if you have
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// 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 System.Collections.Generic;
using EventFlow.Aggregates;
using EventFlow.Examples.Shipping.Domain.Model.CargoModel;
using EventFlow.Examples.Shipping.Domain.Model.CargoModel.Events;
using EventFlow.Examples.Shipping.Domain.Model.CargoModel.ValueObjects;
using EventFlow.Examples.Shipping.Domain.Model.VoyageModel;
using EventFlow.ReadStores;

namespace EventFlow.Examples.Shipping.Queries.InMemory.Cargos
{
public class CargoReadModel : IReadModel,
IAmReadModelFor<CargoAggregate, CargoId, CargoItinerarySetEvent>,
IAmReadModelFor<CargoAggregate, CargoId, CargoBookedEvent>
{
public CargoId Id { get; private set; }
public HashSet<VoyageId> DependentVoyageIds { get; } = new HashSet<VoyageId>();
public Itinerary Itinerary { get; private set; }
public Route Route { get; private set; }

public void Apply(IReadModelContext context, IDomainEvent<CargoAggregate, CargoId, CargoBookedEvent> domainEvent)
{
Id = domainEvent.AggregateIdentity;
Route = domainEvent.AggregateEvent.Route;
}

public void Apply(IReadModelContext context, IDomainEvent<CargoAggregate, CargoId, CargoItinerarySetEvent> domainEvent)
{
Itinerary = domainEvent.AggregateEvent.Itinerary;
foreach (var transportLeg in domainEvent.AggregateEvent.Itinerary.TransportLegs)
{
DependentVoyageIds.Add(transportLeg.VoyageId);
}
}

public Cargo ToCargo()
{
return new Cargo(
Id,
Route,
Itinerary);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// 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 System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using EventFlow.Examples.Shipping.Domain.Model.CargoModel;
using EventFlow.Examples.Shipping.Domain.Model.CargoModel.Queries;
using EventFlow.Queries;
using EventFlow.ReadStores.InMemory;

namespace EventFlow.Examples.Shipping.Queries.InMemory.Cargos.QueryHandlers
{
public class GetCargosDependentOnVoyageQueryHandler : IQueryHandler<GetCargosDependentOnVoyageQuery, IReadOnlyCollection<Cargo>>
{
private readonly IInMemoryReadStore<CargoReadModel> _readStore;

public GetCargosDependentOnVoyageQueryHandler(
IInMemoryReadStore<CargoReadModel> readStore)
{
_readStore = readStore;
}

public async Task<IReadOnlyCollection<Cargo>> ExecuteQueryAsync(GetCargosDependentOnVoyageQuery query, CancellationToken cancellationToken)
{
var cargoReadModels = await _readStore.FindAsync(
rm => rm.DependentVoyageIds.Contains(query.VoyageId),
cancellationToken)
.ConfigureAwait(false);
return cargoReadModels.Select(rm => rm.ToCargo()).ToList();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// 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 System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using EventFlow.Examples.Shipping.Domain.Model.CargoModel;
using EventFlow.Examples.Shipping.Domain.Model.CargoModel.Queries;
using EventFlow.Queries;
using EventFlow.ReadStores.InMemory;

namespace EventFlow.Examples.Shipping.Queries.InMemory.Cargos.QueryHandlers
{
public class GetCargosQueryHandler : IQueryHandler<GetCargosQuery, IReadOnlyCollection<Cargo>>
{
private readonly IInMemoryReadStore<CargoReadModel> _readStore;

public GetCargosQueryHandler(
IInMemoryReadStore<CargoReadModel> readStore)
{
_readStore = readStore;
}

public async Task<IReadOnlyCollection<Cargo>> ExecuteQueryAsync(GetCargosQuery query, CancellationToken cancellationToken)
{
var cargoIds = new HashSet<CargoId>(query.CargoIds);
var cargoReadModels = await _readStore.FindAsync(
rm => cargoIds.Contains(rm.Id),
cancellationToken)
.ConfigureAwait(false);
return cargoReadModels.Select(rm => rm.ToCargo()).ToList();
}
}
}
Loading

0 comments on commit 876228f

Please sign in to comment.