Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
rasmus committed May 8, 2015
2 parents e4e05a9 + e8cf928 commit b8829ad
Show file tree
Hide file tree
Showing 96 changed files with 859 additions and 459 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ to the documentation.
* **Command bus:** Entry point for all command execution.
* **Event store:** Storage of the event stream for aggregates.
Currently there is support for these storage types.
* In-memory
* Files
* In-memory - only for test
* Files - only for test
* [Microsoft SQL Server](./Documentation/ReadStores-MSSQL.md)
* **Read models:** Denormalized representation of aggregate events
optimized for reading fast. Currently there is support for these
read model storage types.
* In-memory
* In-memory - only for test
* Microsoft SQL Server
* [**Metadata:**](./Documentation/Metadata.md)
Additional information for each aggregate event, e.g. the IP of
Expand Down
27 changes: 25 additions & 2 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,30 @@
### New in 0.4
### New in 0.5 (not released yet)

* POTENTIAL DATA LOSS for files event store: Files event store now
stores its log as JSON instead of an `int` in the form
`{"GlobalSequenceNumber":2}`. So rename the current file and put in the
global sequence number before startup
* Breaking: Major changes has been made regarding how the aggregate
identity is implemented and referenced through interfaces. These changes makes
it possible to access the identity type directly though all interface. Some
notable examples are listed here. Note that this has NO impact on how data
is stored!
- `IAggregateRoot` changed to `IAggregateRoot<TIdentity>`
- `ICommand<TAggregate>` changed to `ICommand<TAggregate,TIdentity>`
- `ICommandHandler<TAggregate,TCommand>` changed to
`ICommandHandler<TAggregate,TIdentity, TCommand>`
- `IAmReadModelFor<TEvent>` changed to
`IAmReadModelFor<TAggregate,TIdentity,TEvent>`
- `IDomainEvent<TEvent>` changed to `IDomainEvent<TAggregate,TIdentity>`
* New: `ICommandBus.Publish` now takes a `CancellationToken` argument
* Fixed: MSSQL should list columns to SELECT when fetching events


### New in 0.4.353 (released 2015-05-05)

* Breaking: `ValueObject` now uses public properties instead of both
private and public fields
- Braking: Aggregate IDs are no longer `string` but objects implementing
* Breaking: Aggregate IDs are no longer `string` but objects implementing
`IIdentity`
* Breaking: MSSQL transient exceptions are now retried
* Breaking: All methods on `IMsSqlConnection` has an extra `Label` argument
Expand All @@ -14,6 +36,7 @@
* Fixed: `NullReferenceException` thrown if `null` was stored
in `SingleValueObject` and `ToString()` was called


### New in 0.3.292 (released 2015-04-30)

* First stable version of EventFlow
17 changes: 12 additions & 5 deletions Source/EventFlow.EventStores.MsSql/MssqlEventStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ public class EventDataModel : ICommittedDomainEvent
_connection = connection;
}

