From 861fe40f661fc0d78f5b44b22bc3f2418e47e8e5 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Thu, 6 Feb 2025 16:45:25 +0100 Subject: [PATCH 1/8] Merge pull request #6370 from yinzara/feature/alterations-client-api MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added Alterations API to Client API library and updated server API co… --- .../Alterations/Contracts/IAlteration.cs | 6 +++ .../Alterations/Contracts/IAlterationsApi.cs | 52 +++++++++++++++++++ .../Alterations/Enums/ActivityStatus.cs | 32 ++++++++++++ .../Alterations/Enums/AlterationJobStatus.cs | 27 ++++++++++ .../Alterations/Enums/AlterationPlanStatus.cs | 37 +++++++++++++ .../Alterations/Models/ActivityFilter.cs | 34 ++++++++++++ .../Alterations/Models/AlterationBase.cs | 8 +++ .../Alterations/Models/AlterationJob.cs | 45 ++++++++++++++++ .../Alterations/Models/AlterationLog.cs | 13 +++++ .../Alterations/Models/AlterationLogEntry.cs | 12 +++++ .../Alterations/Models/AlterationPlan.cs | 41 +++++++++++++++ .../Models/AlterationPlanParams.cs | 24 +++++++++ .../AlterationWorkflowInstanceFilter.cs | 45 ++++++++++++++++ .../Alterations/Models/CancelActivity.cs | 17 ++++++ .../Resources/Alterations/Models/Migrate.cs | 12 +++++ .../Alterations/Models/ModifyVariable.cs | 18 +++++++ .../Models/RunAlterationsResult.cs | 27 ++++++++++ .../Alterations/Models/ScheduleActivity.cs | 17 ++++++ .../Alterations/Requests/BulkRetryRequest.cs | 17 ++++++ .../Responses/BulkRetryResponse.cs | 14 +++++ .../Alterations/Responses/DryRunResponse.cs | 12 +++++ .../Responses/GetAlterationPlanResponse.cs | 19 +++++++ .../Alterations/Responses/RunRequest.cs | 19 +++++++ .../Alterations/Responses/RunResponse.cs | 14 +++++ .../Alterations/Responses/SubmitResponse.cs | 12 +++++ .../Models/AlterationPlanParams.cs | 2 +- .../Endpoints/Alterations/DryRun/Endpoint.cs | 2 +- .../Endpoints/Alterations/Get/Endpoint.cs | 2 +- .../Endpoints/Alterations/Run/Endpoint.cs | 2 +- .../Endpoints/Alterations/Submit/Endpoint.cs | 2 +- 30 files changed, 579 insertions(+), 5 deletions(-) create mode 100644 src/clients/Elsa.Api.Client/Resources/Alterations/Contracts/IAlteration.cs create mode 100644 src/clients/Elsa.Api.Client/Resources/Alterations/Contracts/IAlterationsApi.cs create mode 100644 src/clients/Elsa.Api.Client/Resources/Alterations/Enums/ActivityStatus.cs create mode 100644 src/clients/Elsa.Api.Client/Resources/Alterations/Enums/AlterationJobStatus.cs create mode 100644 src/clients/Elsa.Api.Client/Resources/Alterations/Enums/AlterationPlanStatus.cs create mode 100644 src/clients/Elsa.Api.Client/Resources/Alterations/Models/ActivityFilter.cs create mode 100644 src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationBase.cs create mode 100644 src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationJob.cs create mode 100644 src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationLog.cs create mode 100644 src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationLogEntry.cs create mode 100644 src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationPlan.cs create mode 100644 src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationPlanParams.cs create mode 100644 src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationWorkflowInstanceFilter.cs create mode 100644 src/clients/Elsa.Api.Client/Resources/Alterations/Models/CancelActivity.cs create mode 100644 src/clients/Elsa.Api.Client/Resources/Alterations/Models/Migrate.cs create mode 100644 src/clients/Elsa.Api.Client/Resources/Alterations/Models/ModifyVariable.cs create mode 100644 src/clients/Elsa.Api.Client/Resources/Alterations/Models/RunAlterationsResult.cs create mode 100644 src/clients/Elsa.Api.Client/Resources/Alterations/Models/ScheduleActivity.cs create mode 100644 src/clients/Elsa.Api.Client/Resources/Alterations/Requests/BulkRetryRequest.cs create mode 100644 src/clients/Elsa.Api.Client/Resources/Alterations/Responses/BulkRetryResponse.cs create mode 100644 src/clients/Elsa.Api.Client/Resources/Alterations/Responses/DryRunResponse.cs create mode 100644 src/clients/Elsa.Api.Client/Resources/Alterations/Responses/GetAlterationPlanResponse.cs create mode 100644 src/clients/Elsa.Api.Client/Resources/Alterations/Responses/RunRequest.cs create mode 100644 src/clients/Elsa.Api.Client/Resources/Alterations/Responses/RunResponse.cs create mode 100644 src/clients/Elsa.Api.Client/Resources/Alterations/Responses/SubmitResponse.cs diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Contracts/IAlteration.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Contracts/IAlteration.cs new file mode 100644 index 0000000000..0ce1f7a50b --- /dev/null +++ b/src/clients/Elsa.Api.Client/Resources/Alterations/Contracts/IAlteration.cs @@ -0,0 +1,6 @@ +namespace Elsa.Api.Client.Resources.Alterations.Contracts; + +/// +/// Marker interface for all alteration classes +/// +public interface IAlteration; \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Contracts/IAlterationsApi.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Contracts/IAlterationsApi.cs new file mode 100644 index 0000000000..6e212ec363 --- /dev/null +++ b/src/clients/Elsa.Api.Client/Resources/Alterations/Contracts/IAlterationsApi.cs @@ -0,0 +1,52 @@ +using Elsa.Api.Client.Resources.Alterations.Models; +using Elsa.Api.Client.Resources.Alterations.Requests; +using Elsa.Api.Client.Resources.Alterations.Responses; +using Refit; + +namespace Elsa.Api.Client.Resources.Alterations.Contracts; + +/// +/// Represents a client for the alterations API. Requires the Elsa.Alterations feature. +/// +public interface IAlterationsApi +{ + /// + /// Returns an alteration plan and its associated jobs. + /// + /// The ID of the alteration plan to return. + /// The cancellation token. + [Get("/alterations/{id}")] + Task GetAsync(string id, CancellationToken cancellationToken = default); + + /// + /// Determines which workflow instances a "Submit" request would target without actually running an alteration + /// + /// The requested workflow filter to dry run + /// The cancellation token. + [Post("/alterations/dry-run")] + Task DryRun(AlterationWorkflowInstanceFilter request, CancellationToken cancellationToken = default); + + /// + /// Submits an alteration plan and a filter for workflows instances to be executed against + /// + /// The alterations and filter to submit + /// The cancellation token. + [Post("/alterations/submit")] + Task Submit(AlterationPlanParams request, CancellationToken cancellationToken = default); + + /// + /// Runs an alteration plan and a list of workflow Instance Ids to be executed against + /// + /// The alterations and workflowInstanceIds to execute + /// The cancellation token. + [Post("/alterations/run")] + Task Run(RunRequest request, CancellationToken cancellationToken = default); + + /// + /// Retries the specified workflow instances. + /// + /// The request containing the selection of workflow instances to retry. + /// The cancellation token. + [Post("/alterations/workflows/retry")] + Task BulkRetryAsync(BulkRetryRequest request, CancellationToken cancellationToken); +} \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Enums/ActivityStatus.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Enums/ActivityStatus.cs new file mode 100644 index 0000000000..a4693e6ae9 --- /dev/null +++ b/src/clients/Elsa.Api.Client/Resources/Alterations/Enums/ActivityStatus.cs @@ -0,0 +1,32 @@ +namespace Elsa.Api.Client.Resources.Alterations.Enums; + +/// +/// Represents the status of an activity. +/// +public enum ActivityStatus +{ + /// + /// The activity is in the Pending state. + /// + Pending, + + /// + /// The activity is in the Running state. Note that event if an activity is running, it may not be executing. + /// + Running, + + /// + /// The activity is in the Completed state. + /// + Completed, + + /// + /// The activity is in the Canceled state. + /// + Canceled, + + /// + /// The activity is in the Faulted state. + /// + Faulted +} \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Enums/AlterationJobStatus.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Enums/AlterationJobStatus.cs new file mode 100644 index 0000000000..49e65a99a5 --- /dev/null +++ b/src/clients/Elsa.Api.Client/Resources/Alterations/Enums/AlterationJobStatus.cs @@ -0,0 +1,27 @@ +namespace Elsa.Api.Client.Resources.Alterations.Enums; + +/// +/// The status of an alteration plan for a workflow instance. +/// +public enum AlterationJobStatus +{ + /// + /// The plan is pending execution. + /// + Pending, + + /// + /// The plan is currently being executed. + /// + Running, + + /// + /// The plan has been completed. + /// + Completed, + + /// + /// The job has failed. + /// + Failed +} \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Enums/AlterationPlanStatus.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Enums/AlterationPlanStatus.cs new file mode 100644 index 0000000000..80ded4c2e5 --- /dev/null +++ b/src/clients/Elsa.Api.Client/Resources/Alterations/Enums/AlterationPlanStatus.cs @@ -0,0 +1,37 @@ +namespace Elsa.Api.Client.Resources.Alterations.Enums; + +/// +/// The status of an alteration plan. +/// +public enum AlterationPlanStatus +{ + /// + /// The plan is pending execution. + /// + Pending, + + /// + /// The plan is currently generating jobs. + /// + Generating, + + /// + /// The plan is currently dispatching jobs. + /// + Dispatching, + + /// + /// The plan is currently being executed. + /// + Running, + + /// + /// The plan has been completed. + /// + Completed, + + /// + /// The plan has failed. + /// + Failed +} \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Models/ActivityFilter.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/ActivityFilter.cs new file mode 100644 index 0000000000..37fdec5ee5 --- /dev/null +++ b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/ActivityFilter.cs @@ -0,0 +1,34 @@ +using Elsa.Api.Client.Resources.Alterations.Enums; + +namespace Elsa.Api.Client.Resources.Alterations.Models; + +/// +/// A filter for activities within a workflow instance +/// +public class ActivityFilter +{ + /// + /// The ID of the activity. + /// + public string? ActivityId { get; set; } + + /// + /// The ID of the activity instance. + /// + public string? ActivityInstanceId { get; set; } + + /// + /// The node ID of the activity. + /// + public string? NodeId { get; set; } + + /// + /// The name of the activity. + /// + public string? Name { get; set; } + + /// + /// The status of the activity. + /// + public ActivityStatus? Status { get; set; } +} \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationBase.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationBase.cs new file mode 100644 index 0000000000..18615eca90 --- /dev/null +++ b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationBase.cs @@ -0,0 +1,8 @@ +using Elsa.Api.Client.Resources.Alterations.Contracts; + +namespace Elsa.Api.Client.Resources.Alterations.Models; + +/// +/// A base class for all IAlterations. +/// +public abstract class AlterationBase : IAlteration; \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationJob.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationJob.cs new file mode 100644 index 0000000000..d756c23d76 --- /dev/null +++ b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationJob.cs @@ -0,0 +1,45 @@ +using Elsa.Api.Client.Resources.Alterations.Enums; +using Elsa.Api.Client.Shared.Models; + +namespace Elsa.Api.Client.Resources.Alterations.Models; + +/// +/// Represents the execution of the plan for an individual workflow instance. +/// +public class AlterationJob : Entity +{ + /// + /// The ID of the plan that this job belongs to. + /// + public string PlanId { get; set; } = default!; + + /// + /// The ID of the workflow instance that this job applies to. + /// + public string WorkflowInstanceId { get; set; } = default!; + + /// + /// The status of the job. + /// + public AlterationJobStatus Status { get; set; } + + /// + /// The serialized log of the job. + /// + public ICollection? Log { get; set; } = new List(); + + /// + /// The date and time at which the job was created. + /// + public DateTimeOffset CreatedAt { get; set; } + + /// + /// The date and time at which the job was started. + /// + public DateTimeOffset? StartedAt { get; set; } + + /// + /// The date and time at which the job was completed. + /// + public DateTimeOffset? CompletedAt { get; set; } +} \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationLog.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationLog.cs new file mode 100644 index 0000000000..c39d44c123 --- /dev/null +++ b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationLog.cs @@ -0,0 +1,13 @@ +namespace Elsa.Api.Client.Resources.Alterations.Models; + +/// +/// Represents a log of alterations. +/// +public class AlterationLog +{ + + /// + /// The log entries. + /// + public ICollection LogEntries { get; set; } = new List(); +} \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationLogEntry.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationLogEntry.cs new file mode 100644 index 0000000000..9c661275ba --- /dev/null +++ b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationLogEntry.cs @@ -0,0 +1,12 @@ +using Microsoft.Extensions.Logging; + +namespace Elsa.Api.Client.Resources.Alterations.Models; + +/// +/// An individual log entry about an alteration +/// +/// +/// +/// +/// +public record AlterationLogEntry(string Message, LogLevel LogLevel, DateTimeOffset Timestamp, string? EventName = null); \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationPlan.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationPlan.cs new file mode 100644 index 0000000000..993858cf51 --- /dev/null +++ b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationPlan.cs @@ -0,0 +1,41 @@ +using Elsa.Api.Client.Resources.Alterations.Contracts; +using Elsa.Api.Client.Resources.Alterations.Enums; +using Elsa.Api.Client.Shared.Models; + +namespace Elsa.Api.Client.Resources.Alterations.Models; + +/// +/// A plan that contains a list of alterations to be applied to a set of workflow instances. +/// +public class AlterationPlan : Entity +{ + /// + /// The alterations to be applied. + /// + public ICollection Alterations { get; set; } = new List(); + + /// + /// The IDs of the workflow instances that this plan applies to. + /// + public AlterationWorkflowInstanceFilter WorkflowInstanceFilter { get; set; } = new(); + + /// + /// The status of the plan. + /// + public AlterationPlanStatus Status { get; set; } + + /// + /// The date and time at which the plan was created. + /// + public DateTimeOffset CreatedAt { get; set; } + + /// + /// The date and time at which the plan was started. + /// + public DateTimeOffset? StartedAt { get; set; } + + /// + /// The date and time at which the plan was completed. + /// + public DateTimeOffset? CompletedAt { get; set; } +} \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationPlanParams.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationPlanParams.cs new file mode 100644 index 0000000000..f9fc5a1c1e --- /dev/null +++ b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationPlanParams.cs @@ -0,0 +1,24 @@ +using Elsa.Api.Client.Resources.Alterations.Contracts; + +namespace Elsa.Api.Client.Resources.Alterations.Models; + +/// +/// Represents the execution of an alteration plan against a set of workflow instances defined by the given filter +/// +public class AlterationPlanParams +{ + /// + /// The unique identifier for the alteration plan. If not specified, a new ID will be generated. + /// + public string? Id { get; set; } + + /// + /// The alterations to be applied. + /// + public ICollection Alterations { get; set; } = new List(); + + /// + /// The IDs of the workflow instances that this plan applies to. + /// + public AlterationWorkflowInstanceFilter Filter { get; set; } = new(); +} \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationWorkflowInstanceFilter.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationWorkflowInstanceFilter.cs new file mode 100644 index 0000000000..6f4419114c --- /dev/null +++ b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationWorkflowInstanceFilter.cs @@ -0,0 +1,45 @@ +using Elsa.Api.Client.Shared.Models; + +namespace Elsa.Api.Client.Resources.Alterations.Models; + +/// +/// Represents a filter for workflow instances. +/// +public class AlterationWorkflowInstanceFilter +{ + /// + /// The IDs of the workflow instances that this plan applies to. + /// + public IEnumerable? WorkflowInstanceIds { get; set; } + + /// + /// The correlation IDs of the workflow instances that this plan applies to. + /// + public IEnumerable? CorrelationIds { get; set; } + + /// + /// A collection of timestamp filters used for filtering data based on specified timestamp columns and operators. + /// + public IEnumerable? TimestampFilters { get; set; } + + /// + /// The IDs of the workflow definitions that this plan applies to. + /// + public IEnumerable? DefinitionVersionIds { get; set; } + + /// + /// Whether the workflow instances to match have incidents. + /// + public bool? HasIncidents { get; set; } + + /// + /// Whether the workflow instances to match are system workflows. Defaults to false. + /// + public bool? IsSystem { get; set; } = false; + + /// + /// Represents a collection of filters for activities. + /// + public IEnumerable? ActivityFilters { get; set; } + +} \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Models/CancelActivity.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/CancelActivity.cs new file mode 100644 index 0000000000..2500e7d975 --- /dev/null +++ b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/CancelActivity.cs @@ -0,0 +1,17 @@ +namespace Elsa.Api.Client.Resources.Alterations.Models; + +/// +/// Cancels a workflow instance activity during an alteration +/// +public class CancelActivity : AlterationBase +{ + /// + /// The ID of the activity to be cancelled. If not specified, the activity instance ID will be used. + /// + public string? ActivityId { get; set; } + + /// + /// The ID of the activity instance to be cancelled. If specified, overrides . + /// + public string? ActivityInstanceId { get; set; } +} \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Models/Migrate.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/Migrate.cs new file mode 100644 index 0000000000..1a4dc3b692 --- /dev/null +++ b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/Migrate.cs @@ -0,0 +1,12 @@ +namespace Elsa.Api.Client.Resources.Alterations.Models; + +/// +/// Migrates a workflow instance to a newer version in an alteration. +/// +public class Migrate : AlterationBase +{ + /// + /// The target version to upgrade to. + /// + public int TargetVersion { get; set; } +} \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Models/ModifyVariable.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/ModifyVariable.cs new file mode 100644 index 0000000000..60ab9f6bae --- /dev/null +++ b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/ModifyVariable.cs @@ -0,0 +1,18 @@ +namespace Elsa.Api.Client.Resources.Alterations.Models; + +/// +/// Modifies a variable in a workflow instance alteration +/// +public class ModifyVariable : AlterationBase +{ + /// + /// The ID of the variable to modify. + /// + public string VariableId { get; set; } = default!; + + /// + /// The new value of the variable. + /// + public object? Value { get; set; } + +} \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Models/RunAlterationsResult.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/RunAlterationsResult.cs new file mode 100644 index 0000000000..756240be2a --- /dev/null +++ b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/RunAlterationsResult.cs @@ -0,0 +1,27 @@ +namespace Elsa.Api.Client.Resources.Alterations.Models; + +/// +/// The result of running a series of alterations. +/// +public class RunAlterationsResult +{ + /// + /// The ID of the workflow instance that was altered. + /// + public string WorkflowInstanceId { get; set; } = string.Empty; + + /// + /// A log of the alterations that were run. + /// + public AlterationLog Log { get; set; } = new(); + + /// + /// A flag indicating whether the workflow has scheduled work. + /// + public bool WorkflowHasScheduledWork { get; set; } + + /// + /// A flag indicating whether the alterations have succeeded. + /// + public bool IsSuccessful { get; set; } +} \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Models/ScheduleActivity.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/ScheduleActivity.cs new file mode 100644 index 0000000000..2b0f77f6d3 --- /dev/null +++ b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/ScheduleActivity.cs @@ -0,0 +1,17 @@ +namespace Elsa.Api.Client.Resources.Alterations.Models; + +/// +/// Schedules an activity for execution in an alteration. +/// +public class ScheduleActivity : AlterationBase +{ + /// + /// The ID of the next activity to be scheduled. If not specified, the ActivityInstanceId will be used. + /// + public string? ActivityId { get; set; } + + /// + /// The ID of the activity instance to be scheduled. If not specified, the ActivityId will be used. + /// + public string? ActivityInstanceId { get; set; } +} \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Requests/BulkRetryRequest.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Requests/BulkRetryRequest.cs new file mode 100644 index 0000000000..2fbc9fdefb --- /dev/null +++ b/src/clients/Elsa.Api.Client/Resources/Alterations/Requests/BulkRetryRequest.cs @@ -0,0 +1,17 @@ +namespace Elsa.Api.Client.Resources.Alterations.Requests; + +/// +/// Represents a request to bulk retry workflow instances. +/// +public class BulkRetryRequest +{ + /// + /// The IDs of the workflow instances that have incidents to be retried. + /// + public ICollection WorkflowInstanceIds { get; set; } = new List(); + + /// + /// An optional list of explicitly specified activity IDs to retry. If omitted, all faulted activities will be retried. + /// + public ICollection? ActivityIds { get; set; } +} \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Responses/BulkRetryResponse.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Responses/BulkRetryResponse.cs new file mode 100644 index 0000000000..532e517c95 --- /dev/null +++ b/src/clients/Elsa.Api.Client/Resources/Alterations/Responses/BulkRetryResponse.cs @@ -0,0 +1,14 @@ +using Elsa.Api.Client.Resources.Alterations.Models; + +namespace Elsa.Api.Client.Resources.Alterations.Responses; + +/// +/// Represents a response to bulk retry workflow instances. +/// +public class BulkRetryResponse +{ + /// + /// The alterations that resulted from the bulk retry request + /// + public ICollection Results { get;set; } = new List(); +} \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Responses/DryRunResponse.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Responses/DryRunResponse.cs new file mode 100644 index 0000000000..6eb0d2beac --- /dev/null +++ b/src/clients/Elsa.Api.Client/Resources/Alterations/Responses/DryRunResponse.cs @@ -0,0 +1,12 @@ +namespace Elsa.Api.Client.Resources.Alterations.Responses; + +/// +/// The response to the DryRun request +/// +public class DryRunResponse +{ + /// + /// The list of workflow instance IDs that would be affected by a "Submit" request + /// + public ICollection WorkflowInstanceIds { get; set; } = new List(); +} \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Responses/GetAlterationPlanResponse.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Responses/GetAlterationPlanResponse.cs new file mode 100644 index 0000000000..c3fc2fb510 --- /dev/null +++ b/src/clients/Elsa.Api.Client/Resources/Alterations/Responses/GetAlterationPlanResponse.cs @@ -0,0 +1,19 @@ +using Elsa.Api.Client.Resources.Alterations.Models; + +namespace Elsa.Api.Client.Resources.Alterations.Responses; + +/// +/// The response from the "Get" alteration plan endpoint +/// +public class GetAlterationPlanResponse +{ + /// + /// The alteration plan mathching the provided ID + /// + public AlterationPlan Plan { get; set; } = new(); + + /// + /// The list of jobs that exist for that AlterationPlan + /// + public ICollection Jobs { get; set; } = new List(); +} \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Responses/RunRequest.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Responses/RunRequest.cs new file mode 100644 index 0000000000..fdaf341e8e --- /dev/null +++ b/src/clients/Elsa.Api.Client/Resources/Alterations/Responses/RunRequest.cs @@ -0,0 +1,19 @@ +using Elsa.Api.Client.Resources.Alterations.Contracts; + +namespace Elsa.Api.Client.Resources.Alterations.Responses; + +/// +/// A plan that contains a list of alterations to be applied to a set of workflow instances. +/// +public class RunRequest +{ + /// + /// The alterations to be applied. + /// + public ICollection Alterations { get; set; } = new List(); + + /// + /// The IDs of the workflow instances that this plan applies to. + /// + public ICollection WorkflowInstanceIds { get; set; } = new List(); +} \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Responses/RunResponse.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Responses/RunResponse.cs new file mode 100644 index 0000000000..0d65d891ea --- /dev/null +++ b/src/clients/Elsa.Api.Client/Resources/Alterations/Responses/RunResponse.cs @@ -0,0 +1,14 @@ +using Elsa.Api.Client.Resources.Alterations.Models; + +namespace Elsa.Api.Client.Resources.Alterations.Responses; + +/// +/// The response to the Run endpoint +/// +public class RunResponse +{ + /// + /// The alteration results of a Run request + /// + private ICollection Results { get; set; } = new List(); +} \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Responses/SubmitResponse.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Responses/SubmitResponse.cs new file mode 100644 index 0000000000..82c5cd1e35 --- /dev/null +++ b/src/clients/Elsa.Api.Client/Resources/Alterations/Responses/SubmitResponse.cs @@ -0,0 +1,12 @@ +namespace Elsa.Api.Client.Resources.Alterations.Responses; + +/// +/// The response to the "Submit" endpoint +/// +public class SubmitResponse +{ + /// + /// The ID of the alteration plan created as part of the Submit request + /// + public string PlanId { get; set; } = string.Empty; +} \ No newline at end of file diff --git a/src/modules/Elsa.Alterations.Core/Models/AlterationPlanParams.cs b/src/modules/Elsa.Alterations.Core/Models/AlterationPlanParams.cs index dec58d038e..08c266c4c9 100644 --- a/src/modules/Elsa.Alterations.Core/Models/AlterationPlanParams.cs +++ b/src/modules/Elsa.Alterations.Core/Models/AlterationPlanParams.cs @@ -18,7 +18,7 @@ public class AlterationPlanParams public ICollection Alterations { get; set; } = new List(); /// - /// The IDs of the workflow instances that this plan applies to. + /// The filter used to determine which workflow instances that this plan applies to. /// public AlterationWorkflowInstanceFilter Filter { get; set; } = new(); } \ No newline at end of file diff --git a/src/modules/Elsa.Alterations/Endpoints/Alterations/DryRun/Endpoint.cs b/src/modules/Elsa.Alterations/Endpoints/Alterations/DryRun/Endpoint.cs index eb9461dfff..cbf0d5471d 100644 --- a/src/modules/Elsa.Alterations/Endpoints/Alterations/DryRun/Endpoint.cs +++ b/src/modules/Elsa.Alterations/Endpoints/Alterations/DryRun/Endpoint.cs @@ -6,7 +6,7 @@ namespace Elsa.Alterations.Endpoints.Alterations.DryRun; /// -/// Executes an alteration plan. +/// Determines which workflow instances a "Submit" request would target without actually running an alteration. /// [PublicAPI] public class DryRun(IWorkflowInstanceFinder workflowInstanceFinder) : ElsaEndpoint diff --git a/src/modules/Elsa.Alterations/Endpoints/Alterations/Get/Endpoint.cs b/src/modules/Elsa.Alterations/Endpoints/Alterations/Get/Endpoint.cs index c1615636f5..7c4be8ebe5 100644 --- a/src/modules/Elsa.Alterations/Endpoints/Alterations/Get/Endpoint.cs +++ b/src/modules/Elsa.Alterations/Endpoints/Alterations/Get/Endpoint.cs @@ -6,7 +6,7 @@ namespace Elsa.Alterations.Endpoints.Alterations.Get; /// -/// Executes an alteration plan. +/// Gets an alteration plan and its associated jobs. /// [PublicAPI] public class Get : ElsaEndpointWithoutRequest diff --git a/src/modules/Elsa.Alterations/Endpoints/Alterations/Run/Endpoint.cs b/src/modules/Elsa.Alterations/Endpoints/Alterations/Run/Endpoint.cs index 4301682dbd..a1d090e5ef 100644 --- a/src/modules/Elsa.Alterations/Endpoints/Alterations/Run/Endpoint.cs +++ b/src/modules/Elsa.Alterations/Endpoints/Alterations/Run/Endpoint.cs @@ -5,7 +5,7 @@ namespace Elsa.Alterations.Endpoints.Alterations.Run; /// -/// Executes an alteration plan. +/// Executes an alteration plan by targeting workflow instances by ID. /// [PublicAPI] public class Run : ElsaEndpoint diff --git a/src/modules/Elsa.Alterations/Endpoints/Alterations/Submit/Endpoint.cs b/src/modules/Elsa.Alterations/Endpoints/Alterations/Submit/Endpoint.cs index 16cfcf3d54..bbf49d8ede 100644 --- a/src/modules/Elsa.Alterations/Endpoints/Alterations/Submit/Endpoint.cs +++ b/src/modules/Elsa.Alterations/Endpoints/Alterations/Submit/Endpoint.cs @@ -8,7 +8,7 @@ namespace Elsa.Alterations.Endpoints.Alterations.Submit; /// -/// Executes an alteration plan. +/// Submits an alteration plan to be executed targeting workflow instances by a filter. /// [PublicAPI] public class Submit : ElsaEndpoint From 7cc638b86f619033b09f5ba09ddce691eeed4f79 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Fri, 7 Feb 2025 19:54:26 +0100 Subject: [PATCH 2/8] Add filtering enhancements and clean up code inconsistencies Introduced new filtering capabilities such as `Names`, `Statuses`, `SubStatuses`, and `SearchTerm` for workflow instance filters. Simplified object initialization syntax and removed unnecessary attributes, improving code readability. Added missing dependencies and API service registrations to ensure completeness. --- .../DependencyInjectionExtensions.cs | 2 ++ .../AlterationWorkflowInstanceFilter.cs | 26 +++++++++++++++++++ .../AlterationWorkflowInstanceFilter.cs | 26 +++++++++++++++++++ .../Services/WorkflowInstanceFinder.cs | 6 ++++- .../DefaultAlterationPlanScheduler.cs | 1 - .../Services/MassTransitWorkflowDispatcher.cs | 4 +-- .../Filters/WorkflowInstanceFilter.cs | 6 +++++ .../WorkflowDispatcherExtensions.cs | 8 +++--- 8 files changed, 71 insertions(+), 8 deletions(-) diff --git a/src/clients/Elsa.Api.Client/Extensions/DependencyInjectionExtensions.cs b/src/clients/Elsa.Api.Client/Extensions/DependencyInjectionExtensions.cs index e7bed45078..ac5752cb6f 100644 --- a/src/clients/Elsa.Api.Client/Extensions/DependencyInjectionExtensions.cs +++ b/src/clients/Elsa.Api.Client/Extensions/DependencyInjectionExtensions.cs @@ -2,6 +2,7 @@ using Elsa.Api.Client.Resources.ActivityDescriptorOptions.Contracts; using Elsa.Api.Client.Resources.ActivityDescriptors.Contracts; using Elsa.Api.Client.Resources.ActivityExecutions.Contracts; +using Elsa.Api.Client.Resources.Alterations.Contracts; using Elsa.Api.Client.Resources.Features.Contracts; using Elsa.Api.Client.Resources.Identity.Contracts; using Elsa.Api.Client.Resources.IncidentStrategies.Contracts; @@ -68,6 +69,7 @@ public static IServiceCollection AddDefaultApiClients(this IServiceCollection se services.AddApi(builderOptions); services.AddApi(builderOptions); services.AddApi(builderOptions); + services.AddApi(builderOptions); }); } diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationWorkflowInstanceFilter.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationWorkflowInstanceFilter.cs index 6f4419114c..ff2e584f78 100644 --- a/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationWorkflowInstanceFilter.cs +++ b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationWorkflowInstanceFilter.cs @@ -1,3 +1,4 @@ +using Elsa.Api.Client.Resources.WorkflowInstances.Enums; using Elsa.Api.Client.Shared.Models; namespace Elsa.Api.Client.Resources.Alterations.Models; @@ -16,11 +17,26 @@ public class AlterationWorkflowInstanceFilter /// The correlation IDs of the workflow instances that this plan applies to. /// public IEnumerable? CorrelationIds { get; set; } + + /// + /// A collection of names associated with the workflow instances being filtered. + /// + public ICollection? Names { get; set; } + + /// + /// A search term used to filter workflow instances based on matching criteria. + /// + public string? SearchTerm { get; set; } /// /// A collection of timestamp filters used for filtering data based on specified timestamp columns and operators. /// public IEnumerable? TimestampFilters { get; set; } + + /// + /// The IDs of the workflow definitions that this plan applies to. + /// + public ICollection? DefinitionIds { get; set; } /// /// The IDs of the workflow definitions that this plan applies to. @@ -37,6 +53,16 @@ public class AlterationWorkflowInstanceFilter /// public bool? IsSystem { get; set; } = false; + /// + /// Represents the workflow statuses included in the filter. + /// + public ICollection? Statuses { get; set; } + + /// + /// A collection of sub-statuses used to filter workflow instances by their specific sub-state. + /// + public ICollection? SubStatuses { get; set; } + /// /// Represents a collection of filters for activities. /// diff --git a/src/modules/Elsa.Alterations.Core/Models/AlterationWorkflowInstanceFilter.cs b/src/modules/Elsa.Alterations.Core/Models/AlterationWorkflowInstanceFilter.cs index de83e2c32c..12d9d863cf 100644 --- a/src/modules/Elsa.Alterations.Core/Models/AlterationWorkflowInstanceFilter.cs +++ b/src/modules/Elsa.Alterations.Core/Models/AlterationWorkflowInstanceFilter.cs @@ -1,3 +1,4 @@ +using Elsa.Workflows; using Elsa.Workflows.Management.Models; using JetBrains.Annotations; @@ -19,11 +20,26 @@ public class AlterationWorkflowInstanceFilter /// public IEnumerable? CorrelationIds { get; set; } + /// + /// A collection of names associated with the workflow instances being filtered. + /// + public ICollection? Names { get; set; } + + /// + /// A search term used to filter workflow instances based on matching criteria. + /// + public string? SearchTerm { get; set; } + /// /// A collection of timestamp filters used for filtering data based on specified timestamp columns and operators. /// public IEnumerable? TimestampFilters { get; set; } + /// + /// The IDs of the workflow definitions that this plan applies to. + /// + public ICollection? DefinitionIds { get; set; } + /// /// The IDs of the workflow definitions that this plan applies to. /// @@ -38,6 +54,16 @@ public class AlterationWorkflowInstanceFilter /// Whether the workflow instances to match are system workflows. Defaults to false. /// public bool? IsSystem { get; set; } = false; + + /// + /// Represents the workflow statuses included in the filter. + /// + public ICollection? Statuses { get; set; } + + /// + /// A collection of sub-statuses used to filter workflow instances by their specific sub-state. + /// + public ICollection? SubStatuses { get; set; } /// /// Represents a collection of filters for activities. diff --git a/src/modules/Elsa.Alterations.Core/Services/WorkflowInstanceFinder.cs b/src/modules/Elsa.Alterations.Core/Services/WorkflowInstanceFinder.cs index 457250b2c9..ba1f862b38 100644 --- a/src/modules/Elsa.Alterations.Core/Services/WorkflowInstanceFinder.cs +++ b/src/modules/Elsa.Alterations.Core/Services/WorkflowInstanceFinder.cs @@ -17,12 +17,16 @@ public async Task> FindAsync(AlterationWorkflowInstanceFilte var workflowInstanceFilter = new WorkflowInstanceFilter { Ids = filter.WorkflowInstanceIds?.ToList(), + DefinitionIds = filter.DefinitionIds, DefinitionVersionIds = filter.DefinitionVersionIds?.ToList(), CorrelationIds = filter.CorrelationIds?.ToList(), HasIncidents = filter.HasIncidents, IsSystem = filter.IsSystem, TimestampFilters = filter.TimestampFilters?.ToList(), - WorkflowStatus = WorkflowStatus.Running + WorkflowStatuses = filter.Statuses?.ToList(), + WorkflowSubStatuses = filter.SubStatuses?.ToList(), + Names = filter.Names?.ToList(), + SearchTerm = filter.SearchTerm, }; var activityExecutionFilters = filter.ActivityFilters?.Select(x => new ActivityExecutionRecordFilter { diff --git a/src/modules/Elsa.Alterations/Services/DefaultAlterationPlanScheduler.cs b/src/modules/Elsa.Alterations/Services/DefaultAlterationPlanScheduler.cs index 2109146916..0edd6f23ff 100644 --- a/src/modules/Elsa.Alterations/Services/DefaultAlterationPlanScheduler.cs +++ b/src/modules/Elsa.Alterations/Services/DefaultAlterationPlanScheduler.cs @@ -30,7 +30,6 @@ public DefaultAlterationPlanScheduler(IWorkflowDispatcher workflowDispatcher, II } /// - [RequiresUnreferencedCode("The type of the object to be deserialized is not known at compile time.")] public async Task SubmitAsync(AlterationPlanParams planParams, CancellationToken cancellationToken = default) { if(string.IsNullOrWhiteSpace(planParams.Id)) diff --git a/src/modules/Elsa.MassTransit/Services/MassTransitWorkflowDispatcher.cs b/src/modules/Elsa.MassTransit/Services/MassTransitWorkflowDispatcher.cs index edf665e581..caf5366108 100644 --- a/src/modules/Elsa.MassTransit/Services/MassTransitWorkflowDispatcher.cs +++ b/src/modules/Elsa.MassTransit/Services/MassTransitWorkflowDispatcher.cs @@ -36,7 +36,7 @@ public async Task DispatchAsync(DispatchWorkflowDefini var workflowGraph = await workflowDefinitionService.FindWorkflowGraphAsync(request.DefinitionId, request.VersionOptions, cancellationToken); if (workflowGraph == null) - throw new Exception($"Workflow definition with definition ID '{request.DefinitionId} and version {request.VersionOptions}' not found"); + throw new($"Workflow definition with definition ID '{request.DefinitionId} and version {request.VersionOptions}' not found"); var workflow = workflowGraph.Workflow; var createWorkflowInstanceRequest = new CreateWorkflowInstanceRequest @@ -178,7 +178,7 @@ private async Task DispatchBookmarksAsync(IEnumerable bookmarks, private async Task GetSendEndpointAsync(DispatchWorkflowOptions? options = default) { var endpointName = endpointChannelFormatter.FormatEndpointName(options?.Channel); - var sendEndpoint = await bus.GetSendEndpoint(new Uri($"queue:{endpointName}")); + var sendEndpoint = await bus.GetSendEndpoint(new($"queue:{endpointName}")); return sendEndpoint; } diff --git a/src/modules/Elsa.Workflows.Management/Filters/WorkflowInstanceFilter.cs b/src/modules/Elsa.Workflows.Management/Filters/WorkflowInstanceFilter.cs index e578468c5f..c87c63c52d 100644 --- a/src/modules/Elsa.Workflows.Management/Filters/WorkflowInstanceFilter.cs +++ b/src/modules/Elsa.Workflows.Management/Filters/WorkflowInstanceFilter.cs @@ -101,6 +101,11 @@ public class WorkflowInstanceFilter /// public ICollection? TimestampFilters { get; set; } + /// + /// Filter workflow instances by name. + /// + public List? Names { get; set; } + /// /// Applies the filter to the specified query. /// @@ -119,6 +124,7 @@ public IQueryable Apply(IQueryable query) if (filter.ParentWorkflowInstanceIds != null) query = query.Where(x => x.ParentWorkflowInstanceId != null && filter.ParentWorkflowInstanceIds.Contains(x.ParentWorkflowInstanceId)); if (!string.IsNullOrWhiteSpace(filter.CorrelationId)) query = query.Where(x => x.CorrelationId == filter.CorrelationId); if (filter.CorrelationIds != null) query = query.Where(x => filter.CorrelationIds.Contains(x.CorrelationId!)); + if (filter.Names != null) query = query.Where(x => filter.Names.Contains(x.Name!)); if (filter.WorkflowStatus != null) query = query.Where(x => x.Status == filter.WorkflowStatus); if (filter.WorkflowSubStatus != null) query = query.Where(x => x.SubStatus == filter.WorkflowSubStatus); if (filter.WorkflowStatuses != null) query = query.Where(x => filter.WorkflowStatuses.Contains(x.Status)); diff --git a/src/modules/Elsa.Workflows.Runtime/Extensions/WorkflowDispatcherExtensions.cs b/src/modules/Elsa.Workflows.Runtime/Extensions/WorkflowDispatcherExtensions.cs index 1bdc6b87b6..cf2dc9c34d 100644 --- a/src/modules/Elsa.Workflows.Runtime/Extensions/WorkflowDispatcherExtensions.cs +++ b/src/modules/Elsa.Workflows.Runtime/Extensions/WorkflowDispatcherExtensions.cs @@ -15,7 +15,7 @@ public static class WorkflowDispatcherExtensions /// public static Task DispatchAsync(this IWorkflowDispatcher workflowDispatcher, DispatchWorkflowDefinitionRequest request, CancellationToken cancellationToken = default) { - return workflowDispatcher.DispatchAsync(request, new DispatchWorkflowOptions(), cancellationToken); + return workflowDispatcher.DispatchAsync(request, new(), cancellationToken); } /// @@ -23,7 +23,7 @@ public static Task DispatchAsync(this IWorkflowDispatc /// public static Task DispatchAsync(this IWorkflowDispatcher workflowDispatcher, DispatchWorkflowInstanceRequest request, CancellationToken cancellationToken = default) { - return workflowDispatcher.DispatchAsync(request, new DispatchWorkflowOptions(), cancellationToken); + return workflowDispatcher.DispatchAsync(request, new(), cancellationToken); } /// @@ -31,7 +31,7 @@ public static Task DispatchAsync(this IWorkflowDispatc /// public static Task DispatchAsync(this IWorkflowDispatcher workflowDispatcher, DispatchTriggerWorkflowsRequest request, CancellationToken cancellationToken = default) { - return workflowDispatcher.DispatchAsync(request, new DispatchWorkflowOptions(), cancellationToken); + return workflowDispatcher.DispatchAsync(request, new(), cancellationToken); } /// @@ -39,6 +39,6 @@ public static Task DispatchAsync(this IWorkflowDispatc /// public static Task DispatchAsync(this IWorkflowDispatcher workflowDispatcher, DispatchResumeWorkflowsRequest request, CancellationToken cancellationToken = default) { - return workflowDispatcher.DispatchAsync(request, new DispatchWorkflowOptions(), cancellationToken); + return workflowDispatcher.DispatchAsync(request, new(), cancellationToken); } } \ No newline at end of file From 0e4a74bfbab0a10740337ec1e693f9492e133a8d Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Fri, 7 Feb 2025 23:10:22 +0100 Subject: [PATCH 3/8] Add `Cancel` alteration type and handler for workflow cancellation Introduced a new `Cancel` alteration type with its corresponding handler to allow workflow instance cancellations in alteration plans. Updated related services, serialization configurations, and activity metadata to support the new type. Improved JSON polymorphism handling to include the `Cancel` type. --- .../Helpers/RefitSettingsHelper.cs | 24 +++++++++++++++++++ .../Resources/Alterations/Models/Cancel.cs | 6 +++++ ...terationSerializationOptionConfigurator.cs | 3 +-- .../Activities/CompleteAlterationPlan.cs | 2 +- .../Activities/DispatchAlterationJobs.cs | 2 +- .../Activities/GenerateAlterationJobs.cs | 2 +- .../AlterationHandlers/CancelHandler.cs | 22 +++++++++++++++++ .../AlterationTypes/Cancel.cs | 10 ++++++++ .../Extensions/ServiceCollectionExtensions.cs | 1 + 9 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 src/clients/Elsa.Api.Client/Resources/Alterations/Models/Cancel.cs create mode 100644 src/modules/Elsa.Alterations/AlterationHandlers/CancelHandler.cs create mode 100644 src/modules/Elsa.Alterations/AlterationTypes/Cancel.cs diff --git a/src/clients/Elsa.Api.Client/Helpers/RefitSettingsHelper.cs b/src/clients/Elsa.Api.Client/Helpers/RefitSettingsHelper.cs index 8a87220a36..fafd238911 100644 --- a/src/clients/Elsa.Api.Client/Helpers/RefitSettingsHelper.cs +++ b/src/clients/Elsa.Api.Client/Helpers/RefitSettingsHelper.cs @@ -1,6 +1,9 @@ using System.Text.Json; using System.Text.Json.Serialization; +using System.Text.Json.Serialization.Metadata; using Elsa.Api.Client.Converters; +using Elsa.Api.Client.Resources.Alterations.Contracts; +using Elsa.Api.Client.Resources.Alterations.Models; using Refit; namespace Elsa.Api.Client; @@ -34,6 +37,27 @@ public static JsonSerializerOptions CreateJsonSerializerOptions(IServiceProvider options.Converters.Add(new VersionOptionsJsonConverter()); options.Converters.Add(new TypeJsonConverter()); + var alterationTypes = new[] { typeof(Cancel) }; + + options.TypeInfoResolver = new DefaultJsonTypeInfoResolver() + .WithAddedModifier(typeInfo => + { + if (typeInfo.Type != typeof(IAlteration)) + return; + + if (typeInfo.Kind != JsonTypeInfoKind.Object) + return; + + var polymorphismOptions = new JsonPolymorphismOptions { TypeDiscriminatorPropertyName = "type" }; + + foreach (var alterationType in alterationTypes.ToList()) + { + polymorphismOptions.DerivedTypes.Add(new(alterationType, alterationType.Name)); + } + + typeInfo.PolymorphismOptions = polymorphismOptions; + }); + configureJsonSerializerOptions?.Invoke(serviceProvider, options); return options; diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Models/Cancel.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/Cancel.cs new file mode 100644 index 0000000000..45b2c836de --- /dev/null +++ b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/Cancel.cs @@ -0,0 +1,6 @@ +namespace Elsa.Api.Client.Resources.Alterations.Models; + +/// +/// Cancels the workflow instances in an alteration plan. +/// +public class Cancel : AlterationBase; \ No newline at end of file diff --git a/src/modules/Elsa.Alterations.Core/Serialization/AlterationSerializationOptionConfigurator.cs b/src/modules/Elsa.Alterations.Core/Serialization/AlterationSerializationOptionConfigurator.cs index d5614b6d95..217331a5f8 100644 --- a/src/modules/Elsa.Alterations.Core/Serialization/AlterationSerializationOptionConfigurator.cs +++ b/src/modules/Elsa.Alterations.Core/Serialization/AlterationSerializationOptionConfigurator.cs @@ -1,4 +1,3 @@ -using System.Text.Json; using System.Text.Json.Serialization; using System.Text.Json.Serialization.Metadata; using Elsa.Alterations.Core.Contracts; @@ -35,7 +34,7 @@ public override IEnumerable> GetModifiers() foreach (var alterationType in alterationTypes.ToList()) { - polymorphismOptions.DerivedTypes.Add(new JsonDerivedType(alterationType, alterationType.Name)); + polymorphismOptions.DerivedTypes.Add(new(alterationType, alterationType.Name)); } typeInfo.PolymorphismOptions = polymorphismOptions; diff --git a/src/modules/Elsa.Alterations/Activities/CompleteAlterationPlan.cs b/src/modules/Elsa.Alterations/Activities/CompleteAlterationPlan.cs index b63cd97159..17ec70101d 100644 --- a/src/modules/Elsa.Alterations/Activities/CompleteAlterationPlan.cs +++ b/src/modules/Elsa.Alterations/Activities/CompleteAlterationPlan.cs @@ -13,7 +13,7 @@ namespace Elsa.Alterations.Activities; /// Marks an alteration plan as completed. /// [Browsable(false)] -[Activity("Elsa", "Alterations", "Dispatches jobs for the specified Alteration Plan", Kind = ActivityKind.Job)] +[Activity("Elsa", "Alterations", "Dispatches jobs for the specified Alteration Plan", Kind = ActivityKind.Task)] public class CompleteAlterationPlan : CodeActivity { /// diff --git a/src/modules/Elsa.Alterations/Activities/DispatchAlterationJobs.cs b/src/modules/Elsa.Alterations/Activities/DispatchAlterationJobs.cs index a8c2c6fe5e..a22a456520 100644 --- a/src/modules/Elsa.Alterations/Activities/DispatchAlterationJobs.cs +++ b/src/modules/Elsa.Alterations/Activities/DispatchAlterationJobs.cs @@ -15,7 +15,7 @@ namespace Elsa.Alterations.Activities; /// Submits an alteration plan for execution. /// [Browsable(false)] -[Activity("Elsa", "Alterations", "Dispatches jobs for the specified Alteration Plan", Kind = ActivityKind.Job)] +[Activity("Elsa", "Alterations", "Dispatches jobs for the specified Alteration Plan", Kind = ActivityKind.Task)] public class DispatchAlterationJobs : CodeActivity { /// diff --git a/src/modules/Elsa.Alterations/Activities/GenerateAlterationJobs.cs b/src/modules/Elsa.Alterations/Activities/GenerateAlterationJobs.cs index fd2357501f..03a68cca58 100644 --- a/src/modules/Elsa.Alterations/Activities/GenerateAlterationJobs.cs +++ b/src/modules/Elsa.Alterations/Activities/GenerateAlterationJobs.cs @@ -20,7 +20,7 @@ namespace Elsa.Alterations.Activities; /// Submits an alteration plan for execution. /// [Browsable(false)] -[Activity("Elsa", "Alterations", "Generates jobs for the specified Alteration Plan", Kind = ActivityKind.Job)] +[Activity("Elsa", "Alterations", "Generates jobs for the specified Alteration Plan", Kind = ActivityKind.Task)] public class GenerateAlterationJobs : CodeActivity { /// diff --git a/src/modules/Elsa.Alterations/AlterationHandlers/CancelHandler.cs b/src/modules/Elsa.Alterations/AlterationHandlers/CancelHandler.cs new file mode 100644 index 0000000000..38bc32404b --- /dev/null +++ b/src/modules/Elsa.Alterations/AlterationHandlers/CancelHandler.cs @@ -0,0 +1,22 @@ +using Elsa.Alterations.AlterationTypes; +using Elsa.Alterations.Core.Abstractions; +using Elsa.Alterations.Core.Contexts; +using JetBrains.Annotations; + +namespace Elsa.Alterations.AlterationHandlers; + +/// +/// Upgrades the version of the workflow instance. +/// +[UsedImplicitly] +public class CancelHandler : AlterationHandlerBase +{ + /// + protected override ValueTask HandleAsync(AlterationContext context, Cancel alteration) + { + context.WorkflowExecutionContext.Cancel(); + + context.Succeed(); + return ValueTask.CompletedTask; + } +} \ No newline at end of file diff --git a/src/modules/Elsa.Alterations/AlterationTypes/Cancel.cs b/src/modules/Elsa.Alterations/AlterationTypes/Cancel.cs new file mode 100644 index 0000000000..c0a5f7fded --- /dev/null +++ b/src/modules/Elsa.Alterations/AlterationTypes/Cancel.cs @@ -0,0 +1,10 @@ +using Elsa.Alterations.Core.Abstractions; +using JetBrains.Annotations; + +namespace Elsa.Alterations.AlterationTypes; + +/// +/// Cancels the workflow instances in an alteration plan. +/// +[UsedImplicitly] +public class Cancel : AlterationBase; \ No newline at end of file diff --git a/src/modules/Elsa.Alterations/Extensions/ServiceCollectionExtensions.cs b/src/modules/Elsa.Alterations/Extensions/ServiceCollectionExtensions.cs index 76a6818b8e..b930d28783 100644 --- a/src/modules/Elsa.Alterations/Extensions/ServiceCollectionExtensions.cs +++ b/src/modules/Elsa.Alterations/Extensions/ServiceCollectionExtensions.cs @@ -20,6 +20,7 @@ public static IServiceCollection AddAlterations(this IServiceCollection services services.AddAlteration(); services.AddAlteration(); services.AddAlteration(); + services.AddAlteration(); services.AddNotificationHandlersFrom(); return services; } From e719bd7c7dceaa026fbf8127dec84bf417b21dad Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Sat, 8 Feb 2025 09:45:50 +0100 Subject: [PATCH 4/8] Remove alteration models and interfaces; refactor to use JsonObject. This commit deletes all alteration-related models and the `IAlteration` interface in favor of using `JsonObject`. Adjustments were made to `AlterationPlan`, `AlterationPlanParams`, and `RunRequest` to replace `IAlteration` collections with `JsonObject`. Simplified the `RefitSettingsHelper` by eliminating polymorphism configuration for alterations. --- .../Helpers/RefitSettingsHelper.cs | 28 +------------------ .../Alterations/Contracts/IAlteration.cs | 6 ---- .../Alterations/Models/AlterationBase.cs | 8 ------ .../Alterations/Models/AlterationPlan.cs | 4 +-- .../Models/AlterationPlanParams.cs | 4 +-- .../Resources/Alterations/Models/Cancel.cs | 6 ---- .../Alterations/Models/CancelActivity.cs | 17 ----------- .../Resources/Alterations/Models/Migrate.cs | 12 -------- .../Alterations/Models/ModifyVariable.cs | 18 ------------ .../Alterations/Models/ScheduleActivity.cs | 17 ----------- .../Alterations/Responses/RunRequest.cs | 4 +-- 11 files changed, 7 insertions(+), 117 deletions(-) delete mode 100644 src/clients/Elsa.Api.Client/Resources/Alterations/Contracts/IAlteration.cs delete mode 100644 src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationBase.cs delete mode 100644 src/clients/Elsa.Api.Client/Resources/Alterations/Models/Cancel.cs delete mode 100644 src/clients/Elsa.Api.Client/Resources/Alterations/Models/CancelActivity.cs delete mode 100644 src/clients/Elsa.Api.Client/Resources/Alterations/Models/Migrate.cs delete mode 100644 src/clients/Elsa.Api.Client/Resources/Alterations/Models/ModifyVariable.cs delete mode 100644 src/clients/Elsa.Api.Client/Resources/Alterations/Models/ScheduleActivity.cs diff --git a/src/clients/Elsa.Api.Client/Helpers/RefitSettingsHelper.cs b/src/clients/Elsa.Api.Client/Helpers/RefitSettingsHelper.cs index fafd238911..b5e5de3c5c 100644 --- a/src/clients/Elsa.Api.Client/Helpers/RefitSettingsHelper.cs +++ b/src/clients/Elsa.Api.Client/Helpers/RefitSettingsHelper.cs @@ -1,9 +1,6 @@ using System.Text.Json; using System.Text.Json.Serialization; -using System.Text.Json.Serialization.Metadata; using Elsa.Api.Client.Converters; -using Elsa.Api.Client.Resources.Alterations.Contracts; -using Elsa.Api.Client.Resources.Alterations.Models; using Refit; namespace Elsa.Api.Client; @@ -36,30 +33,7 @@ public static JsonSerializerOptions CreateJsonSerializerOptions(IServiceProvider options.Converters.Add(new JsonStringEnumConverter()); options.Converters.Add(new VersionOptionsJsonConverter()); options.Converters.Add(new TypeJsonConverter()); - - var alterationTypes = new[] { typeof(Cancel) }; - - options.TypeInfoResolver = new DefaultJsonTypeInfoResolver() - .WithAddedModifier(typeInfo => - { - if (typeInfo.Type != typeof(IAlteration)) - return; - - if (typeInfo.Kind != JsonTypeInfoKind.Object) - return; - - var polymorphismOptions = new JsonPolymorphismOptions { TypeDiscriminatorPropertyName = "type" }; - - foreach (var alterationType in alterationTypes.ToList()) - { - polymorphismOptions.DerivedTypes.Add(new(alterationType, alterationType.Name)); - } - - typeInfo.PolymorphismOptions = polymorphismOptions; - }); - - configureJsonSerializerOptions?.Invoke(serviceProvider, options); - + return options; } } \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Contracts/IAlteration.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Contracts/IAlteration.cs deleted file mode 100644 index 0ce1f7a50b..0000000000 --- a/src/clients/Elsa.Api.Client/Resources/Alterations/Contracts/IAlteration.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Elsa.Api.Client.Resources.Alterations.Contracts; - -/// -/// Marker interface for all alteration classes -/// -public interface IAlteration; \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationBase.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationBase.cs deleted file mode 100644 index 18615eca90..0000000000 --- a/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationBase.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Elsa.Api.Client.Resources.Alterations.Contracts; - -namespace Elsa.Api.Client.Resources.Alterations.Models; - -/// -/// A base class for all IAlterations. -/// -public abstract class AlterationBase : IAlteration; \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationPlan.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationPlan.cs index 993858cf51..dd5843d5f0 100644 --- a/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationPlan.cs +++ b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationPlan.cs @@ -1,4 +1,4 @@ -using Elsa.Api.Client.Resources.Alterations.Contracts; +using System.Text.Json.Nodes; using Elsa.Api.Client.Resources.Alterations.Enums; using Elsa.Api.Client.Shared.Models; @@ -12,7 +12,7 @@ public class AlterationPlan : Entity /// /// The alterations to be applied. /// - public ICollection Alterations { get; set; } = new List(); + public ICollection Alterations { get; set; } = new List(); /// /// The IDs of the workflow instances that this plan applies to. diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationPlanParams.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationPlanParams.cs index f9fc5a1c1e..893aa89e67 100644 --- a/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationPlanParams.cs +++ b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationPlanParams.cs @@ -1,4 +1,4 @@ -using Elsa.Api.Client.Resources.Alterations.Contracts; +using System.Text.Json.Nodes; namespace Elsa.Api.Client.Resources.Alterations.Models; @@ -15,7 +15,7 @@ public class AlterationPlanParams /// /// The alterations to be applied. /// - public ICollection Alterations { get; set; } = new List(); + public ICollection Alterations { get; set; } = new List(); /// /// The IDs of the workflow instances that this plan applies to. diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Models/Cancel.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/Cancel.cs deleted file mode 100644 index 45b2c836de..0000000000 --- a/src/clients/Elsa.Api.Client/Resources/Alterations/Models/Cancel.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Elsa.Api.Client.Resources.Alterations.Models; - -/// -/// Cancels the workflow instances in an alteration plan. -/// -public class Cancel : AlterationBase; \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Models/CancelActivity.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/CancelActivity.cs deleted file mode 100644 index 2500e7d975..0000000000 --- a/src/clients/Elsa.Api.Client/Resources/Alterations/Models/CancelActivity.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace Elsa.Api.Client.Resources.Alterations.Models; - -/// -/// Cancels a workflow instance activity during an alteration -/// -public class CancelActivity : AlterationBase -{ - /// - /// The ID of the activity to be cancelled. If not specified, the activity instance ID will be used. - /// - public string? ActivityId { get; set; } - - /// - /// The ID of the activity instance to be cancelled. If specified, overrides . - /// - public string? ActivityInstanceId { get; set; } -} \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Models/Migrate.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/Migrate.cs deleted file mode 100644 index 1a4dc3b692..0000000000 --- a/src/clients/Elsa.Api.Client/Resources/Alterations/Models/Migrate.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Elsa.Api.Client.Resources.Alterations.Models; - -/// -/// Migrates a workflow instance to a newer version in an alteration. -/// -public class Migrate : AlterationBase -{ - /// - /// The target version to upgrade to. - /// - public int TargetVersion { get; set; } -} \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Models/ModifyVariable.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/ModifyVariable.cs deleted file mode 100644 index 60ab9f6bae..0000000000 --- a/src/clients/Elsa.Api.Client/Resources/Alterations/Models/ModifyVariable.cs +++ /dev/null @@ -1,18 +0,0 @@ -namespace Elsa.Api.Client.Resources.Alterations.Models; - -/// -/// Modifies a variable in a workflow instance alteration -/// -public class ModifyVariable : AlterationBase -{ - /// - /// The ID of the variable to modify. - /// - public string VariableId { get; set; } = default!; - - /// - /// The new value of the variable. - /// - public object? Value { get; set; } - -} \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Models/ScheduleActivity.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/ScheduleActivity.cs deleted file mode 100644 index 2b0f77f6d3..0000000000 --- a/src/clients/Elsa.Api.Client/Resources/Alterations/Models/ScheduleActivity.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace Elsa.Api.Client.Resources.Alterations.Models; - -/// -/// Schedules an activity for execution in an alteration. -/// -public class ScheduleActivity : AlterationBase -{ - /// - /// The ID of the next activity to be scheduled. If not specified, the ActivityInstanceId will be used. - /// - public string? ActivityId { get; set; } - - /// - /// The ID of the activity instance to be scheduled. If not specified, the ActivityId will be used. - /// - public string? ActivityInstanceId { get; set; } -} \ No newline at end of file diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Responses/RunRequest.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Responses/RunRequest.cs index fdaf341e8e..0d99957126 100644 --- a/src/clients/Elsa.Api.Client/Resources/Alterations/Responses/RunRequest.cs +++ b/src/clients/Elsa.Api.Client/Resources/Alterations/Responses/RunRequest.cs @@ -1,4 +1,4 @@ -using Elsa.Api.Client.Resources.Alterations.Contracts; +using System.Text.Json.Nodes; namespace Elsa.Api.Client.Resources.Alterations.Responses; @@ -10,7 +10,7 @@ public class RunRequest /// /// The alterations to be applied. /// - public ICollection Alterations { get; set; } = new List(); + public ICollection Alterations { get; set; } = new List(); /// /// The IDs of the workflow instances that this plan applies to. From 578a15832c8262056edb0af9fa8441728ce0ade2 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Sat, 8 Feb 2025 09:51:26 +0100 Subject: [PATCH 5/8] Update workflow cancellation logic Replaced status checks with a call to `CanTransitionTo` for determining if a workflow can transition to the "Cancelled" state. This improves code readability and maintains consistent transition validation logic. --- .../Contexts/WorkflowExecutionContext.Cancel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/Elsa.Workflows.Core/Contexts/WorkflowExecutionContext.Cancel.cs b/src/modules/Elsa.Workflows.Core/Contexts/WorkflowExecutionContext.Cancel.cs index 74a21f7f60..c4f7fe4f6a 100644 --- a/src/modules/Elsa.Workflows.Core/Contexts/WorkflowExecutionContext.Cancel.cs +++ b/src/modules/Elsa.Workflows.Core/Contexts/WorkflowExecutionContext.Cancel.cs @@ -24,7 +24,7 @@ private void CancelWorkflow() Bookmarks.Clear(); _completionCallbackEntries.Clear(); - if (Status != WorkflowStatus.Running && SubStatus != WorkflowSubStatus.Faulted) + if (!CanTransitionTo(WorkflowSubStatus.Cancelled)) return; AddExecutionLogEntry("Workflow cancelled"); From c0bf4b7f84365cf11191939ba8566fe67ca4a8c0 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Sat, 8 Feb 2025 10:07:07 +0100 Subject: [PATCH 6/8] Add support for selecting all records with empty filters Introduced a new property, `EmptyFilterSelectsAll`, to handle cases where empty filters should match all records. Updated logic in `WorkflowInstanceFinder` to respect this property, ensuring consistent behavior across the system. Removed redundant comments in the dry-run endpoint for cleaner code. --- .../Alterations/Models/AlterationWorkflowInstanceFilter.cs | 5 +++++ .../Models/AlterationWorkflowInstanceFilter.cs | 5 +++++ .../Elsa.Alterations.Core/Services/WorkflowInstanceFinder.cs | 3 ++- .../Endpoints/Alterations/DryRun/Endpoint.cs | 2 -- 4 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationWorkflowInstanceFilter.cs b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationWorkflowInstanceFilter.cs index ff2e584f78..e741c240e6 100644 --- a/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationWorkflowInstanceFilter.cs +++ b/src/clients/Elsa.Api.Client/Resources/Alterations/Models/AlterationWorkflowInstanceFilter.cs @@ -8,6 +8,11 @@ namespace Elsa.Api.Client.Resources.Alterations.Models; /// public class AlterationWorkflowInstanceFilter { + /// + /// If the filter is empty, all records are matched. + /// + public bool EmptyFilterSelectsAll { get; set; } + /// /// The IDs of the workflow instances that this plan applies to. /// diff --git a/src/modules/Elsa.Alterations.Core/Models/AlterationWorkflowInstanceFilter.cs b/src/modules/Elsa.Alterations.Core/Models/AlterationWorkflowInstanceFilter.cs index 12d9d863cf..51f2cd680d 100644 --- a/src/modules/Elsa.Alterations.Core/Models/AlterationWorkflowInstanceFilter.cs +++ b/src/modules/Elsa.Alterations.Core/Models/AlterationWorkflowInstanceFilter.cs @@ -10,6 +10,11 @@ namespace Elsa.Alterations.Core.Models; [UsedImplicitly] public class AlterationWorkflowInstanceFilter { + /// + /// If the filter is empty, all records are matched. + /// + public bool EmptyFilterSelectsAll { get; set; } + /// /// The IDs of the workflow instances that this plan applies to. /// diff --git a/src/modules/Elsa.Alterations.Core/Services/WorkflowInstanceFinder.cs b/src/modules/Elsa.Alterations.Core/Services/WorkflowInstanceFinder.cs index ba1f862b38..979ec99b64 100644 --- a/src/modules/Elsa.Alterations.Core/Services/WorkflowInstanceFinder.cs +++ b/src/modules/Elsa.Alterations.Core/Services/WorkflowInstanceFinder.cs @@ -37,9 +37,10 @@ public async Task> FindAsync(AlterationWorkflowInstanceFilte Status = x.Status, }).ToList(); + var emptyFilterSelectsAll = filter.EmptyFilterSelectsAll; var workflowInstanceFilterIsEmpty = WorkflowFilterIsEmpty(workflowInstanceFilter); - var workflowInstanceIds = workflowInstanceFilterIsEmpty + var workflowInstanceIds = workflowInstanceFilterIsEmpty && !emptyFilterSelectsAll ? Enumerable.Empty().ToHashSet() : (await workflowInstanceStore.FindManyIdsAsync(workflowInstanceFilter, cancellationToken)).ToHashSet(); diff --git a/src/modules/Elsa.Alterations/Endpoints/Alterations/DryRun/Endpoint.cs b/src/modules/Elsa.Alterations/Endpoints/Alterations/DryRun/Endpoint.cs index cbf0d5471d..f401755221 100644 --- a/src/modules/Elsa.Alterations/Endpoints/Alterations/DryRun/Endpoint.cs +++ b/src/modules/Elsa.Alterations/Endpoints/Alterations/DryRun/Endpoint.cs @@ -22,8 +22,6 @@ public override void Configure() public override async Task HandleAsync(AlterationWorkflowInstanceFilter filter, CancellationToken cancellationToken) { var workflowInstanceIds = await workflowInstanceFinder.FindAsync(filter, cancellationToken); - - // Write response. var response = new Response(workflowInstanceIds.ToList()); await SendOkAsync(response, cancellationToken); } From bde7c0dbfedbe4f7f8a2a4f7c8c6eba88ba4147e Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Sat, 8 Feb 2025 10:10:17 +0100 Subject: [PATCH 7/8] Restore support for custom JSON serializer configuration Allow external configuration of JSON serializer settings by introducing an optional delegate. This enhances flexibility and enables customization based on specific use cases. --- src/clients/Elsa.Api.Client/Helpers/RefitSettingsHelper.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/clients/Elsa.Api.Client/Helpers/RefitSettingsHelper.cs b/src/clients/Elsa.Api.Client/Helpers/RefitSettingsHelper.cs index b5e5de3c5c..4a36d759ab 100644 --- a/src/clients/Elsa.Api.Client/Helpers/RefitSettingsHelper.cs +++ b/src/clients/Elsa.Api.Client/Helpers/RefitSettingsHelper.cs @@ -34,6 +34,8 @@ public static JsonSerializerOptions CreateJsonSerializerOptions(IServiceProvider options.Converters.Add(new VersionOptionsJsonConverter()); options.Converters.Add(new TypeJsonConverter()); + configureJsonSerializerOptions?.Invoke(serviceProvider, options); + return options; } } \ No newline at end of file From bec0e559b221e2cd54582071877ec540b94d9d92 Mon Sep 17 00:00:00 2001 From: Sipke Schoorstra Date: Sat, 8 Feb 2025 10:10:40 +0100 Subject: [PATCH 8/8] Refactor RefitSettingsHelper for improved readability Reformatted object initialization in CreateRefitSettings to improve structure and code clarity. Also cleaned up unnecessary whitespace for consistency and better readability. --- .../Elsa.Api.Client/Helpers/RefitSettingsHelper.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/clients/Elsa.Api.Client/Helpers/RefitSettingsHelper.cs b/src/clients/Elsa.Api.Client/Helpers/RefitSettingsHelper.cs index 4a36d759ab..446b012ec3 100644 --- a/src/clients/Elsa.Api.Client/Helpers/RefitSettingsHelper.cs +++ b/src/clients/Elsa.Api.Client/Helpers/RefitSettingsHelper.cs @@ -15,7 +15,10 @@ public static class RefitSettingsHelper /// public static RefitSettings CreateRefitSettings(IServiceProvider serviceProvider, Action? configureJsonSerializerOptions = null) { - var settings = new RefitSettings { ContentSerializer = new SystemTextJsonContentSerializer(CreateJsonSerializerOptions(serviceProvider, configureJsonSerializerOptions)) }; + var settings = new RefitSettings + { + ContentSerializer = new SystemTextJsonContentSerializer(CreateJsonSerializerOptions(serviceProvider, configureJsonSerializerOptions)) + }; return settings; } @@ -33,9 +36,9 @@ public static JsonSerializerOptions CreateJsonSerializerOptions(IServiceProvider options.Converters.Add(new JsonStringEnumConverter()); options.Converters.Add(new VersionOptionsJsonConverter()); options.Converters.Add(new TypeJsonConverter()); - + configureJsonSerializerOptions?.Invoke(serviceProvider, options); - + return options; } } \ No newline at end of file