Skip to content

Commit 11873f9

Browse files
authored
Merge pull request #2289 from Cratis:fix/reload-projections
Fix/reload-projections
2 parents efc4688 + 38a96c5 commit 11873f9

File tree

53 files changed

+419
-288
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+419
-288
lines changed

.github/workflows/dotnet-build.yml

Lines changed: 29 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -135,32 +135,32 @@ jobs:
135135
working-directory: ./Integration/DotNET.InProcess
136136
run: dotnet test --no-build --filter FullyQualifiedName~${{ env.NAMESPACE }} --logger "console;verbosity=normal" --configuration Release --framework net9.0
137137

138-
integration-api:
139-
runs-on: ubuntu-latest
140-
needs: [dotnet-build]
141-
steps:
142-
- name: Checkout code
143-
uses: actions/checkout@v4
144-
145-
- name: Setup .Net
146-
uses: actions/setup-dotnet@v4
147-
with:
148-
dotnet-version: |
149-
${{ env.DOTNET_VERSION }}
150-
151-
- uses: actions/cache@v3
152-
id: dotnet-x64-output
153-
with:
154-
path: ./**/bin
155-
key: ${{ env.DOTNET_CACHE }}
156-
157-
- name: Login to GitHub Docker Registry
158-
uses: docker/login-action@v3
159-
with:
160-
registry: ghcr.io
161-
username: ${{ github.actor }}
162-
password: ${{ secrets.GITHUB_TOKEN }}
163-
164-
- name: Run API integration tests for .Net 9
165-
working-directory: ./Integration/Api
166-
run: dotnet test --no-build --logger "console;verbosity=normal" --configuration Release --framework net9.0
138+
# integration-api:
139+
# runs-on: ubuntu-latest
140+
# needs: [dotnet-build]
141+
# steps:
142+
# - name: Checkout code
143+
# uses: actions/checkout@v4
144+
145+
# - name: Setup .Net
146+
# uses: actions/setup-dotnet@v4
147+
# with:
148+
# dotnet-version: |
149+
# ${{ env.DOTNET_VERSION }}
150+
151+
# - uses: actions/cache@v3
152+
# id: dotnet-x64-output
153+
# with:
154+
# path: ./**/bin
155+
# key: ${{ env.DOTNET_CACHE }}
156+
157+
# - name: Login to GitHub Docker Registry
158+
# uses: docker/login-action@v3
159+
# with:
160+
# registry: ghcr.io
161+
# username: ${{ github.actor }}
162+
# password: ${{ secrets.GITHUB_TOKEN }}
163+
164+
# - name: Run API integration tests for .Net 9
165+
# working-directory: ./Integration/Api
166+
# run: dotnet test --no-build --logger "console;verbosity=normal" --configuration Release --framework net9.0

Directory.Packages.props

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@
2323
<!-- Cratis -->
2424
<PackageVersion Include="Cratis.Fundamentals" Version="7.2.3" />
2525
<PackageVersion Include="Cratis.Metrics.Roslyn" Version="7.2.3" />
26-
<PackageVersion Include="Cratis.Applications" Version="17.23.2" />
27-
<PackageVersion Include="Cratis.Applications.MongoDB" Version="17.23.2" />
28-
<PackageVersion Include="Cratis.Applications.Orleans" Version="17.23.2" />
29-
<PackageVersion Include="Cratis.Applications.Orleans.MongoDB" Version="17.23.2" />
30-
<PackageVersion Include="Cratis.Applications.ProxyGenerator.Build" Version="17.23.2" />
31-
<PackageVersion Include="Cratis.Applications.Swagger" Version="17.23.2" />
26+
<PackageVersion Include="Cratis.Applications" Version="17.24.6" />
27+
<PackageVersion Include="Cratis.Applications.MongoDB" Version="17.24.6" />
28+
<PackageVersion Include="Cratis.Applications.Orleans" Version="17.24.6" />
29+
<PackageVersion Include="Cratis.Applications.Orleans.MongoDB" Version="17.24.6" />
30+
<PackageVersion Include="Cratis.Applications.ProxyGenerator.Build" Version="17.24.6" />
31+
<PackageVersion Include="Cratis.Applications.Swagger" Version="17.24.6" />
3232
<!-- Orleans -->
3333
<PackageVersion Include="Microsoft.Orleans.Core.Abstractions" Version="9.2.1" />
3434
<PackageVersion Include="Microsoft.Orleans.Clustering.AzureStorage" Version="9.2.1" />
@@ -83,7 +83,7 @@
8383
<PackageVersion Include="protobuf-net.Grpc" Version="1.2.5" />
8484
<PackageVersion Include="protobuf-net.Grpc.AspNetCore" Version="1.2.2" />
8585
<PackageVersion Include="Grpc.Net.Client" Version="2.71.0" />
86-
<PackageVersion Include="mongodb.driver" Version="3.5.0" />
86+
<PackageVersion Include="mongodb.driver" Version="3.5.1" />
8787
<PackageVersion Include="AspNetCore.HealthChecks.MongoDb" Version="9.0.0" />
8888
<PackageVersion Include="Swashbuckle.AspNetCore" Version="10.0.1" />
8989
<PackageVersion Include="Swashbuckle.AspNetCore.Filters" Version="10.0.0" />
@@ -104,7 +104,7 @@
104104
<Import Project="$(MSBuildThisFileDirectory)/Directory.Packages.NET8.props" Condition=" '$(TargetFramework)' == 'net8.0' " />
105105

