Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add EventStore Hosting and Client integrations #277

Merged
merged 30 commits into from
Nov 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
f543c2b
Add EventStore Hosting and Client integrations
fredimachado Nov 21, 2024
5da0502
Update CODEOWNERS
fredimachado Nov 21, 2024
259b29b
Address PR feedback
fredimachado Nov 22, 2024
bb12675
Add client integration tests
fredimachado Nov 22, 2024
6843bd9
Update AddEventStoreTests.cs
fredimachado Nov 23, 2024
a8b8066
Add HealthCheckTimeout setting
fredimachado Nov 25, 2024
ebd5908
Remove HealthCheckTimeout from Conformance tests
fredimachado Nov 25, 2024
8998861
Remove Atom Pub over HTTP as support is deprecated
fredimachado Nov 25, 2024
2daf3c8
Add Functional tests
fredimachado Nov 25, 2024
1d93d6c
Log volume and mount can be added manually
fredimachado Nov 25, 2024
65a034b
Merge branch 'main' into eventstore-integration
aaronpowell Nov 26, 2024
a3c762f
Merge branch 'main' into eventstore-integration
aaronpowell Nov 26, 2024
bae8ad2
Merge branch 'main' into eventstore-integration
aaronpowell Nov 27, 2024
7cad08f
Merge branch 'main' into eventstore-integration
aaronpowell Nov 27, 2024
d0c35a0
Remove unused const
fredimachado Nov 27, 2024
8553d6f
Update EventStoreFunctionalTests.cs
fredimachado Nov 28, 2024
6a1b859
Update EventStoreFunctionalTests.cs
fredimachado Nov 28, 2024
9fc57ec
Update EventStoreFunctionalTests.cs
fredimachado Nov 28, 2024
90fceff
Wait for resource to be healthy
fredimachado Nov 28, 2024
58f537c
Update EventStoreFunctionalTests.cs
fredimachado Nov 28, 2024
61d2676
Update EventStoreFunctionalTests.cs
fredimachado Nov 28, 2024
396fe02
Fix typo
fredimachado Nov 28, 2024
20e91bf
Use Cts
fredimachado Nov 28, 2024
cdae698
Update EventStoreFunctionalTests.cs
fredimachado Nov 28, 2024
282d122
Check last test
fredimachado Nov 28, 2024
8011a92
Update EventStoreFunctionalTests.cs
fredimachado Nov 28, 2024
30f10e9
Trying all tests
fredimachado Nov 28, 2024
0ff0242
Update EventStoreFunctionalTests.cs
fredimachado Nov 28, 2024
d9c770b
Update EventStoreFunctionalTests.cs
fredimachado Nov 28, 2024
f0d33f8
Update EventStoreFunctionalTests.cs
fredimachado Nov 28, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,12 @@
/examples/rust/_ @Alirexaa
/src/CommunityToolkit.Aspire.Hosting.Rust/_ @Alirexaa
/tests/CommunityToolkit.Aspire.Hosting.Rust/_ @Alirexaa

# CommunityToolkit.Aspire.EventStore
# CommunityToolkit.Aspire.Hosting.EventStore

