132 lines
5.3 KiB
C#
132 lines
5.3 KiB
C#
using System.Threading;
|
|
using Svrnty.CQRS.Events.Abstractions.Models;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Svrnty.CQRS.Events.Abstractions.EventHandlers;
|
|
|
|
/// <summary>
|
|
/// Handler interface for commands that participate in a workflow and return a result.
|
|
/// The workflow manages event emission and correlation.
|
|
/// </summary>
|
|
/// <typeparam name="TCommand">The command type to handle.</typeparam>
|
|
/// <typeparam name="TResult">The result type returned by the handler.</typeparam>
|
|
/// <typeparam name="TWorkflow">The workflow type that manages events for this command. Must inherit from <see cref="Workflow"/>.</typeparam>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// <strong>Workflow Pattern:</strong>
|
|
/// Instead of manually managing event contexts and correlation IDs, handlers receive a workflow instance.
|
|
/// The workflow encapsulates the business process and provides methods to emit events.
|
|
/// All events emitted within the workflow are automatically correlated using the workflow's ID.
|
|
/// </para>
|
|
/// <para>
|
|
/// <strong>Example Usage:</strong>
|
|
/// <code>
|
|
/// public class InviteUserCommandHandler
|
|
/// : ICommandHandlerWithWorkflow<InviteUserCommand, string, InvitationWorkflow>
|
|
/// {
|
|
/// public async Task<string> HandleAsync(
|
|
/// InviteUserCommand command,
|
|
/// InvitationWorkflow workflow,
|
|
/// CancellationToken cancellationToken)
|
|
/// {
|
|
/// // Business logic
|
|
/// var invitationId = Guid.NewGuid().ToString();
|
|
///
|
|
/// // Emit event via workflow (automatically correlated)
|
|
/// workflow.Emit(new UserInvitedEvent
|
|
/// {
|
|
/// InvitationId = invitationId,
|
|
/// Email = command.Email
|
|
/// });
|
|
///
|
|
/// // Return workflow ID for follow-up commands
|
|
/// return workflow.Id;
|
|
/// }
|
|
/// }
|
|
/// </code>
|
|
/// </para>
|
|
/// <para>
|
|
/// <strong>Framework Behavior:</strong>
|
|
/// - The framework creates/loads the workflow instance before calling the handler
|
|
/// - Workflow.Id is set (either new GUID or existing workflow ID)
|
|
/// - Workflow.IsNew indicates if this is a new workflow or continuation
|
|
/// - After the handler completes, the framework emits all events collected in the workflow
|
|
/// - All events receive the workflow ID as their correlation ID
|
|
/// </para>
|
|
/// </remarks>
|
|
public interface ICommandHandlerWithWorkflow<in TCommand, TResult, TWorkflow>
|
|
where TCommand : class
|
|
where TWorkflow : Workflow
|
|
{
|
|
/// <summary>
|
|
/// Handles the command within the context of a workflow.
|
|
/// </summary>
|
|
/// <param name="command">The command to handle.</param>
|
|
/// <param name="workflow">The workflow instance managing events for this command execution.</param>
|
|
/// <param name="cancellationToken">Cancellation token for the async operation.</param>
|
|
/// <returns>The result of handling the command.</returns>
|
|
/// <remarks>
|
|
/// Emit events by calling methods on the workflow instance (which internally call workflow.Emit()).
|
|
/// The framework will persist all emitted events after this method completes successfully.
|
|
/// </remarks>
|
|
Task<TResult> HandleAsync(
|
|
TCommand command,
|
|
TWorkflow workflow,
|
|
CancellationToken cancellationToken = default);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Handler interface for commands that participate in a workflow but do not return a result.
|
|
/// The workflow manages event emission and correlation.
|
|
/// </summary>
|
|
/// <typeparam name="TCommand">The command type to handle.</typeparam>
|
|
/// <typeparam name="TWorkflow">The workflow type that manages events for this command. Must inherit from <see cref="Workflow"/>.</typeparam>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// This is the "no result" variant of <see cref="ICommandHandlerWithWorkflow{TCommand, TResult, TWorkflow}"/>.
|
|
/// Use this when your command performs an action but doesn't need to return a value.
|
|
/// </para>
|
|
/// <para>
|
|
/// <strong>Example Usage:</strong>
|
|
/// <code>
|
|
/// public class DeclineInviteCommandHandler
|
|
/// : ICommandHandlerWithWorkflow<DeclineInviteCommand, InvitationWorkflow>
|
|
/// {
|
|
/// public async Task HandleAsync(
|
|
/// DeclineInviteCommand command,
|
|
/// InvitationWorkflow workflow,
|
|
/// CancellationToken cancellationToken)
|
|
/// {
|
|
/// workflow.Emit(new UserInviteDeclinedEvent
|
|
/// {
|
|
/// InvitationId = command.InvitationId,
|
|
/// Reason = command.Reason
|
|
/// });
|
|
///
|
|
/// await Task.CompletedTask;
|
|
/// }
|
|
/// }
|
|
/// </code>
|
|
/// </para>
|
|
/// </remarks>
|
|
public interface ICommandHandlerWithWorkflow<in TCommand, TWorkflow>
|
|
where TCommand : class
|
|
where TWorkflow : Workflow
|
|
{
|
|
/// <summary>
|
|
/// Handles the command within the context of a workflow.
|
|
/// </summary>
|
|
/// <param name="command">The command to handle.</param>
|
|
/// <param name="workflow">The workflow instance managing events for this command execution.</param>
|
|
/// <param name="cancellationToken">Cancellation token for the async operation.</param>
|
|
/// <returns>A task representing the async operation.</returns>
|
|
/// <remarks>
|
|
/// Emit events by calling methods on the workflow instance (which internally call workflow.Emit()).
|
|
/// The framework will persist all emitted events after this method completes successfully.
|
|
/// </remarks>
|
|
Task HandleAsync(
|
|
TCommand command,
|
|
TWorkflow workflow,
|
|
CancellationToken cancellationToken = default);
|
|
}
|