From 2d174480be2364b242a32a40019ce17f453c1bba Mon Sep 17 00:00:00 2001 From: Tomohisa Takaoka Date: Fri, 27 Dec 2024 02:13:08 -0800 Subject: [PATCH 1/2] working on the resource --- internalUsages/Pure.Domain/Class1.cs | 246 ++++++--------------------- src/Sekiban.Pure/Class1.cs | 241 ++++++++++++++------------ 2 files changed, 186 insertions(+), 301 deletions(-) diff --git a/internalUsages/Pure.Domain/Class1.cs b/internalUsages/Pure.Domain/Class1.cs index 964c1137..3ed5fe83 100644 --- a/internalUsages/Pure.Domain/Class1.cs +++ b/internalUsages/Pure.Domain/Class1.cs @@ -1,6 +1,5 @@ using ResultBoxes; using Sekiban.Pure; -using Sekiban.Pure.Exception; namespace Pure.Domain; public record UnconfirmedUser(string Name, string Email) : IAggregatePayload; @@ -211,196 +210,55 @@ public Task> HandleAsync( // new SekibanEventTypeNotFoundException($"Event Type {payload.GetType().Name} Not Found")) // }; // } -public class CpPureDomainEventTypes : IEventTypes -{ - public ResultBox GenerateTypedEvent( - IEventPayload payload, - PartitionKeys partitionKeys, - string sortableUniqueId, - int version) => payload switch - { - UserRegistered userregistered => new Event( - userregistered, - partitionKeys, - sortableUniqueId, - version), - UserConfirmed userconfirmed => new Event( - userconfirmed, - partitionKeys, - sortableUniqueId, - version), - UserUnconfirmed userunconfirmed => new Event( - userunconfirmed, - partitionKeys, - sortableUniqueId, - version), - BranchCreated branchcreated => new Event( - branchcreated, - partitionKeys, - sortableUniqueId, - version), - BranchNameChanged branchnamechanged => new Event( - branchnamechanged, - partitionKeys, - sortableUniqueId, - version), - ShoppingCartCreated shoppingcartcreated => new Event( - shoppingcartcreated, - partitionKeys, - sortableUniqueId, - version), - ShoppingCartItemAdded shoppingcartitemadded => new Event( - shoppingcartitemadded, - partitionKeys, - sortableUniqueId, - version), - PaymentProcessedShoppingCart paymentprocessedshoppingcart => new Event( - paymentprocessedshoppingcart, - partitionKeys, - sortableUniqueId, - version), - _ => ResultBox.FromException( - new SekibanEventTypeNotFoundException($"Event Type {payload.GetType().Name} Not Found")) - }; -} -public static class CpDomainExecutorExtensions -{ - public static Task> Execute(this CommandExecutor executor, RegisterBranch command) => - executor.ExecuteFunctionWithoutAggregateRestriction( - command, - (command as ICommandGetProjector).GetProjector(), - command.SpecifyPartitionKeys, - command.Handle); - - public static Task> ExecuteFunction( - this CommandExecutor executor, - RegisterBranch command, - IAggregateProjector projector, - Func specifyPartitionKeys, - Func, ResultBox> handler) => - executor.ExecuteFunctionWithoutAggregateRestriction(command, projector, specifyPartitionKeys, handler); - - public static Task> Execute(this CommandExecutor executor, ChangeBranchName command) => - executor.ExecuteFunctionWithoutAggregateRestriction( - command, - (command as ICommandGetProjector).GetProjector(), - command.SpecifyPartitionKeys, - command.Handle); - - public static Task> ExecuteFunction( - this CommandExecutor executor, - ChangeBranchName command, - IAggregateProjector projector, - Func specifyPartitionKeys, - Func, ResultBox> handler) => - executor.ExecuteFunctionWithoutAggregateRestriction(command, projector, specifyPartitionKeys, handler); - - public static Task> Execute(this CommandExecutor executor, ConfirmUser command) => - executor.ExecuteFunctionWithAggregateRestriction( - command, - (command as ICommandGetProjector).GetProjector(), - command.SpecifyPartitionKeys, - command.Handle); - - public static Task> ExecuteFunction( - this CommandExecutor executor, - ConfirmUser command, - IAggregateProjector projector, - Func specifyPartitionKeys, - Func, ResultBox> handler) => - executor.ExecuteFunctionWithAggregateRestriction( - command, - projector, - specifyPartitionKeys, - handler); - - public static Task> Execute(this CommandExecutor executor, CreateShoppingCart command) => - executor.ExecuteFunctionWithoutAggregateRestrictionAsync( - command, - (command as ICommandGetProjector).GetProjector(), - command.SpecifyPartitionKeys, - command.HandleAsync); - - public static Task> ExecuteFunctionAsync( - this CommandExecutor executor, - CreateShoppingCart command, - IAggregateProjector projector, - Func specifyPartitionKeys, - Func, Task>> handler) => - executor.ExecuteFunctionWithoutAggregateRestrictionAsync(command, projector, specifyPartitionKeys, handler); - - public static Task> Execute( - this CommandExecutor executor, - RegisterUser command, - RegisterUser.Injection injection) => - executor.ExecuteFunctionWithInjectionWithoutAggregateRestriction( - command, - (command as ICommandGetProjector).GetProjector(), - command.SpecifyPartitionKeys, - injection, - command.Handle); - - public static Task> ExecuteFunction( - this CommandExecutor executor, - RegisterUser command, - IAggregateProjector projector, - Func specifyPartitionKeys, - RegisterUser.Injection injection, - Func, ResultBox> - handler) => - executor.ExecuteFunctionWithInjectionWithoutAggregateRestriction( - command, - projector, - specifyPartitionKeys, - injection, - handler); - - public static Task> Execute( - this CommandExecutor executor, - RevokeUser command, - RevokeUser.Injection injection) => - executor.ExecuteFunctionWithInjectionWithAggregateRestriction( - command, - (command as ICommandGetProjector).GetProjector(), - command.SpecifyPartitionKeys, - injection, - command.Handle); - - public static Task> ExecuteFunction( - this CommandExecutor executor, - RevokeUser command, - IAggregateProjector projector, - Func specifyPartitionKeys, - RevokeUser.Injection injection, - Func, ResultBox> handler) => - executor.ExecuteFunctionWithInjectionWithAggregateRestriction( - command, - projector, - specifyPartitionKeys, - injection, - handler); - - public static Task> ExecuteFunction( - this CommandExecutor executor, - RegisterBranch2 command, - IAggregateProjector projector, - Func specifyPartitionKeys, - Func, ResultBox> handler) => - executor.ExecuteFunctionWithoutAggregateRestriction( - command, - projector, - specifyPartitionKeys, - handler); - - public static Task> ExecuteFunction( - this CommandExecutor executor, - RegisterBranch3 command, - IAggregateProjector projector, - Func specifyPartitionKeys, - Func, ResultBox> handler) => - executor.ExecuteFunctionWithAggregateRestriction( - command, - projector, - specifyPartitionKeys, - handler); -} +// public class CpPureDomainEventTypes : IEventTypes +// { +// public ResultBox GenerateTypedEvent( +// IEventPayload payload, +// PartitionKeys partitionKeys, +// string sortableUniqueId, +// int version) => payload switch +// { +// UserRegistered userregistered => new Event( +// userregistered, +// partitionKeys, +// sortableUniqueId, +// version), +// UserConfirmed userconfirmed => new Event( +// userconfirmed, +// partitionKeys, +// sortableUniqueId, +// version), +// UserUnconfirmed userunconfirmed => new Event( +// userunconfirmed, +// partitionKeys, +// sortableUniqueId, +// version), +// BranchCreated branchcreated => new Event( +// branchcreated, +// partitionKeys, +// sortableUniqueId, +// version), +// BranchNameChanged branchnamechanged => new Event( +// branchnamechanged, +// partitionKeys, +// sortableUniqueId, +// version), +// ShoppingCartCreated shoppingcartcreated => new Event( +// shoppingcartcreated, +// partitionKeys, +// sortableUniqueId, +// version), +// ShoppingCartItemAdded shoppingcartitemadded => new Event( +// shoppingcartitemadded, +// partitionKeys, +// sortableUniqueId, +// version), +// PaymentProcessedShoppingCart paymentprocessedshoppingcart => new Event( +// paymentprocessedshoppingcart, +// partitionKeys, +// sortableUniqueId, +// version), +// _ => ResultBox.FromException( +// new SekibanEventTypeNotFoundException($"Event Type {payload.GetType().Name} Not Found")) +// }; +// } diff --git a/src/Sekiban.Pure/Class1.cs b/src/Sekiban.Pure/Class1.cs index 1c9bd6d7..d596aca6 100644 --- a/src/Sekiban.Pure/Class1.cs +++ b/src/Sekiban.Pure/Class1.cs @@ -89,7 +89,10 @@ public interface ICommandContext where TAggregatePayload : IA public interface ICommand; public interface ICommandWithAggregateRestriction : ICommand where TAggregatePayload : IAggregatePayload; -public record NoInjection; +public record NoInjection +{ + public static NoInjection Empty => new(); +} public interface ICommandHandler : ICommandHandlerCommon where TCommand : ICommand, IEquatable where TAggregatePayload : IAggregatePayload @@ -266,115 +269,18 @@ public interface ICommandExecutor; public class CommandExecutor : ICommandExecutor { public IEventTypes EventTypes { get; init; } = new EmptyEventTypes(); - public Task> ExecuteFunctionWithoutAggregateRestriction( - TCommand command, - IAggregateProjector projector, - Func specifyPartitionKeys, - Func, ResultBox> handler) where TCommand : ICommand => - ExecuteGeneral( - command, - projector, - specifyPartitionKeys, - OptionalValue.Empty, - handler); - public Task> ExecuteFunctionWithoutAggregateRestrictionAsync( - TCommand command, - IAggregateProjector projector, - Func specifyPartitionKeys, - Func, Task>> handler) - where TCommand : ICommand => - ExecuteGeneral( - command, - projector, - specifyPartitionKeys, - OptionalValue.Empty, - handler); - public Task> ExecuteFunctionWithAggregateRestriction( - TCommand command, - IAggregateProjector projector, - Func specifyPartitionKeys, - Func, ResultBox> handler) - where TCommand : ICommandWithAggregateRestriction - where TAggregatePayload : IAggregatePayload => - ExecuteGeneral( - command, - projector, - specifyPartitionKeys, - OptionalValue.Empty, - handler); - public Task> ExecuteFunctionWithAggregateRestrictionAsync( - TCommand command, - IAggregateProjector projector, - Func specifyPartitionKeys, - Func, Task>> handler) - where TCommand : ICommandWithAggregateRestriction - where TAggregatePayload : IAggregatePayload => - ExecuteGeneral( - command, - projector, - specifyPartitionKeys, - OptionalValue.Empty, - handler); - public Task> - ExecuteFunctionWithInjectionWithoutAggregateRestriction( - TCommand command, - IAggregateProjector projector, - Func specifyPartitionKeys, - TInjection inject, - Func, ResultBox> handler) - where TCommand : ICommand => - ExecuteGeneral( - command, - projector, - specifyPartitionKeys, - OptionalValue.FromValue(inject), - handler); - public Task> - ExecuteFunctionWithInjectionWithoutAggregateRestrictionAsync( - TCommand command, - IAggregateProjector projector, - Func specifyPartitionKeys, - TInjection inject, - Func, Task>> handler) - where TCommand : ICommand => - ExecuteGeneral( + public Task> ExecuteWithResource( + TCommand command, + ICommandResource resource) where TCommand : ICommand, IEquatable => + ExecuteGeneralNonGeneric( command, - projector, - specifyPartitionKeys, - OptionalValue.FromValue(inject), - handler); + resource.GetProjector(), + resource.GetSpecifyPartitionKeysFunc(), + resource.GetInjection(), + resource.GetHandler(), + resource.GetAggregatePayloadType()); - public Task> - ExecuteFunctionWithInjectionWithAggregateRestriction( - TCommand command, - IAggregateProjector projector, - Func specifyPartitionKeys, - TInjection inject, - Func, ResultBox> handler) - where TCommand : ICommandWithAggregateRestriction - where TAggregatePayload : IAggregatePayload => - ExecuteGeneral( - command, - projector, - specifyPartitionKeys, - OptionalValue.FromValue(inject), - handler); - public Task> - ExecuteFunctionWithInjectionWithAggregateRestrictionAsync( - TCommand command, - IAggregateProjector projector, - Func specifyPartitionKeys, - TInjection inject, - Func, Task>> handler) - where TCommand : ICommandWithAggregateRestriction - where TAggregatePayload : IAggregatePayload => - ExecuteGeneral( - command, - projector, - specifyPartitionKeys, - OptionalValue.FromValue(inject), - handler); #region Private Methods [DynamicDependency(DynamicallyAccessedMemberTypes.PublicMethods, typeof(CommandExecutor))] [UnconditionalSuppressMessage( @@ -545,3 +451,124 @@ public ResultBox GenerateTypedEvent( string sortableUniqueId, int version) => ResultBox.FromException(new SekibanEventTypeNotFoundException("")); } +public interface ICommandResource where TCommand : ICommand, IEquatable +{ + public Func GetSpecifyPartitionKeysFunc(); + public OptionalValue GetAggregatePayloadType(); + public Type GetCommandType(); + public IAggregateProjector GetProjector(); + public object? GetInjection(); + public Delegate GetHandler(); +} +public record CommandResource( + Func SpecifyPartitionKeys, + Func, ResultBox> Handler) + : ICommandResource where TCommand : ICommand, IEquatable + where TAggregatePayload : IAggregatePayload + where TProjector : IAggregateProjector, new() +{ + public Func GetSpecifyPartitionKeysFunc() => SpecifyPartitionKeys; + public Type GetCommandType() => typeof(TCommand); + public IAggregateProjector GetProjector() => new TProjector(); + public object? GetInjection() => NoInjection.Empty; + public Delegate GetHandler() => Handler; + public OptionalValue GetAggregatePayloadType() => typeof(TAggregatePayload); +} +public record CommandResourceTask( + Func SpecifyPartitionKeys, + Func, Task>> Handler) + : ICommandResource where TCommand : ICommand, IEquatable + where TAggregatePayload : IAggregatePayload + where TProjector : IAggregateProjector, new() +{ + public Func GetSpecifyPartitionKeysFunc() => SpecifyPartitionKeys; + public Type GetCommandType() => typeof(TCommand); + public IAggregateProjector GetProjector() => new TProjector(); + public object? GetInjection() => NoInjection.Empty; + public Delegate GetHandler() => Handler; + public OptionalValue GetAggregatePayloadType() => typeof(TAggregatePayload); +} +public record CommandResource( + Func SpecifyPartitionKeys, + Func, ResultBox> Handler) + : ICommandResource where TCommand : ICommand, IEquatable + where TProjector : IAggregateProjector, new() +{ + public Func GetSpecifyPartitionKeysFunc() => SpecifyPartitionKeys; + public Type GetCommandType() => typeof(TCommand); + public IAggregateProjector GetProjector() => new TProjector(); + public object GetInjection() => NoInjection.Empty; + public Delegate GetHandler() => Handler; + public OptionalValue GetAggregatePayloadType() => OptionalValue.Empty; +} +public record CommandResourceTask( + Func SpecifyPartitionKeys, + Func, Task>> Handler) + : ICommandResource where TCommand : ICommand, IEquatable + where TProjector : IAggregateProjector, new() +{ + public Func GetSpecifyPartitionKeysFunc() => SpecifyPartitionKeys; + public Type GetCommandType() => typeof(TCommand); + public IAggregateProjector GetProjector() => new TProjector(); + public object GetInjection() => NoInjection.Empty; + public Delegate GetHandler() => Handler; + public OptionalValue GetAggregatePayloadType() => OptionalValue.Empty; +} +public record CommandResourceWithInject( + Func SpecifyPartitionKeys, + TInject? Injection, + Func, ResultBox> Handler) + : ICommandResource where TCommand : ICommand, IEquatable + where TProjector : IAggregateProjector, new() +{ + public Func GetSpecifyPartitionKeysFunc() => SpecifyPartitionKeys; + public Type GetCommandType() => typeof(TCommand); + public IAggregateProjector GetProjector() => new TProjector(); + public object GetInjection() => NoInjection.Empty; + public Delegate GetHandler() => Handler; + public OptionalValue GetAggregatePayloadType() => OptionalValue.Empty; +} +public record CommandResourceWithInjectTask( + Func SpecifyPartitionKeys, + TInject? Injection, + Func, Task>> Handler) + : ICommandResource where TCommand : ICommand, IEquatable + where TProjector : IAggregateProjector, new() +{ + public Func GetSpecifyPartitionKeysFunc() => SpecifyPartitionKeys; + public Type GetCommandType() => typeof(TCommand); + public IAggregateProjector GetProjector() => new TProjector(); + public object GetInjection() => NoInjection.Empty; + public Delegate GetHandler() => Handler; + public OptionalValue GetAggregatePayloadType() => OptionalValue.Empty; +} +public record CommandResourceWithInject( + Func SpecifyPartitionKeys, + TInject? Injection, + Func, Task>> Handler) + : ICommandResource where TCommand : ICommand, IEquatable + where TAggregatePayload : IAggregatePayload + where TProjector : IAggregateProjector, new() +{ + public Func GetSpecifyPartitionKeysFunc() => SpecifyPartitionKeys; + public Type GetCommandType() => typeof(TCommand); + public IAggregateProjector GetProjector() => new TProjector(); + public object? GetInjection() => Injection; + public Delegate GetHandler() => Handler; + public OptionalValue GetAggregatePayloadType() => typeof(TAggregatePayload); +} +public record CommandResourceWithInjectTask( + Func SpecifyPartitionKeys, + TInject? Injection, + Func, Task>> Handler) + : ICommandResource where TCommand : ICommand, IEquatable + where TAggregatePayload : IAggregatePayload + where TProjector : IAggregateProjector, new() +{ + public Func GetSpecifyPartitionKeysFunc() => SpecifyPartitionKeys; + public Type GetCommandType() => typeof(TCommand); + public IAggregateProjector GetProjector() => new TProjector(); + public object? GetInjection() => Injection; + public Delegate GetHandler() => Handler; + public OptionalValue GetAggregatePayloadType() => typeof(TAggregatePayload); +} From 036ebcbedbea8cce1478c7ad607fa28758e5cc8a Mon Sep 17 00:00:00 2001 From: Tomohisa Takaoka Date: Fri, 27 Dec 2024 17:25:45 -0800 Subject: [PATCH 2/2] finished --- .../CommandExecutionExtensionGenerator.cs | 71 +++++------ src/Sekiban.Pure/Class1.cs | 8 +- .../Pure.Domain.Test/Pure.Domain.Test.csproj | 9 +- tests/Pure.Domain.Test/UnitTest1.cs | 110 ++++++++++++++++-- 4 files changed, 138 insertions(+), 60 deletions(-) diff --git a/src/Sekiban.Pure.SourceGenerator/CommandExecutionExtensionGenerator.cs b/src/Sekiban.Pure.SourceGenerator/CommandExecutionExtensionGenerator.cs index 50f53173..8eba1c7f 100644 --- a/src/Sekiban.Pure.SourceGenerator/CommandExecutionExtensionGenerator.cs +++ b/src/Sekiban.Pure.SourceGenerator/CommandExecutionExtensionGenerator.cs @@ -259,10 +259,12 @@ private string GenerateSourceCode(ImmutableArray event case ("ICommandWithHandler", 2): sb.AppendLine( $" public static Task> Execute(this CommandExecutor executor, {type.RecordName} command) =>"); - sb.AppendLine(" executor.ExecuteFunctionWithoutAggregateRestriction("); + sb.AppendLine( + $" executor.ExecuteGeneral<{type.RecordName},NoInjection,IAggregatePayload>("); sb.AppendLine(" command,"); sb.AppendLine(" (command as ICommandGetProjector).GetProjector(),"); sb.AppendLine(" command.SpecifyPartitionKeys,"); + sb.AppendLine(" NoInjection.Empty,"); sb.AppendLine(" command.Handle);"); sb.AppendLine(); // add this too @@ -272,10 +274,12 @@ private string GenerateSourceCode(ImmutableArray event sb.AppendLine($" Func<{type.RecordName}, PartitionKeys> specifyPartitionKeys,"); sb.AppendLine( $" Func<{type.RecordName}, ICommandContext, ResultBox> handler) =>"); - sb.AppendLine(" executor.ExecuteFunctionWithoutAggregateRestriction("); + sb.AppendLine( + $" executor.ExecuteGeneral<{type.RecordName},NoInjection,IAggregatePayload>("); sb.AppendLine(" command,"); sb.AppendLine(" projector,"); sb.AppendLine(" specifyPartitionKeys,"); + sb.AppendLine(" NoInjection.Empty,"); sb.AppendLine(" handler);"); sb.AppendLine(); break; @@ -283,11 +287,11 @@ private string GenerateSourceCode(ImmutableArray event sb.AppendLine( $" public static Task> Execute(this CommandExecutor executor, {type.RecordName} command) =>"); sb.AppendLine( - " executor.ExecuteFunctionWithAggregateRestriction<" + - $"{type.RecordName}, {type.AggregatePayloadTypeName}>("); + $" executor.ExecuteGeneral<{type.RecordName},NoInjection,{type.AggregatePayloadTypeName}>("); sb.AppendLine(" command,"); sb.AppendLine(" (command as ICommandGetProjector).GetProjector(),"); sb.AppendLine(" command.SpecifyPartitionKeys,"); + sb.AppendLine(" NoInjection.Empty,"); sb.AppendLine(" command.Handle);"); sb.AppendLine(); @@ -299,30 +303,24 @@ private string GenerateSourceCode(ImmutableArray event sb.AppendLine( $" Func<{type.RecordName}, ICommandContext<{type.AggregatePayloadTypeName}>, ResultBox> handler) =>"); sb.AppendLine( - " executor.ExecuteFunctionWithAggregateRestriction<" + - $"{type.RecordName}, {type.AggregatePayloadTypeName}>("); + $" executor.ExecuteGeneral<{type.RecordName},NoInjection,{type.AggregatePayloadTypeName}>("); sb.AppendLine(" command,"); sb.AppendLine(" projector,"); sb.AppendLine(" specifyPartitionKeys,"); + sb.AppendLine(" NoInjection.Empty,"); sb.AppendLine(" handler);"); sb.AppendLine(); - - - break; - - - - - case ("ICommandWithHandlerAsync", 2): sb.AppendLine( $" public static Task> Execute(this CommandExecutor executor, {type.RecordName} command) =>"); - sb.AppendLine(" executor.ExecuteFunctionWithoutAggregateRestrictionAsync("); + sb.AppendLine( + $" executor.ExecuteGeneral<{type.RecordName},NoInjection,IAggregatePayload>("); sb.AppendLine(" command,"); sb.AppendLine(" (command as ICommandGetProjector).GetProjector(),"); sb.AppendLine(" command.SpecifyPartitionKeys,"); + sb.AppendLine(" NoInjection.Empty,"); sb.AppendLine(" command.HandleAsync);"); sb.AppendLine(); // add this too @@ -332,10 +330,12 @@ private string GenerateSourceCode(ImmutableArray event sb.AppendLine($" Func<{type.RecordName}, PartitionKeys> specifyPartitionKeys,"); sb.AppendLine( $" Func<{type.RecordName}, ICommandContext, Task>> handler) =>"); - sb.AppendLine(" executor.ExecuteFunctionWithoutAggregateRestrictionAsync("); + sb.AppendLine( + $" executor.ExecuteGeneral<{type.RecordName},NoInjection,IAggregatePayload>("); sb.AppendLine(" command,"); sb.AppendLine(" projector,"); sb.AppendLine(" specifyPartitionKeys,"); + sb.AppendLine(" NoInjection.Empty,"); sb.AppendLine(" handler);"); sb.AppendLine(); break; @@ -343,11 +343,11 @@ private string GenerateSourceCode(ImmutableArray event sb.AppendLine( $" public static Task> Execute(this CommandExecutor executor, {type.RecordName} command) =>"); sb.AppendLine( - " executor.ExecuteFunctionWithAggregateRestrictionAsync<" + - $"{type.RecordName}, {type.AggregatePayloadTypeName}>("); + $" executor.ExecuteGeneral<{type.RecordName},NoInjection,{type.AggregatePayloadTypeName}>("); sb.AppendLine(" command,"); sb.AppendLine(" (command as ICommandGetProjector).GetProjector(),"); sb.AppendLine(" command.SpecifyPartitionKeys,"); + sb.AppendLine(" NoInjection.Empty,"); sb.AppendLine(" command.HandleAsync);"); sb.AppendLine(); @@ -359,35 +359,20 @@ private string GenerateSourceCode(ImmutableArray event sb.AppendLine( $" Func<{type.RecordName}, ICommandContext<{type.AggregatePayloadTypeName}>, Task>> handler) =>"); sb.AppendLine( - " executor.ExecuteFunctionWithAggregateRestrictionAsync<" + - $"{type.RecordName}, {type.AggregatePayloadTypeName}>("); + $" executor.ExecuteGeneral<{type.RecordName},NoInjection,{type.AggregatePayloadTypeName}>("); sb.AppendLine(" command,"); sb.AppendLine(" projector,"); sb.AppendLine(" specifyPartitionKeys,"); + sb.AppendLine(" NoInjection.Empty,"); sb.AppendLine(" handler);"); sb.AppendLine(); - - - break; - - - - - - - - - - - case ("ICommandWithHandlerInjection", 3): sb.AppendLine( $" public static Task> Execute(this CommandExecutor executor, {type.RecordName} command, {type.InjectTypeName} injection) =>"); sb.AppendLine( - " executor.ExecuteFunctionWithInjectionWithoutAggregateRestriction<" + - $"{type.RecordName}, {type.InjectTypeName}>("); + $" executor.ExecuteGeneral<{type.RecordName},{type.InjectTypeName},IAggregatePayload>("); sb.AppendLine(" command,"); sb.AppendLine(" (command as ICommandGetProjector).GetProjector(),"); sb.AppendLine(" command.SpecifyPartitionKeys,"); @@ -404,8 +389,7 @@ private string GenerateSourceCode(ImmutableArray event sb.AppendLine( $" Func<{type.RecordName}, {type.InjectTypeName}, ICommandContext, ResultBox> handler) =>"); sb.AppendLine( - " executor.ExecuteFunctionWithInjectionWithoutAggregateRestriction<" + - $"{type.RecordName}, {type.InjectTypeName}>("); + $" executor.ExecuteGeneral<{type.RecordName},{type.InjectTypeName},IAggregatePayload>("); sb.AppendLine(" command,"); sb.AppendLine(" projector,"); sb.AppendLine(" specifyPartitionKeys,"); @@ -417,8 +401,7 @@ private string GenerateSourceCode(ImmutableArray event sb.AppendLine( $" public static Task> Execute(this CommandExecutor executor, {type.RecordName} command, {type.InjectTypeName} injection) =>"); sb.AppendLine( - " executor.ExecuteFunctionWithInjectionWithAggregateRestriction<" + - $"{type.RecordName}, {type.InjectTypeName}, {type.AggregatePayloadTypeName}>("); + $" executor.ExecuteGeneral<{type.RecordName},{type.InjectTypeName},{type.AggregatePayloadTypeName}>("); sb.AppendLine(" command,"); sb.AppendLine(" (command as ICommandGetProjector).GetProjector(),"); sb.AppendLine(" command.SpecifyPartitionKeys,"); @@ -435,7 +418,7 @@ private string GenerateSourceCode(ImmutableArray event sb.AppendLine( $" Func<{type.RecordName}, {type.InjectTypeName}, ICommandContext<{type.AggregatePayloadTypeName}>, ResultBox> handler) =>"); sb.AppendLine( - $" executor.ExecuteFunctionWithInjectionWithAggregateRestriction<{type.RecordName}, {type.InjectTypeName}, {type.AggregatePayloadTypeName}>("); + $" executor.ExecuteGeneral<{type.RecordName},{type.InjectTypeName},{type.AggregatePayloadTypeName}>("); sb.AppendLine(" command,"); sb.AppendLine(" projector,"); sb.AppendLine(" specifyPartitionKeys,"); @@ -451,10 +434,11 @@ private string GenerateSourceCode(ImmutableArray event sb.AppendLine( $" Func<{type.RecordName}, ICommandContext, ResultBox> handler) =>"); sb.AppendLine( - " executor.ExecuteFunctionWithoutAggregateRestriction<" + $"{type.RecordName}>("); + $" executor.ExecuteGeneral<{type.RecordName},NoInjection,IAggregatePayload>("); sb.AppendLine(" command,"); sb.AppendLine(" projector,"); sb.AppendLine(" specifyPartitionKeys,"); + sb.AppendLine(" NoInjection.Empty,"); sb.AppendLine(" handler);"); sb.AppendLine(); @@ -467,10 +451,11 @@ private string GenerateSourceCode(ImmutableArray event sb.AppendLine( $" Func<{type.RecordName}, ICommandContext<{type.AggregatePayloadTypeName}>, ResultBox> handler) =>"); sb.AppendLine( - $" executor.ExecuteFunctionWithAggregateRestriction<{type.RecordName}, {type.AggregatePayloadTypeName}>("); + $" executor.ExecuteGeneral<{type.RecordName},NoInjection,{type.AggregatePayloadTypeName}>("); sb.AppendLine(" command,"); sb.AppendLine(" projector,"); sb.AppendLine(" specifyPartitionKeys,"); + sb.AppendLine(" NoInjection.Empty,"); sb.AppendLine(" handler);"); sb.AppendLine(); break; diff --git a/src/Sekiban.Pure/Class1.cs b/src/Sekiban.Pure/Class1.cs index d596aca6..20c92cb2 100644 --- a/src/Sekiban.Pure/Class1.cs +++ b/src/Sekiban.Pure/Class1.cs @@ -497,7 +497,7 @@ public record CommandResource( public Func GetSpecifyPartitionKeysFunc() => SpecifyPartitionKeys; public Type GetCommandType() => typeof(TCommand); public IAggregateProjector GetProjector() => new TProjector(); - public object GetInjection() => NoInjection.Empty; + public object? GetInjection() => NoInjection.Empty; public Delegate GetHandler() => Handler; public OptionalValue GetAggregatePayloadType() => OptionalValue.Empty; } @@ -524,7 +524,7 @@ public record CommandResourceWithInject( public Func GetSpecifyPartitionKeysFunc() => SpecifyPartitionKeys; public Type GetCommandType() => typeof(TCommand); public IAggregateProjector GetProjector() => new TProjector(); - public object GetInjection() => NoInjection.Empty; + public object? GetInjection() => Injection; public Delegate GetHandler() => Handler; public OptionalValue GetAggregatePayloadType() => OptionalValue.Empty; } @@ -538,14 +538,14 @@ public record CommandResourceWithInjectTask( public Func GetSpecifyPartitionKeysFunc() => SpecifyPartitionKeys; public Type GetCommandType() => typeof(TCommand); public IAggregateProjector GetProjector() => new TProjector(); - public object GetInjection() => NoInjection.Empty; + public object? GetInjection() => Injection; public Delegate GetHandler() => Handler; public OptionalValue GetAggregatePayloadType() => OptionalValue.Empty; } public record CommandResourceWithInject( Func SpecifyPartitionKeys, TInject? Injection, - Func, Task>> Handler) + Func, ResultBox> Handler) : ICommandResource where TCommand : ICommand, IEquatable where TAggregatePayload : IAggregatePayload where TProjector : IAggregateProjector, new() diff --git a/tests/Pure.Domain.Test/Pure.Domain.Test.csproj b/tests/Pure.Domain.Test/Pure.Domain.Test.csproj index 17db7e9e..02ee43ad 100644 --- a/tests/Pure.Domain.Test/Pure.Domain.Test.csproj +++ b/tests/Pure.Domain.Test/Pure.Domain.Test.csproj @@ -5,14 +5,17 @@ enable enable false - true + - + - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/tests/Pure.Domain.Test/UnitTest1.cs b/tests/Pure.Domain.Test/UnitTest1.cs index f38e0a83..6c61897d 100644 --- a/tests/Pure.Domain.Test/UnitTest1.cs +++ b/tests/Pure.Domain.Test/UnitTest1.cs @@ -1,4 +1,5 @@ -using ResultBoxes; +using Pure.Domain.Generated; +using ResultBoxes; using Sekiban.Pure; using Sekiban.Pure.Exception; namespace Pure.Domain.Test; @@ -31,7 +32,7 @@ public void TenantPartitionKeysTest() public async Task SimpleEventSourcing() { Repository.Events.Clear(); - var executor = new CommandExecutor { EventTypes = new CpPureDomainEventTypes() }; + var executor = new CommandExecutor { EventTypes = new PureDomainEventTypes() }; Assert.Empty(Repository.Events); await executor.Execute(new RegisterBranch("branch1")); @@ -82,7 +83,7 @@ public async Task SimpleEventSourcing() public async Task SimpleEventSourcingFunction() { Repository.Events.Clear(); - var executor = new CommandExecutor { EventTypes = new CpPureDomainEventTypes() }; + var executor = new CommandExecutor { EventTypes = new PureDomainEventTypes() }; Assert.Empty(Repository.Events); var registerBranch = new RegisterBranch("branch1"); @@ -163,11 +164,100 @@ await executor.ExecuteFunction( Assert.IsType(revokeResult2.GetException()); } + + [Fact] + public async Task SimpleEventSourcingResource() + { + Repository.Events.Clear(); + var executor = new CommandExecutor { EventTypes = new PureDomainEventTypes() }; + + Assert.Empty(Repository.Events); + var registerBranch = new RegisterBranch("branch1"); + await executor.ExecuteWithResource( + registerBranch, + new CommandResource( + registerBranch.SpecifyPartitionKeys, + registerBranch.Handle)); + + Assert.Single(Repository.Events); + var last = Repository.Events.Last(); + Assert.IsType>(last); + + var aggregate = Repository.Load(last.PartitionKeys, new BranchProjector()).UnwrapBox(); + var payload = aggregate.GetPayload(); + Assert.IsType(payload); + + var registerUser = new RegisterUser("tomo", "tomo@example.com"); + var userExecuted = await executor + .ExecuteWithResource( + registerUser, + new CommandResourceWithInject( + registerUser.SpecifyPartitionKeys, + new RegisterUser.Injection(_ => false), + registerUser.Handle)) + .UnwrapBox(); + + Assert.NotNull(userExecuted); + + var confirmUser = new ConfirmUser(userExecuted.PartitionKeys.AggregateId); + + var confirmResult = await executor.ExecuteFunction( + confirmUser, + new UserProjector(), + confirmUser.SpecifyPartitionKeys, + confirmUser.Handle); + Assert.NotNull(confirmResult); + Assert.True(confirmResult.IsSuccess); + var confirmResult2 = await executor.ExecuteWithResource( + confirmUser, + new CommandResource( + confirmUser.SpecifyPartitionKeys, + confirmUser.Handle)); + Assert.NotNull(confirmResult2); + Assert.False(confirmResult2.IsSuccess); // already confirmed, it should fail + Assert.IsType(confirmResult2.GetException()); + + var revokeCommand = new RevokeUser(userExecuted.PartitionKeys.AggregateId); + var revokeResultFailggg = await executor.ExecuteFunction( + revokeCommand, + new UserProjector(), + revokeCommand.SpecifyPartitionKeys, + new RevokeUser.Injection(_ => false), + revokeCommand.Handle); + var revokeResultFail = await executor.ExecuteWithResource( + revokeCommand, + new CommandResourceWithInject( + revokeCommand.SpecifyPartitionKeys, + new RevokeUser.Injection(_ => false), + revokeCommand.Handle)); + Assert.NotNull(revokeResultFail); + Assert.False(revokeResultFail.IsSuccess); // when use not exists, it should fail + Assert.IsType(revokeResultFail.GetException()); + + var revokeResult = await executor.ExecuteWithResource( + revokeCommand, + new CommandResourceWithInject( + revokeCommand.SpecifyPartitionKeys, + new RevokeUser.Injection(_ => true), + revokeCommand.Handle)); + Assert.NotNull(revokeResult); + Assert.True(revokeResult.IsSuccess); + var revokeResult2 = await executor.ExecuteWithResource( + revokeCommand, + new CommandResourceWithInject( + revokeCommand.SpecifyPartitionKeys, + new RevokeUser.Injection(_ => true), + revokeCommand.Handle)); + Assert.NotNull(revokeResult2); + Assert.False(revokeResult2.IsSuccess); // already revoked, it should fail + Assert.IsType(revokeResult2.GetException()); + } + [Fact] public async Task ChangeBranchNameSpec() { Repository.Events.Clear(); - var executor = new CommandExecutor { EventTypes = new CpPureDomainEventTypes() }; + var executor = new CommandExecutor { EventTypes = new PureDomainEventTypes() }; Assert.Empty(Repository.Events); var executed = await executor.Execute(new RegisterBranch("branch1")); @@ -203,7 +293,7 @@ public void CanUseDelegateSpec() public async Task MultipleBranchesSpec() { Repository.Events.Clear(); - var executor = new CommandExecutor { EventTypes = new CpPureDomainEventTypes() }; + var executor = new CommandExecutor { EventTypes = new PureDomainEventTypes() }; Assert.Empty(Repository.Events); var executed = await executor.Execute(new RegisterBranch("branch 0")); @@ -233,7 +323,7 @@ public async Task MultipleBranchesSpec() public async Task ICommandAndICommandWithAggregateRestrictionShouldWorkWithFunctionTest() { Repository.Events.Clear(); - var executor = new CommandExecutor { EventTypes = new CpPureDomainEventTypes() }; + var executor = new CommandExecutor { EventTypes = new PureDomainEventTypes() }; var command1 = new RegisterBranch2("aaa"); var result = await executor.ExecuteFunction( @@ -267,7 +357,7 @@ public async Task ICommandAndICommandWithAggregateRestrictionShouldWorkWithFunct [Fact] public async Task ShoppingCartSpec() { - var executor = new CommandExecutor { EventTypes = new CpPureDomainEventTypes() }; + var executor = new CommandExecutor { EventTypes = new PureDomainEventTypes() }; var userId = Guid.NewGuid(); var createCommand = new CreateShoppingCart(userId); var result = await executor.Execute(createCommand); @@ -285,7 +375,7 @@ var buyingShoppingCart [Fact] public async Task ShoppingCartSpecFunction() { - var executor = new CommandExecutor { EventTypes = new CpPureDomainEventTypes() }; + var executor = new CommandExecutor { EventTypes = new PureDomainEventTypes() }; var userId = Guid.NewGuid(); var createCommand = new CreateShoppingCart(userId); var result = await executor.ExecuteFunctionAsync( @@ -306,7 +396,7 @@ var buyingShoppingCart [Fact] public async Task ExecuteWithGeneric() { - var executor = new CommandExecutor { EventTypes = new CpPureDomainEventTypes() }; + var executor = new CommandExecutor { EventTypes = new PureDomainEventTypes() }; var createCommand = new RegisterBranch("a"); var result = await executor.ExecuteGeneralNonGeneric( createCommand, @@ -320,7 +410,7 @@ public async Task ExecuteWithGeneric() [Fact] public async Task ExecuteWithoutGeneric() { - var executor = new CommandExecutor { EventTypes = new CpPureDomainEventTypes() }; + var executor = new CommandExecutor { EventTypes = new PureDomainEventTypes() }; var createCommand = new RegisterBranch("a"); var result = await executor.Execute(createCommand); Assert.True(result.IsSuccess);