Skip to content

Commit 80a30eb

Browse files
committed
Up and running with the ability to get read model instances as collection and project multiple events not bound to an event source id
1 parent d7edf3e commit 80a30eb

File tree

18 files changed

+431
-0
lines changed

18 files changed

+431
-0
lines changed

.github/workflows/dotnet-build.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ jobs:
116116
- 'for_JobsManager'
117117
- 'for_Reactors'
118118
- 'for_Reducers'
119+
- 'for_ReadModels'
119120
- 'for_Webhooks'
120121
- 'Jobs'
121122
- 'Projections'
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Copyright (c) Cratis. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using Cratis.Chronicle.Events;
5+
6+
namespace Cratis.Chronicle.InProcess.Integration.for_ReadModels;
7+
8+
[EventType("2d1f20ee-f0fd-5b82-cfa9-cf6eefb23c63")]
9+
public record AnotherEvent(string Value);
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Copyright (c) Cratis. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using Cratis.Chronicle.Events;
5+
6+
namespace Cratis.Chronicle.InProcess.Integration.for_ReadModels;
7+
8+
[EventType("1c0f19dd-e9fc-4a71-bfa8-bf5eefb12b52")]
9+
public record SomeEvent(int Number);
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright (c) Cratis. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
namespace Cratis.Chronicle.InProcess.Integration.for_ReadModels;
5+
6+
public class SomeProjection : IProjectionFor<SomeReadModel>
7+
{
8+
public ProjectionId Identifier => "some-projection";
9+
10+
public void Define(IProjectionBuilderFor<SomeReadModel> builder) => builder
11+
.From<SomeEvent>(e => e
12+
.Set(m => m.Number).To(e => e.Number))
13+
.From<AnotherEvent>(e => e
14+
.Set(m => m.Value).To(e => e.Value));
15+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Copyright (c) Cratis. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
namespace Cratis.Chronicle.InProcess.Integration.for_ReadModels;
5+
6+
public record SomeReadModel(int Number, string Value);
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright (c) Cratis. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using Cratis.Chronicle.Events;
5+
6+
namespace Cratis.Chronicle.InProcess.Integration.for_ReadModels.given;
7+
8+
public class a_projection_with_events(ChronicleInProcessFixture chronicleInProcessFixture) : Specification(chronicleInProcessFixture)
9+
{
10+
public EventSourceId EventSourceId;
11+
public SomeEvent FirstEvent;
12+
public AnotherEvent SecondEvent;
13+
14+
public override IEnumerable<Type> EventTypes => [typeof(SomeEvent), typeof(AnotherEvent)];
15+
public override IEnumerable<Type> Projections => [typeof(SomeProjection)];
16+
17+
protected void Establish()
18+
{
19+
EventSourceId = "some-source";
20+
FirstEvent = new SomeEvent(42);
21+
SecondEvent = new AnotherEvent("test-value");
22+
}
23+
24+
protected async Task AppendEvents()
25+
{
26+
await EventStore.EventLog.Append(EventSourceId, FirstEvent);
27+
await EventStore.EventLog.Append(EventSourceId, SecondEvent);
28+
}
29+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright (c) Cratis. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using Cratis.Chronicle.ReadModels;
5+
using context = Cratis.Chronicle.InProcess.Integration.for_ReadModels.when_getting_instance_with_unspecified_key.and_events_exist.context;
6+
7+
namespace Cratis.Chronicle.InProcess.Integration.for_ReadModels.when_getting_instance_with_unspecified_key;
8+
9+
[Collection(ChronicleCollection.Name)]
10+
public class and_events_exist(context context) : Given<context>(context)
11+
{
12+
public class context(ChronicleInProcessFixture chronicleInProcessFixture) : given.a_projection_with_events(chronicleInProcessFixture)
13+
{
14+
public SomeReadModel Result;
15+
16+
async Task Because()
17+
{
18+
await AppendEvents();
19+
Result = await EventStore.ReadModels.GetInstanceById<SomeReadModel>(ReadModelKey.Unspecified);
20+
}
21+
}
22+
23+
[Fact] void should_have_number_from_first_event() => Context.Result.Number.ShouldEqual(Context.FirstEvent.Number);
24+
[Fact] void should_have_value_from_second_event() => Context.Result.Value.ShouldEqual(Context.SecondEvent.Value);
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
// Copyright (c) Cratis. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using Cratis.Chronicle.Events;
5+
using Cratis.Chronicle.ReadModels;
6+
using context = Cratis.Chronicle.InProcess.Integration.for_ReadModels.when_getting_instance_with_unspecified_key.and_multiple_event_sources_exist.context;
7+
8+
namespace Cratis.Chronicle.InProcess.Integration.for_ReadModels.when_getting_instance_with_unspecified_key;
9+
10+
[Collection(ChronicleCollection.Name)]
11+
public class and_multiple_event_sources_exist(context context) : Given<context>(context)
12+
{
13+
public class context(ChronicleInProcessFixture chronicleInProcessFixture) : given.a_projection_with_events(chronicleInProcessFixture)
14+
{
15+
public EventSourceId SecondEventSourceId;
16+
public SomeEvent ThirdEvent;
17+
public AnotherEvent FourthEvent;
18+
public SomeReadModel Result;
19+
20+
void Establish()
21+
{
22+
SecondEventSourceId = "another-source";
23+
ThirdEvent = new SomeEvent(100);
24+
FourthEvent = new AnotherEvent("another-value");
25+
}
26+
27+
async Task Because()
28+
{
29+
await AppendEvents();
30+
await EventStore.EventLog.Append(SecondEventSourceId, ThirdEvent);
31+
await EventStore.EventLog.Append(SecondEventSourceId, FourthEvent);
32+
Result = await EventStore.ReadModels.GetInstanceById<SomeReadModel>(ReadModelKey.Unspecified);
33+
}
34+
}
35+
36+
[Fact] void should_have_number_from_last_event() => Context.Result.Number.ShouldEqual(Context.ThirdEvent.Number);
37+
[Fact] void should_have_value_from_last_event() => Context.Result.Value.ShouldEqual(Context.FourthEvent.Value);
38+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright (c) Cratis. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using context = Cratis.Chronicle.InProcess.Integration.for_ReadModels.when_getting_instances.with_limited_event_count.context;
5+
6+
namespace Cratis.Chronicle.InProcess.Integration.for_ReadModels.when_getting_instances;
7+
8+
[Collection(ChronicleCollection.Name)]
9+
public class with_limited_event_count(context context) : Given<context>(context)
10+
{
11+
public class context(ChronicleInProcessFixture chronicleInProcessFixture) : given.a_projection_with_events(chronicleInProcessFixture)
12+
{
13+
public IEnumerable<SomeReadModel> Results;
14+
15+
async Task Because()
16+
{
17+
await AppendEvents();
18+
Results = await EventStore.ReadModels.GetInstances<SomeReadModel>(1);
19+
}
20+
}
21+
22+
[Fact] void should_return_single_instance() => Context.Results.Count().ShouldEqual(1);
23+
[Fact] void should_have_number_from_first_event() => Context.Results.First().Number.ShouldEqual(Context.FirstEvent.Number);
24+
[Fact] void should_not_have_value_from_second_event() => Context.Results.First().Value.ShouldBeNull();
25+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Copyright (c) Cratis. All rights reserved.
2+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3+
4+
using Cratis.Chronicle.Events;
5+
using context = Cratis.Chronicle.InProcess.Integration.for_ReadModels.when_getting_instances.with_multiple_event_sources.context;
6+
7+
namespace Cratis.Chronicle.InProcess.Integration.for_ReadModels.when_getting_instances;
8+
9+
[Collection(ChronicleCollection.Name)]
10+
public class with_multiple_event_sources(context context) : Given<context>(context)
11+
{
12+
public class context(ChronicleInProcessFixture chronicleInProcessFixture) : given.a_projection_with_events(chronicleInProcessFixture)
13+
{
14+
public EventSourceId SecondEventSourceId;
15+
public SomeEvent ThirdEvent;
16+
public AnotherEvent FourthEvent;
17+
public IEnumerable<SomeReadModel> Results;
18+
19+
void Establish()
20+
{
21+
SecondEventSourceId = "another-source";
22+
ThirdEvent = new SomeEvent(100);
23+
FourthEvent = new AnotherEvent("another-value");
24+
}
25+
26+
async Task Because()
27+
{
28+
await AppendEvents();
29+
await EventStore.EventLog.Append(SecondEventSourceId, ThirdEvent);
30+
await EventStore.EventLog.Append(SecondEventSourceId, FourthEvent);
31+
Results = await EventStore.ReadModels.GetInstances<SomeReadModel>();
32+
}
33+
}
34+
35+
[Fact] void should_return_two_instances() => Context.Results.Count().ShouldEqual(2);
36+
[Fact] void should_have_first_instance_with_first_events() => Context.Results.First().Number.ShouldEqual(Context.FirstEvent.Number);
37+
[Fact] void should_have_first_instance_value() => Context.Results.First().Value.ShouldEqual(Context.SecondEvent.Value);
38+
[Fact] void should_have_second_instance_with_second_events() => Context.Results.Last().Number.ShouldEqual(Context.ThirdEvent.Number);
39+
[Fact] void should_have_second_instance_value() => Context.Results.Last().Value.ShouldEqual(Context.FourthEvent.Value);
40+
}

0 commit comments

Comments
 (0)