Add project files.
This commit is contained in:
@@ -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);
|
||||
Reference in New Issue
Block a user