106106
<ItemGroup Condition=" '$(TargetFramework)' == 'net9.0' ">
107-
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.10" />
108-
<PackageVersion Include="Microsoft.Extensions.Options.DataAnnotations" Version="9.0.10" />
107+
<PackageVersion Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.11" />
108+
<PackageVersion Include="Microsoft.Extensions.Options.DataAnnotations" Version="9.0.11" />
109109
</ItemGroup>
110110
</Project>
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+
namespace Cratis.Chronicle.InProcess.Integration.Projections.Scenarios.when_updating_projection_definition;
5+
6+
public class ImmediateProjection : IProjectionFor<TestReadModel>
7+
{
8+
public static bool MapBothProperties { get; set; }
9+
10+
public void Define(IProjectionBuilderFor<TestReadModel> builder)
11+
{
12+
builder.Passive();
13+
if (MapBothProperties)
14+
{
15+
builder.From<TestEvent>(e => e
16+
.Set(m => m.Name).To(e => e.Name)
17+
.Set(m => m.Description).To(e => e.Description));
18+
}
19+
else
20+
{
21+
builder.From<TestEvent>(e => e
22+
.Set(m => m.Name).To(e => e.Name));
23+
}
24+
}
25+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
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.Projections.Scenarios.when_updating_projection_definition;
5+
6+
public class MaterializedProjection : IProjectionFor<TestReadModel>
7+
{
8+
public static bool MapBothProperties { get; set; }
9+
10+
public void Define(IProjectionBuilderFor<TestReadModel> builder)
11+
{
12+
if (MapBothProperties)
13+
{
14+
builder.From<TestEvent>(e => e
15+
.Set(m => m.Name).To(e => e.Name)
16+
.Set(m => m.Description).To(e => e.Description));
17+
}
18+
else
19+
{
20+
builder.From<TestEvent>(e => e
21+
.Set(m => m.Name).To(e => e.Name));
22+
}
23+
}
24+
}
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.Projections.Scenarios.when_updating_projection_definition;
7+
8+
[EventType("96e4ef76-ff62-4e43-9b75-a61f5e8c1c40")]
9+
public record TestEvent(string Name, string Description);
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.Projections.Scenarios.when_updating_projection_definition;
5+
6+
public record TestReadModel(string Name, string? Description = null);
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
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.Projections.Scenarios.when_updating_projection_definition.for_materialized_projection.context;
5+
6+
namespace Cratis.Chronicle.InProcess.Integration.Projections.Scenarios.when_updating_projection_definition;
7+
8+
[Collection(ChronicleCollection.Name)]
9+
public class for_immediate_projection(context context) : Given<context>(context)
10+
{
11+
public class context(ChronicleInProcessFixture chronicleInProcessFixture) : given.a_projection_and_events_appended_to_it<ImmediateProjection, TestReadModel>(chronicleInProcessFixture)
12+
{
13+
public TestReadModel ResultAfterUpdate;
14+
public TestEvent SecondEvent;
15+
public override IEnumerable<Type> EventTypes => [typeof(TestEvent)];
16+
17+
protected override void ConfigureServices(IServiceCollection services)
18+
{
19+
ImmediateProjection.MapBothProperties = false;
20+
services.AddSingleton(new ImmediateProjection());
21+
}
22+
23+
void Establish()
24+
{
25+
EventsToAppend.Add(new TestEvent("First Name", "First Description"));
26+
SecondEvent = new TestEvent("Second Name", "Second Description");
27+
}
28+
29+
async Task Because()
30+
{
31+
Result = (await EventStore.Projections.GetInstanceById<TestReadModel>(EventSourceId)).ReadModel;
32+
ImmediateProjection.MapBothProperties = true;
33+
34+
await EventStore.Projections.Discover();
35+
await EventStore.Projections.Register();
36+
37+
await Projection.WaitTillActive();
38+
39+
var appendResult = await EventStore.EventLog.Append(EventSourceId, SecondEvent);
40+
41+
await Projection.WaitTillReachesEventSequenceNumber(appendResult.SequenceNumber);
42+
43+
ResultAfterUpdate = (await EventStore.Projections.GetInstanceById<TestReadModel>(EventSourceId)).ReadModel;
44+
}
45+
}
46+
47+
[Fact] void should_have_first_result_with_name_only() => Context.Result.Name.ShouldEqual("First Name");
48+
[Fact] void should_not_have_description_in_first_result() => Context.Result.Description.ShouldBeNull();
49+
[Fact] void should_have_updated_result_with_name() => Context.ResultAfterUpdate.Name.ShouldEqual("Second Name");
50+
[Fact] void should_have_description_in_updated_result() => Context.ResultAfterUpdate.Description.ShouldEqual("Second Description");
51+
}
52+
53+
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
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.Projections.Scenarios.when_updating_projection_definition.for_materialized_projection.context;
5+
6+
namespace Cratis.Chronicle.InProcess.Integration.Projections.Scenarios.when_updating_projection_definition;
7+
8+
[Collection(ChronicleCollection.Name)]
9+
public class for_materialized_projection(context context) : Given<context>(context)
10+
{
11+
public class context(ChronicleInProcessFixture chronicleInProcessFixture) : given.a_projection_and_events_appended_to_it<MaterializedProjection, TestReadModel>(chronicleInProcessFixture)
12+
{
13+
public TestReadModel ResultAfterUpdate;
14+
public TestEvent SecondEvent;
15+
16+
public override IEnumerable<Type> EventTypes => [typeof(TestEvent)];
17+
18+
protected override void ConfigureServices(IServiceCollection services)
19+
{
20+
MaterializedProjection.MapBothProperties = false;
21+
services.AddSingleton(new MaterializedProjection());
22+
}
23+
24+
void Establish()
25+
{
26+
EventsToAppend.Add(new TestEvent("First Name", "First Description"));
27+
SecondEvent = new TestEvent("Second Name", "Second Description");
28+
}
29+
30+
async Task Because()
31+
{
32+
MaterializedProjection.MapBothProperties = true;
33+
34+
await EventStore.Projections.Discover();
35+
await EventStore.Projections.Register();
36+
37+
await Projection.WaitTillActive();
38+
39+
var appendResult = await EventStore.EventLog.Append(EventSourceId, SecondEvent);
40+
41+
await Projection.WaitTillReachesEventSequenceNumber(appendResult.SequenceNumber);
42+
43+
ResultAfterUpdate = await GetReadModel(EventSourceId);
44+
}
45+
}
46+
47+
[Fact] void should_have_first_result_with_name_only() => Context.Result.Name.ShouldEqual("First Name");
48+
[Fact] void should_not_have_description_in_first_result() => Context.Result.Description.ShouldBeNull();
49+
[Fact] void should_have_updated_result_with_name() => Context.ResultAfterUpdate.Name.ShouldEqual("Second Name");
50+
[Fact] void should_have_description_in_updated_result() => Context.ResultAfterUpdate.Description.ShouldEqual("Second Description");
51+
}
52+
53+

Source/Clients/DotNET.Specs/Projections/ModelBound/for_ModelBoundProjectionBuilder/when_building_model/with_set_from_context.cs renamed to Source/Clients/DotNET.Specs/Projections/ModelBound/for_ModelBoundProjectionBuilder/when_building_model/with_set_from_context/with_implicit_properties.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
using Cratis.Chronicle.Events;
66
using Cratis.Chronicle.Keys;
77

8-
namespace Cratis.Chronicle.Projections.ModelBound.for_ModelBoundProjectionBuilder.when_building_model;
8+
namespace Cratis.Chronicle.Projections.ModelBound.for_ModelBoundProjectionBuilder.when_building_model.with_set_from_context;
99

10-
public class with_set_from_context : given.a_model_bound_projection_builder
10+
public class with_implicit_properties : given.a_model_bound_projection_builder
1111
{
1212
ProjectionDefinition _result;
1313

Source/Kernel/Grains.Interfaces/Projections/INotifyProjectionDefinitionsChanged.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Copyright (c) Cratis. All rights reserved.
22
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
33

4+
using Cratis.Chronicle.Concepts.Projections.Definitions;
5+
46
namespace Cratis.Chronicle.Grains.Projections;
57

68
/// <summary>
@@ -11,6 +13,7 @@ public interface INotifyProjectionDefinitionsChanged : IGrainObserver
1113
/// <summary>
1214
/// Called when a projection definition is changed.
1315
/// </summary>
16+
/// <param name="definition">The new <see cref="ProjectionDefinition"/>.</param>
1417
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
15-
Task OnProjectionDefinitionsChanged();
18+
Task OnProjectionDefinitionsChanged(ProjectionDefinition definition);
1619
}

0 commit comments

Comments
 (0)