/examples/eventstore/_ @fredimachado
/src/CommunityToolkit.Aspire.Hosting.EventStore/_ @fredimachado
/tests/CommunityToolkit.Aspire.Hosting.EventStore.Tests/_ @fredimachado
/src/CommunityToolkit.Aspire.EventStore/_ @fredimachado
/tests/CommunityToolkit.Aspire.EventStore.Tests/_ @fredimachado
84 changes: 68 additions & 16 deletions CommunityToolkit.Aspire.sln
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,22 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommunityToolkit.Aspire.Hos
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommunityToolkit.Aspire.Hosting.Bun.Tests", "tests\CommunityToolkit.Aspire.Hosting.Bun.Tests\CommunityToolkit.Aspire.Hosting.Bun.Tests.csproj", "{DA5DD2CB-51D9-429F-91F5-BF3D1A13A21A}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "eventstore", "eventstore", "{114DDF07-489A-419B-BE76-E5A289F12791}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommunityToolkit.Aspire.Hosting.EventStore", "src\CommunityToolkit.Aspire.Hosting.EventStore\CommunityToolkit.Aspire.Hosting.EventStore.csproj", "{B209275E-1CFF-4AF0-A65A-2895DD679775}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommunityToolkit.Aspire.EventStore", "src\CommunityToolkit.Aspire.EventStore\CommunityToolkit.Aspire.EventStore.csproj", "{AD230A69-F6AE-4A9B-B500-90516BA2E1C6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommunityToolkit.Aspire.Hosting.EventStore.Tests", "tests\CommunityToolkit.Aspire.Hosting.EventStore.Tests\CommunityToolkit.Aspire.Hosting.EventStore.Tests.csproj", "{FA34A40C-62C9-4A73-A39D-53A01243657C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommunityToolkit.Aspire.Hosting.EventStore.AppHost", "examples\eventstore\CommunityToolkit.Aspire.Hosting.EventStore.AppHost\CommunityToolkit.Aspire.Hosting.EventStore.AppHost.csproj", "{ED3E5B89-091C-4A0E-9A2B-946CA1A11557}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommunityToolkit.Aspire.Hosting.EventStore.ServiceDefaults", "examples\eventstore\CommunityToolkit.Aspire.Hosting.EventStore.ServiceDefaults\CommunityToolkit.Aspire.Hosting.EventStore.ServiceDefaults.csproj", "{0A4E5B43-155A-4FDA-A50F-0B86CF1705E7}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommunityToolkit.Aspire.Hosting.EventStore.ApiService", "examples\eventstore\CommunityToolkit.Aspire.Hosting.EventStore.ApiService\CommunityToolkit.Aspire.Hosting.EventStore.ApiService.csproj", "{019D6506-9D68-41AD-A7A1-A27B2FFE1253}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommunityToolkit.Aspire.EventStore.Tests", "tests\CommunityToolkit.Aspire.EventStore.Tests\CommunityToolkit.Aspire.EventStore.Tests.csproj", "{C696480B-C2E0-4ACA-BD5E-A62BF8558024}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CommunityToolkit.Aspire.Hosting.ActiveMQ", "src\CommunityToolkit.Aspire.Hosting.ActiveMQ\CommunityToolkit.Aspire.Hosting.ActiveMQ.csproj", "{56C3C409-10FF-4CA5-99AD-0D35C5418B2A}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "activemq", "activemq", "{BF4C4E57-DAAF-4EE5-B330-1923106BAE69}"
Expand Down Expand Up @@ -339,18 +355,6 @@ Global
{C7D057AF-E2A5-4E26-846E-A328A0F14A3C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C7D057AF-E2A5-4E26-846E-A328A0F14A3C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C7D057AF-E2A5-4E26-846E-A328A0F14A3C}.Release|Any CPU.Build.0 = Release|Any CPU
{4DCF987E-9071-4899-8B5F-5FDAF2BC77D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4DCF987E-9071-4899-8B5F-5FDAF2BC77D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4DCF987E-9071-4899-8B5F-5FDAF2BC77D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4DCF987E-9071-4899-8B5F-5FDAF2BC77D3}.Release|Any CPU.Build.0 = Release|Any CPU
{C686CEA0-8B89-470B-84A2-0264040DCDC8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C686CEA0-8B89-470B-84A2-0264040DCDC8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C686CEA0-8B89-470B-84A2-0264040DCDC8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C686CEA0-8B89-470B-84A2-0264040DCDC8}.Release|Any CPU.Build.0 = Release|Any CPU
{5B825CF9-E8B8-4960-9330-648ED0323FE0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5B825CF9-E8B8-4960-9330-648ED0323FE0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5B825CF9-E8B8-4960-9330-648ED0323FE0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5B825CF9-E8B8-4960-9330-648ED0323FE0}.Release|Any CPU.Build.0 = Release|Any CPU
{6BC98146-279F-4DE5-9B6E-0F0C07507421}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6BC98146-279F-4DE5-9B6E-0F0C07507421}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6BC98146-279F-4DE5-9B6E-0F0C07507421}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand All @@ -371,6 +375,18 @@ Global
{2CC61B84-CF97-4CE7-A08F-2EECF4AEAD92}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2CC61B84-CF97-4CE7-A08F-2EECF4AEAD92}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2CC61B84-CF97-4CE7-A08F-2EECF4AEAD92}.Release|Any CPU.Build.0 = Release|Any CPU
{4DCF987E-9071-4899-8B5F-5FDAF2BC77D3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4DCF987E-9071-4899-8B5F-5FDAF2BC77D3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4DCF987E-9071-4899-8B5F-5FDAF2BC77D3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4DCF987E-9071-4899-8B5F-5FDAF2BC77D3}.Release|Any CPU.Build.0 = Release|Any CPU
{C686CEA0-8B89-470B-84A2-0264040DCDC8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C686CEA0-8B89-470B-84A2-0264040DCDC8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C686CEA0-8B89-470B-84A2-0264040DCDC8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C686CEA0-8B89-470B-84A2-0264040DCDC8}.Release|Any CPU.Build.0 = Release|Any CPU
{5B825CF9-E8B8-4960-9330-648ED0323FE0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5B825CF9-E8B8-4960-9330-648ED0323FE0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5B825CF9-E8B8-4960-9330-648ED0323FE0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5B825CF9-E8B8-4960-9330-648ED0323FE0}.Release|Any CPU.Build.0 = Release|Any CPU
{6095E8B8-7F99-4A12-B7E2-376F7EDD7435}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6095E8B8-7F99-4A12-B7E2-376F7EDD7435}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6095E8B8-7F99-4A12-B7E2-376F7EDD7435}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand All @@ -383,6 +399,34 @@ Global
{DA5DD2CB-51D9-429F-91F5-BF3D1A13A21A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DA5DD2CB-51D9-429F-91F5-BF3D1A13A21A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DA5DD2CB-51D9-429F-91F5-BF3D1A13A21A}.Release|Any CPU.Build.0 = Release|Any CPU
{B209275E-1CFF-4AF0-A65A-2895DD679775}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B209275E-1CFF-4AF0-A65A-2895DD679775}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B209275E-1CFF-4AF0-A65A-2895DD679775}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B209275E-1CFF-4AF0-A65A-2895DD679775}.Release|Any CPU.Build.0 = Release|Any CPU
{AD230A69-F6AE-4A9B-B500-90516BA2E1C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{AD230A69-F6AE-4A9B-B500-90516BA2E1C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AD230A69-F6AE-4A9B-B500-90516BA2E1C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AD230A69-F6AE-4A9B-B500-90516BA2E1C6}.Release|Any CPU.Build.0 = Release|Any CPU
{FA34A40C-62C9-4A73-A39D-53A01243657C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FA34A40C-62C9-4A73-A39D-53A01243657C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FA34A40C-62C9-4A73-A39D-53A01243657C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FA34A40C-62C9-4A73-A39D-53A01243657C}.Release|Any CPU.Build.0 = Release|Any CPU
{ED3E5B89-091C-4A0E-9A2B-946CA1A11557}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ED3E5B89-091C-4A0E-9A2B-946CA1A11557}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ED3E5B89-091C-4A0E-9A2B-946CA1A11557}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ED3E5B89-091C-4A0E-9A2B-946CA1A11557}.Release|Any CPU.Build.0 = Release|Any CPU
{0A4E5B43-155A-4FDA-A50F-0B86CF1705E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0A4E5B43-155A-4FDA-A50F-0B86CF1705E7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0A4E5B43-155A-4FDA-A50F-0B86CF1705E7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0A4E5B43-155A-4FDA-A50F-0B86CF1705E7}.Release|Any CPU.Build.0 = Release|Any CPU
{019D6506-9D68-41AD-A7A1-A27B2FFE1253}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{019D6506-9D68-41AD-A7A1-A27B2FFE1253}.Debug|Any CPU.Build.0 = Debug|Any CPU
{019D6506-9D68-41AD-A7A1-A27B2FFE1253}.Release|Any CPU.ActiveCfg = Release|Any CPU
{019D6506-9D68-41AD-A7A1-A27B2FFE1253}.Release|Any CPU.Build.0 = Release|Any CPU
{C696480B-C2E0-4ACA-BD5E-A62BF8558024}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C696480B-C2E0-4ACA-BD5E-A62BF8558024}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C696480B-C2E0-4ACA-BD5E-A62BF8558024}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C696480B-C2E0-4ACA-BD5E-A62BF8558024}.Release|Any CPU.Build.0 = Release|Any CPU
{56C3C409-10FF-4CA5-99AD-0D35C5418B2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{56C3C409-10FF-4CA5-99AD-0D35C5418B2A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{56C3C409-10FF-4CA5-99AD-0D35C5418B2A}.Release|Any CPU.ActiveCfg = Release|Any CPU
Expand Down Expand Up @@ -461,21 +505,29 @@ Global
{4AE83D68-EA10-473D-BD26-19C5928A8620} = {8519CC01-1370-47C8-AD94-B0F326B1563F}
{79EF8E85-1DFC-42B5-BDE3-72639F25848C} = {4AE83D68-EA10-473D-BD26-19C5928A8620}
{C7D057AF-E2A5-4E26-846E-A328A0F14A3C} = {899F0713-7FC6-4750-BAFC-AC650B35B453}
{4DCF987E-9071-4899-8B5F-5FDAF2BC77D3} = {414151D4-7009-4E78-A5C6-D99EBD1E67D1}
{DDDAABA3-D8F0-47C6-98E0-AB57F28404CF} = {8519CC01-1370-47C8-AD94-B0F326B1563F}
{C686CEA0-8B89-470B-84A2-0264040DCDC8} = {DDDAABA3-D8F0-47C6-98E0-AB57F28404CF}
{5B825CF9-E8B8-4960-9330-648ED0323FE0} = {899F0713-7FC6-4750-BAFC-AC650B35B453}
{6BC98146-279F-4DE5-9B6E-0F0C07507421} = {414151D4-7009-4E78-A5C6-D99EBD1E67D1}
{662514C8-EAED-4EAB-91CE-893D4DE2469A} = {8519CC01-1370-47C8-AD94-B0F326B1563F}
{1E753568-E34B-4E93-93F8-43764171725D} = {662514C8-EAED-4EAB-91CE-893D4DE2469A}
{FB9B8F61-5125-452B-8332-938DCFA27366} = {662514C8-EAED-4EAB-91CE-893D4DE2469A}
{373472DA-BAEB-44B6-915D-1EF3DA845797} = {899F0713-7FC6-4750-BAFC-AC650B35B453}
{79CBF217-CED1-4BB2-9A72-37D2429F83B8} = {899F0713-7FC6-4750-BAFC-AC650B35B453}
{2CC61B84-CF97-4CE7-A08F-2EECF4AEAD92} = {79CBF217-CED1-4BB2-9A72-37D2429F83B8}
{4DCF987E-9071-4899-8B5F-5FDAF2BC77D3} = {414151D4-7009-4E78-A5C6-D99EBD1E67D1}
{DDDAABA3-D8F0-47C6-98E0-AB57F28404CF} = {8519CC01-1370-47C8-AD94-B0F326B1563F}
{C686CEA0-8B89-470B-84A2-0264040DCDC8} = {DDDAABA3-D8F0-47C6-98E0-AB57F28404CF}
{5B825CF9-E8B8-4960-9330-648ED0323FE0} = {899F0713-7FC6-4750-BAFC-AC650B35B453}
{6095E8B8-7F99-4A12-B7E2-376F7EDD7435} = {414151D4-7009-4E78-A5C6-D99EBD1E67D1}
{A7614F2B-E810-412E-91E7-8B6272DD5DBB} = {8519CC01-1370-47C8-AD94-B0F326B1563F}
{36FC2579-582A-4DAF-9B20-AB33331624C6} = {A7614F2B-E810-412E-91E7-8B6272DD5DBB}
{DA5DD2CB-51D9-429F-91F5-BF3D1A13A21A} = {899F0713-7FC6-4750-BAFC-AC650B35B453}
{114DDF07-489A-419B-BE76-E5A289F12791} = {8519CC01-1370-47C8-AD94-B0F326B1563F}
{B209275E-1CFF-4AF0-A65A-2895DD679775} = {414151D4-7009-4E78-A5C6-D99EBD1E67D1}
{AD230A69-F6AE-4A9B-B500-90516BA2E1C6} = {414151D4-7009-4E78-A5C6-D99EBD1E67D1}
{FA34A40C-62C9-4A73-A39D-53A01243657C} = {899F0713-7FC6-4750-BAFC-AC650B35B453}
{ED3E5B89-091C-4A0E-9A2B-946CA1A11557} = {114DDF07-489A-419B-BE76-E5A289F12791}
{0A4E5B43-155A-4FDA-A50F-0B86CF1705E7} = {114DDF07-489A-419B-BE76-E5A289F12791}
{019D6506-9D68-41AD-A7A1-A27B2FFE1253} = {114DDF07-489A-419B-BE76-E5A289F12791}
{C696480B-C2E0-4ACA-BD5E-A62BF8558024} = {899F0713-7FC6-4750-BAFC-AC650B35B453}
{56C3C409-10FF-4CA5-99AD-0D35C5418B2A} = {414151D4-7009-4E78-A5C6-D99EBD1E67D1}
{BF4C4E57-DAAF-4EE5-B330-1923106BAE69} = {8519CC01-1370-47C8-AD94-B0F326B1563F}
{CF6CF1C3-EBE1-41CE-9B34-0C2F931AEA12} = {BF4C4E57-DAAF-4EE5-B330-1923106BAE69}
Expand Down
3 changes: 3 additions & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<PackageVersion Include="Aspire.Hosting.Python" Version="$(AspireVersion)" />
<PackageVersion Include="Aspire.Hosting.SqlServer" Version="$(AspireVersion)" />
<!-- AspNetCore packages -->
<PackageVersion Include="AspNetCore.HealthChecks.EventStore.gRPC" Version="8.0.1" />
<PackageVersion Include="AspNetCore.HealthChecks.SqlServer" Version="8.0.2" />
<PackageVersion Include="Microsoft.AspNetCore.Components.QuickGrid" Version="$(AspNetCoreVersion)" />
<PackageVersion Include="Microsoft.AspNetCore.OpenApi" Version="8.0.11" />
Expand Down Expand Up @@ -48,6 +49,8 @@
<PackageVersion Include="Microsoft.SqlServer.DacFx" Version="162.5.57" />
<PackageVersion Include="Microsoft.Build" Version="17.11.4" />
<PackageVersion Include="Microsoft.Build.Locator" Version="1.7.8" />
<PackageVersion Include="EventStore.Client.Extensions.OpenTelemetry" Version="23.3.7" />
<PackageVersion Include="EventStore.Client.Grpc.Streams" Version="23.3.7" />
<!-- Build dependencies -->
<PackageVersion Include="Microsoft.CodeAnalysis.PublicApiAnalyzers" Version="3.3.4" />
<!-- Testcontainers packages -->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
using System.Text.Json.Serialization;

namespace CommunityToolkit.Aspire.Hosting.EventStore.ApiService;

public class Account
{
public Guid Id { get; private set; }
public string? Name { get; private set; }
public decimal Balance { get; private set; }

[JsonIgnore]
public int Version { get; private set; } = -1;

[NonSerialized]
private readonly Queue<object> uncommittedEvents = new();

public static Account Create(Guid id, string name)
=> new(id, name);

public void Deposit(decimal amount)
{
ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(amount, 0, nameof(amount));

var @event = new AccountFundsDeposited(Id, amount);

uncommittedEvents.Enqueue(@event);
Apply(@event);
}

public void Withdraw(decimal amount)
{
ArgumentOutOfRangeException.ThrowIfLessThanOrEqual(amount, 0, nameof(amount));
ArgumentOutOfRangeException.ThrowIfGreaterThan(amount, Balance, nameof(amount));

var @event = new AccountFundsWithdrew(Id, amount);

uncommittedEvents.Enqueue(@event);
Apply(@event);
}

public void When(object @event)
{
switch (@event)
{
case AccountCreated accountCreated:
Apply(accountCreated);
break;
case AccountFundsDeposited accountFundsDeposited:
Apply(accountFundsDeposited);
break;
case AccountFundsWithdrew accountFundsWithdrew:
Apply(accountFundsWithdrew);
break;
}
}

public object[] DequeueUncommittedEvents()
{
var dequeuedEvents = uncommittedEvents.ToArray();

uncommittedEvents.Clear();

return dequeuedEvents;
}

private Account()
{
}

private Account(Guid id, string name)
{
if (id == Guid.Empty)
{
throw new ArgumentException("Id cannot be empty.", nameof(id));
}
ArgumentException.ThrowIfNullOrWhiteSpace(name, nameof(name));

var @event = new AccountCreated(id, name);

uncommittedEvents.Enqueue(@event);
Apply(@event);
}

private void Apply(AccountCreated @event)
{
Version++;

Id = @event.Id;
Name = @event.Name;
}

private void Apply(AccountFundsDeposited @event)
{
Version++;

Balance += @event.Amount;
}

private void Apply(AccountFundsWithdrew @event)
{
Version++;

Balance -= @event.Amount;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace CommunityToolkit.Aspire.Hosting.EventStore.ApiService;

public record AccountCreated(Guid Id, string Name);

public record AccountFundsDeposited(Guid Id, decimal Amount);

public record AccountFundsWithdrew(Guid Id, decimal Amount);
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.OpenApi" />
<PackageReference Include="Swashbuckle.AspNetCore" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\..\src\CommunityToolkit.Aspire.EventStore\CommunityToolkit.Aspire.EventStore.csproj" />
<ProjectReference Include="..\CommunityToolkit.Aspire.Hosting.EventStore.ServiceDefaults\CommunityToolkit.Aspire.Hosting.EventStore.ServiceDefaults.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
using EventStore.Client;
using System.Text.Json;
using System.Text;

namespace CommunityToolkit.Aspire.Hosting.EventStore.ApiService;

public static class EventStoreExtensions
{
public static async Task<Account?> GetAccount(this EventStoreClient eventStore, Guid id, CancellationToken cancellationToken)
{
var readResult = eventStore.ReadStreamAsync(
Direction.Forwards,
$"account-{id:N}",
StreamPosition.Start,
cancellationToken: cancellationToken
);

var readState = await readResult.ReadState;
if (readState == ReadState.StreamNotFound)
{
return null;
}

var account = (Account)Activator.CreateInstance(typeof(Account), true)!;

await foreach (var resolvedEvent in readResult)
{
var @event = resolvedEvent.Deserialize();

account.When(@event!);
}

return account;
}

public static async Task AppendAcountEvents(this EventStoreClient eventStore, Account account, CancellationToken cancellationToken)
{
var events = account.DequeueUncommittedEvents();

var eventsToAppend = events
.Select(@event => @event.Serialize()).ToArray();

var expectedVersion = account.Version - events.Length;
await eventStore.AppendToStreamAsync(
$"account-{account.Id:N}",
expectedVersion == 0 ? StreamRevision.None : StreamRevision.FromInt64(expectedVersion),
eventsToAppend,
cancellationToken: cancellationToken
);
}

private static object? Deserialize(this ResolvedEvent resolvedEvent)
{
var eventClrTypeName = JsonDocument.Parse(resolvedEvent.Event.Metadata)
.RootElement
.GetProperty("EventClrTypeName")
.GetString();

return JsonSerializer.Deserialize(
Encoding.UTF8.GetString(resolvedEvent.Event.Data.Span),
Type.GetType(eventClrTypeName!)!);
}

private static EventData Serialize(this object @event)
{
return new EventData(
Uuid.NewUuid(),
@event.GetType().Name,
data: Encoding.UTF8.GetBytes(JsonSerializer.Serialize(@event)),
metadata: Encoding.UTF8.GetBytes(JsonSerializer.Serialize(new Dictionary<string, string>
{
{ "EventClrTypeName", @event.GetType().AssemblyQualifiedName! }
}))
);
}
}
Loading
Loading