Add project files.

This commit is contained in:
2025-08-18 17:11:43 +03:30
parent 807dc263be
commit e5eb10d604
3943 changed files with 223719 additions and 0 deletions
@@ -0,0 +1,28 @@
using Elsa.Abstractions;
using Elsa.Alterations.Core.Contracts;
using Elsa.Alterations.Core.Models;
using JetBrains.Annotations;
namespace Elsa.Alterations.Endpoints.Alterations.DryRun;
/// <summary>
/// Determines which workflow instances a "Submit" request would target without actually running an alteration.
/// </summary>
[PublicAPI]
public class DryRun(IWorkflowInstanceFinder workflowInstanceFinder) : ElsaEndpoint<AlterationWorkflowInstanceFilter, Response>
{
/// <inheritdoc />
public override void Configure()
{
Post("/alterations/dry-run");
ConfigurePermissions("run:alterations");
}
/// <inheritdoc />
public override async Task HandleAsync(AlterationWorkflowInstanceFilter filter, CancellationToken cancellationToken)
{
var workflowInstanceIds = await workflowInstanceFinder.FindAsync(filter, cancellationToken);
var response = new Response(workflowInstanceIds.ToList());
await SendOkAsync(response, cancellationToken);
}
}
@@ -0,0 +1,6 @@
namespace Elsa.Alterations.Endpoints.Alterations.DryRun;
/// <summary>
/// The response from the <see cref="DryRun"/> endpoint.
/// </summary>
public record Response(ICollection<string> WorkflowInstanceIds);
@@ -0,0 +1,52 @@
using Elsa.Abstractions;
using Elsa.Alterations.Core.Contracts;
using Elsa.Alterations.Core.Filters;
using JetBrains.Annotations;
namespace Elsa.Alterations.Endpoints.Alterations.Get;
/// <summary>
/// Gets an alteration plan and its associated jobs.
/// </summary>
[PublicAPI]
public class Get : ElsaEndpointWithoutRequest<Response>
{
private readonly IAlterationPlanStore _alterationPlanStore;
private readonly IAlterationJobStore _alterationJobStore;
/// <inheritdoc />
public Get(IAlterationPlanStore alterationPlanStore, IAlterationJobStore alterationJobStore)
{
_alterationPlanStore = alterationPlanStore;
_alterationJobStore = alterationJobStore;
}
/// <inheritdoc />
public override void Configure()
{
Get("/alterations/{id}");
ConfigurePermissions("read:alterations");
}
/// <inheritdoc />
public override async Task HandleAsync(CancellationToken cancellationToken)
{
var planId = Route<string>("id");
// Load the plan.
var plan = await _alterationPlanStore.FindAsync(new AlterationPlanFilter { Id = planId }, cancellationToken);
if (plan == null)
{
await SendNotFoundAsync(cancellationToken);
return;
}
// Load the jobs.
var jobs = (await _alterationJobStore.FindManyAsync(new AlterationJobFilter { PlanId = planId }, cancellationToken)).ToList();
// Write response.
var response = new Response(plan, jobs);
await SendOkAsync(response, cancellationToken);
}
}
@@ -0,0 +1,10 @@
using Elsa.Alterations.Core.Entities;
namespace Elsa.Alterations.Endpoints.Alterations.Get;
/// <summary>
/// Represents a response to a request to get an alteration plan.
/// </summary>
/// <param name="Plan">The alteration plan.</param>
/// <param name="Jobs">The jobs created for the plan.</param>
public record Response(AlterationPlan Plan, ICollection<AlterationJob> Jobs);
@@ -0,0 +1,43 @@
using Elsa.Abstractions;
using Elsa.Alterations.Core.Contracts;
using JetBrains.Annotations;
namespace Elsa.Alterations.Endpoints.Alterations.Run;
/// <summary>
/// Executes an alteration plan by targeting workflow instances by ID.
/// </summary>
[PublicAPI]
public class Run : ElsaEndpoint<Request, Response>
{
private readonly IAlterationRunner _alterationRunner;
private readonly IAlteredWorkflowDispatcher _workflowDispatcher;
/// <inheritdoc />
public Run(IAlterationRunner alterationRunner, IAlteredWorkflowDispatcher workflowDispatcher)
{
_alterationRunner = alterationRunner;
_workflowDispatcher = workflowDispatcher;
}
/// <inheritdoc />
public override void Configure()
{
Post("/alterations/run");
ConfigurePermissions("run:alterations");
}
/// <inheritdoc />
public override async Task HandleAsync(Request request, CancellationToken cancellationToken)
{
// Run the alterations.
var results = await _alterationRunner.RunAsync(request.WorkflowInstanceIds, request.Alterations, cancellationToken);
// Schedule each successfully updated workflow containing scheduled work.
await _workflowDispatcher.DispatchAsync(results, cancellationToken);
// Write response.
var response = new Response(results);
await SendOkAsync(response, cancellationToken);
}
}
@@ -0,0 +1,20 @@
using Elsa.Alterations.Core.Contracts;
// ReSharper disable CollectionNeverUpdated.Global
namespace Elsa.Alterations.Endpoints.Alterations.Run;
/// <summary>
/// A plan that contains a list of alterations to be applied to a set of workflow instances.
/// </summary>
public class Request
{
/// <summary>
/// The alterations to be applied.
/// </summary>
public ICollection<IAlteration> Alterations { get; set; } = new List<IAlteration>();
/// <summary>
/// The IDs of the workflow instances that this plan applies to.
/// </summary>
public ICollection<string> WorkflowInstanceIds { get; set; } = new List<string>();
}
@@ -0,0 +1,8 @@
using Elsa.Alterations.Core.Results;
namespace Elsa.Alterations.Endpoints.Alterations.Run;
/// <summary>
/// The response from the <see cref="Run"/> endpoint.
/// </summary>
public record Response(ICollection<RunAlterationsResult> Results);
@@ -0,0 +1,45 @@
using Elsa.Abstractions;
using Elsa.Alterations.Core.Contracts;
using Elsa.Alterations.Core.Models;
using Elsa.Common;
using Elsa.Workflows;
using JetBrains.Annotations;
namespace Elsa.Alterations.Endpoints.Alterations.Submit;
/// <summary>
/// Submits an alteration plan to be executed targeting workflow instances by a filter.
/// </summary>
[PublicAPI]
public class Submit : ElsaEndpoint<AlterationPlanParams, Response>
{
private readonly IAlterationPlanScheduler _alterationPlanScheduler;
private readonly IIdentityGenerator _identityGenerator;
private readonly ISystemClock _systemClock;
/// <inheritdoc />
public Submit(IAlterationPlanScheduler alterationPlanScheduler, IIdentityGenerator identityGenerator, ISystemClock systemClock)
{
_alterationPlanScheduler = alterationPlanScheduler;
_identityGenerator = identityGenerator;
_systemClock = systemClock;
}
/// <inheritdoc />
public override void Configure()
{
Post("/alterations/submit");
ConfigurePermissions("run:alterations");
}
/// <inheritdoc />
public override async Task HandleAsync(AlterationPlanParams planParams, CancellationToken cancellationToken)
{
// Submit the plan.
var planId = await _alterationPlanScheduler.SubmitAsync(planParams, cancellationToken);
// Write response.
var response = new Response(planId);
await SendOkAsync(response, cancellationToken);
}
}
@@ -0,0 +1,6 @@
namespace Elsa.Alterations.Endpoints.Alterations.Submit;
/// <summary>
/// The response from the <see cref="Execute"/> endpoint.
/// </summary>
public record Response(string PlanId);
@@ -0,0 +1,77 @@
using Elsa.Abstractions;
using Elsa.Alterations.AlterationTypes;
using Elsa.Alterations.Core.Contracts;
using Elsa.Alterations.Core.Results;
using Elsa.Workflows.Management;
using Elsa.Workflows.Management.Entities;
using Elsa.Workflows.Management.Filters;
using Elsa.Workflows.Runtime;
using Elsa.Workflows.Runtime.Contracts;
using Elsa.Workflows.Runtime.Requests;
using JetBrains.Annotations;
namespace Elsa.Alterations.Endpoints.Workflows.Retry;
/// <summary>
/// Retries the specified workflow instances.
/// </summary>
[PublicAPI]
public class Retry : ElsaEndpoint<Request, Response>
{
private readonly IAlterationRunner _alterationRunner;
private readonly IWorkflowDispatcher _workflowDispatcher;
private readonly IWorkflowInstanceStore _workflowInstanceStore;
/// <inheritdoc />
public Retry(IAlterationRunner alterationRunner, IWorkflowDispatcher workflowDispatcher, IWorkflowInstanceStore workflowInstanceStore)
{
_alterationRunner = alterationRunner;
_workflowDispatcher = workflowDispatcher;
_workflowInstanceStore = workflowInstanceStore;
}
/// <inheritdoc />
public override void Configure()
{
Routes("/alterations/workflows/retry");
Verbs(FastEndpoints.Http.GET, FastEndpoints.Http.POST);
ConfigurePermissions("run:alterations");
}
/// <inheritdoc />
public override async Task HandleAsync(Request request, CancellationToken cancellationToken)
{
var allResults = new List<RunAlterationsResult>();
// Load each workflow instance.
var workflowInstances = (await _workflowInstanceStore.FindManyAsync(new WorkflowInstanceFilter { Ids = request.WorkflowInstanceIds }, cancellationToken)).ToList();
foreach (var workflowInstance in workflowInstances)
{
// Setup an alteration plan.
var activityIds = GetActivityIds(request, workflowInstance).ToList();
var alterations = activityIds.Select(activityId => new ScheduleActivity { ActivityId = activityId }).Cast<IAlteration>().ToList();
// Run the plan.
var results = await _alterationRunner.RunAsync(request.WorkflowInstanceIds, alterations, cancellationToken);
allResults.AddRange(results);
// Schedule updated workflow.
await _workflowDispatcher.DispatchAsync(new DispatchWorkflowInstanceRequest(workflowInstance.Id), cancellationToken: cancellationToken);
}
// Write response.
var response = new Response(allResults);
await SendOkAsync(response, cancellationToken);
}
private IEnumerable<string> GetActivityIds(Request request, WorkflowInstance workflowInstance)
{
// If activity IDs are explicitly specified, use them.
if (request.ActivityIds?.Any() == true)
return request.ActivityIds;
// Otherwise, select IDs of all faulted activities.
return workflowInstance.WorkflowState.Incidents.Select(x => x.ActivityId).Distinct().ToList();
}
}
@@ -0,0 +1,17 @@
namespace Elsa.Alterations.Endpoints.Workflows.Retry;
/// <summary>
/// A request to retry one or more faulted workflow instances.
/// </summary>
public class Request
{
/// <summary>
/// The IDs of the workflow instances that have incidents to be retried.
/// </summary>
public ICollection<string> WorkflowInstanceIds { get; set; } = new List<string>();
/// <summary>
/// An optional list of explicitly specified activity IDs to retry. If omitted, all faulted activities will be retried.
/// </summary>
public ICollection<string>? ActivityIds { get; set; }
}
@@ -0,0 +1,8 @@
using Elsa.Alterations.Core.Results;
namespace Elsa.Alterations.Endpoints.Workflows.Retry;
/// <summary>
/// The response from the <see cref="Retry"/> endpoint.
/// </summary>
public record Response(ICollection<RunAlterationsResult> Results);