protected override async Task<IReadOnlyCollection<ICommittedDomainEvent>> CommitEventsAsync<TAggregate>(
IIdentity id,
protected override async Task<IReadOnlyCollection<ICommittedDomainEvent>> CommitEventsAsync<TAggregate, TIdentity>(
TIdentity id,
IReadOnlyCollection<SerializedEvent> serializedEvents,
CancellationToken cancellationToken)
{
Expand Down Expand Up @@ -142,11 +142,18 @@ OUTPUT CAST(INSERTED.GlobalSequenceNumber as bigint)
return eventDataModels;
}

protected override async Task<IReadOnlyCollection<ICommittedDomainEvent>> LoadCommittedEventsAsync<TAggregate>(
IIdentity id,
protected override async Task<IReadOnlyCollection<ICommittedDomainEvent>> LoadCommittedEventsAsync<TAggregate, TIdentity>(
TIdentity id,
CancellationToken cancellationToken)
{
const string sql = @"SELECT * FROM EventFlow WHERE AggregateId = @AggregateId ORDER BY AggregateSequenceNumber ASC";
const string sql = @"
SELECT
GlobalSequenceNumber, BatchId, AggregateId, AggregateName, Data, Metadata, AggregateSequenceNumber
FROM EventFlow
WHERE
AggregateId = @AggregateId
ORDER BY
AggregateSequenceNumber ASC";
var eventDataModels = await _connection.QueryAsync<EventDataModel>(
Label.Named("mssql-fetch-events"),
cancellationToken,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ public override IRootResolver CreateRootResolver(EventFlowOptions eventFlowOptio
var resolver = eventFlowOptions
.ConfigureMsSql(MsSqlConfiguration.New.SetConnectionString(TestDatabase.ConnectionString))
.UseEventStore<MsSqlEventStore>()
.UseMssqlReadModel<TestAggregate, TestAggregateReadModel>()
.UseMssqlReadModel<TestAggregate, TestId, TestAggregateReadModel>()
.CreateResolver();

MsSqlConnection = resolver.Resolve<IMsSqlConnection>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
using EventFlow.Aggregates;
using EventFlow.ReadStores;
using EventFlow.ReadStores.MsSql;
using EventFlow.TestHelpers.Aggregates.Test;
using EventFlow.TestHelpers.Aggregates.Test.Events;
using EventFlow.TestHelpers.Aggregates.Test.ReadModels;

Expand All @@ -33,12 +34,12 @@ public class TestAggregateReadModel : MssqlReadModel, ITestAggregateReadModel
public bool DomainErrorAfterFirstReceived { get; set; }
public int PingsReceived { get; set; }

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

public void Apply(IReadModelContext context, IDomainEvent<DomainErrorAfterFirstEvent> e)
public void Apply(IReadModelContext context, IDomainEvent<TestAggregate, TestId, DomainErrorAfterFirstEvent> e)
{
DomainErrorAfterFirstReceived = true;
}
Expand Down
4 changes: 2 additions & 2 deletions Source/EventFlow.Owin.Tests/IntegrationTests/Site/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@ public void Configuration(IAppBuilder appBuilder)

var container = EventFlowOptions.New
.UseAutofacContainerBuilder(containerBuilder)
.AddEvents(EventFlowTest.Assembly)
.AddCommandHandlers(EventFlowTest.Assembly)
.AddEvents(EventFlowTestHelpers.Assembly)
.AddCommandHandlers(EventFlowTestHelpers.Assembly)
.AddOwinMetadataProviders()
.UseFilesEventStore(FilesEventStoreConfiguration.Create(storePath))
.RegisterServices(f => f.Register(r => new DirectoryCleaner(storePath), Lifetime.Singleton))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
using EventFlow.Aggregates;
using EventFlow.TestHelpers.Aggregates.Test;
using EventFlow.TestHelpers.Aggregates.Test.Commands;
using EventFlow.TestHelpers.Aggregates.Test.ValueObjects;

namespace EventFlow.Owin.Tests.IntegrationTests.Site
{
Expand All @@ -45,7 +46,7 @@ public class TestAggregateController : ApiController
public async Task<IHttpActionResult> Ping(string id)
{
var testId = TestId.With(id);
var pingCommand = new PingCommand(testId);
var pingCommand = new PingCommand(testId, PingId.New);
await _commandBus.PublishAsync(pingCommand, CancellationToken.None).ConfigureAwait(false);
return Ok();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,12 @@ public class AddRequestHeadersMetadataProvider : IMetadataProvider
_owinContext = owinContext;
}

public IEnumerable<KeyValuePair<string, string>> ProvideMetadata<TAggregate>(
IIdentity id,
public IEnumerable<KeyValuePair<string, string>> ProvideMetadata<TAggregate, TIdentity>(
TIdentity id,
IAggregateEvent aggregateEvent,
IMetadata metadata)
where TAggregate : IAggregateRoot
where TAggregate : IAggregateRoot<TIdentity>
where TIdentity : IIdentity
{
return _owinContext.Request.Headers
.Where(kv => !RequestHeadersToSkip.Contains(kv.Key))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,12 @@ public class AddUriMetadataProvider : IMetadataProvider
_owinContext = owinContext;
}

public IEnumerable<KeyValuePair<string, string>> ProvideMetadata<TAggregate>(
IIdentity id,
public IEnumerable<KeyValuePair<string, string>> ProvideMetadata<TAggregate, TIdentity>(
TIdentity id,
IAggregateEvent aggregateEvent,
IMetadata metadata)
where TAggregate : IAggregateRoot
where TAggregate : IAggregateRoot<TIdentity>
where TIdentity : IIdentity
{
// TODO: Handle X-Forwarded-Proto header

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,12 @@ public class AddUserHostAddressMetadataProvider : IMetadataProvider
_owinContext = owinContext;
}

public IEnumerable<KeyValuePair<string, string>> ProvideMetadata<TAggregate>(
IIdentity id,
public IEnumerable<KeyValuePair<string, string>> ProvideMetadata<TAggregate, TIdentity>(
TIdentity id,
IAggregateEvent aggregateEvent,
IMetadata metadata)
where TAggregate : IAggregateRoot
where TAggregate : IAggregateRoot<TIdentity>
where TIdentity : IIdentity
{
yield return new KeyValuePair<string, string>("remote_ip_address", _owinContext.Request.RemoteIpAddress);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ namespace EventFlow.ReadStores.MsSql.Extensions
{
public static class EventFlowOptionsExtensions
{
public static EventFlowOptions UseMssqlReadModel<TAggregate, TReadModel>(this EventFlowOptions eventFlowOptions)
where TAggregate : IAggregateRoot
public static EventFlowOptions UseMssqlReadModel<TAggregate, TIdentity, TReadModel>(this EventFlowOptions eventFlowOptions)
where TAggregate : IAggregateRoot<TIdentity>
where TIdentity : IIdentity
where TReadModel : IMssqlReadModel, new()
{
eventFlowOptions.RegisterServices(f =>
Expand All @@ -37,7 +38,7 @@ public static class EventFlowOptionsExtensions
{
f.Register<IReadModelSqlGenerator, ReadModelSqlGenerator>(Lifetime.Singleton);
}
f.Register<IReadModelStore<TAggregate>, MssqlReadModelStore<TAggregate, TReadModel>>();
f.Register<IReadModelStore<TAggregate, TIdentity>, MssqlReadModelStore<TAggregate, TIdentity, TReadModel>>();
});

return eventFlowOptions;
Expand Down
5 changes: 3 additions & 2 deletions Source/EventFlow.ReadStores.MsSql/IMssqlReadModelStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@

namespace EventFlow.ReadStores.MsSql
{
public interface IMssqlReadModelStore<TAggregate, TReadModel> : IReadModelStore<TAggregate>
public interface IMssqlReadModelStore<TAggregate, in TIdentity, TReadModel> : IReadModelStore<TAggregate, TIdentity>
where TReadModel : IMssqlReadModel, new()
where TAggregate : IAggregateRoot
where TAggregate : IAggregateRoot<TIdentity>
where TIdentity : IIdentity
{
}
}
11 changes: 6 additions & 5 deletions Source/EventFlow.ReadStores.MsSql/MssqlReadModelStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,12 @@

namespace EventFlow.ReadStores.MsSql
{
public class MssqlReadModelStore<TAggregate, TReadModel> :
ReadModelStore<TAggregate, TReadModel>,
IMssqlReadModelStore<TAggregate, TReadModel>
public class MssqlReadModelStore<TAggregate, TIdentity, TReadModel> :
ReadModelStore<TAggregate, TIdentity, TReadModel>,
IMssqlReadModelStore<TAggregate, TIdentity, TReadModel>
where TAggregate : IAggregateRoot<TIdentity>
where TIdentity : IIdentity
where TReadModel : IMssqlReadModel, new()
where TAggregate : IAggregateRoot
{
private readonly IMsSqlConnection _connection;
private readonly IReadModelSqlGenerator _readModelSqlGenerator;
Expand All @@ -51,7 +52,7 @@ public class MssqlReadModelStore<TAggregate, TReadModel> :
}

public override async Task UpdateReadModelAsync(
IIdentity id,
TIdentity id,
IReadOnlyCollection<IDomainEvent> domainEvents,
CancellationToken cancellationToken)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@

namespace EventFlow.TestHelpers.Aggregates.Test.Commands
{
public class DoesNothingCommand : Command<TestAggregate>
public class DoesNothingCommand : Command<TestAggregate, TestId>
{
public DoesNothingCommand(TestId id) : base(id)
{
}
}

public class DoesNothingCommandHandler : CommandHandler<TestAggregate, DoesNothingCommand>
public class DoesNothingCommandHandler : CommandHandler<TestAggregate, TestId, DoesNothingCommand>
{
public override Task ExecuteAsync(TestAggregate aggregate, DoesNothingCommand command, CancellationToken cancellationToken)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,16 @@

using System.Threading;
using System.Threading.Tasks;
using EventFlow.Aggregates;
using EventFlow.Commands;

namespace EventFlow.TestHelpers.Aggregates.Test.Commands
{
public class DomainErrorAfterFirstCommand : Command<TestAggregate>
public class DomainErrorAfterFirstCommand : Command<TestAggregate, TestId>
{
public DomainErrorAfterFirstCommand(IIdentity id) : base(id) { }
public DomainErrorAfterFirstCommand(TestId id) : base(id) { }
}

public class DomainErrorAfterFirstCommandHander : CommandHandler<TestAggregate, DomainErrorAfterFirstCommand>
public class DomainErrorAfterFirstCommandHander : CommandHandler<TestAggregate, TestId, DomainErrorAfterFirstCommand>
{
public override Task ExecuteAsync(TestAggregate aggregate, DomainErrorAfterFirstCommand command, CancellationToken cancellationToken)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,21 +22,26 @@

using System.Threading;
using System.Threading.Tasks;
using EventFlow.Aggregates;
using EventFlow.Commands;
using EventFlow.TestHelpers.Aggregates.Test.ValueObjects;

namespace EventFlow.TestHelpers.Aggregates.Test.Commands
{
public class PingCommand : Command<TestAggregate>
public class PingCommand : Command<TestAggregate, TestId>
{
public PingCommand(IIdentity id) : base (id) { }
public PingId PingId { get; private set; }

public PingCommand(TestId id, PingId pingId) : base (id)
{
PingId = pingId;
}
}

public class PingCommandHandler : CommandHandler<TestAggregate, PingCommand>
public class PingCommandHandler : CommandHandler<TestAggregate, TestId, PingCommand>
{
public override Task ExecuteAsync(TestAggregate aggregate, PingCommand command, CancellationToken cancellationToken)
{
aggregate.Ping();
aggregate.Ping(command.PingId);
return Task.FromResult(0);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

namespace EventFlow.TestHelpers.Aggregates.Test.Events
{
public class DomainErrorAfterFirstEvent : AggregateEvent<TestAggregate>
public class DomainErrorAfterFirstEvent : AggregateEvent<TestAggregate, TestId>
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,16 @@
// 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;
using EventFlow.Aggregates;
using EventFlow.TestHelpers.Aggregates.Test.ValueObjects;

namespace EventFlow.TestHelpers.Aggregates.Test.Events
{
public class PingEvent : AggregateEvent<TestAggregate>
public class PingEvent : AggregateEvent<TestAggregate, TestId>
{
public Guid PingId { get; private set; }
public PingId PingId { get; private set; }

public PingEvent(Guid pingId)
public PingEvent(PingId pingId)
{
PingId = pingId;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@
namespace EventFlow.TestHelpers.Aggregates.Test.ReadModels
{
public interface ITestAggregateReadModel :
IAmReadModelFor<DomainErrorAfterFirstEvent>,
IAmReadModelFor<PingEvent>
IAmReadModelFor<TestAggregate, TestId, DomainErrorAfterFirstEvent>,
IAmReadModelFor<TestAggregate, TestId, PingEvent>
{
bool DomainErrorAfterFirstReceived { get; }
int PingsReceived { get; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ public class TestAggregateReadModel : IReadModel, ITestAggregateReadModel
public bool DomainErrorAfterFirstReceived { get; private set; }
public int PingsReceived { get; private set; }

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

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

0 comments on commit b8829ad

Please sign in to comment.