Skip to content

Commit

Permalink
[feat] add workflow instance & definition additional operations
Browse files Browse the repository at this point in the history
  • Loading branch information
jxnkwlp committed Apr 23, 2022
1 parent 55a3eef commit 30b53b8
Show file tree
Hide file tree
Showing 20 changed files with 528 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
using Volo.Abp.Caching.StackExchangeRedis;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore.SqlServer;
using Volo.Abp.Json;
using Volo.Abp.Json.SystemTextJson;
using Volo.Abp.Json.SystemTextJson.JsonConverters;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.MultiTenancy;
Expand Down Expand Up @@ -262,16 +265,25 @@ public override void ConfigureServices(ServiceConfigurationContext context)
options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver() { NamingStrategy = new CamelCaseNamingStrategy(false, true) };
});

//PostConfigure<AbpSystemTextJsonSerializerOptions>(options =>
//{
// options.JsonSerializerOptions.Converters.RemoveAll(x => x.GetType() == typeof(AbpStringToEnumFactory));
//});

//PostConfigure<AbpJsonOptions>(options =>
//{
//});

//PostConfigure<JsonOptions>(options =>
//{
// options.JsonSerializerOptions.Converters.RemoveAll(x => x.GetType() == typeof(AbpStringToEnumFactory));
//});

Configure<AbpAntiForgeryOptions>(options =>
{
options.AutoValidate = false;
});

context.Services.AddSpaStaticFiles(options =>
{
options.RootPath = "wwwroot/dist";
});

}

public override void OnApplicationInitialization(ApplicationInitializationContext context)
Expand All @@ -297,7 +309,7 @@ public override void OnApplicationInitialization(ApplicationInitializationContex
// app.UseHttpsRedirection();
app.UseCorrelationId();
app.UseStaticFiles();
app.UseSpaStaticFiles();
//app.UseSpaStaticFiles();

app.UseRouting();
app.UseCors();
Expand All @@ -311,7 +323,7 @@ public override void OnApplicationInitialization(ApplicationInitializationContex
}

app.UseHangfireDashboard();

app.UseAbpRequestLocalization();
app.UseAuthorization();
app.UseSwagger();
Expand Down Expand Up @@ -341,9 +353,9 @@ public override void OnApplicationInitialization(ApplicationInitializationContex
return next();
});

#if !DEBUG
app.UseSpa(c => { });
#endif
//#if !DEBUG
// app.UseSpa(c => { });
//#endif
}

public class SwaggerEnumDescriptions : ISchemaFilter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
<!--<PackageReference Include="Elsa.Activities.Temporal.Quartz" Version="2.5.0" />-->
<PackageReference Include="Elsa.Activities.Temporal.Hangfire" Version="2.5.0" />
<PackageReference Include="Elsa.Activities.Entity" Version="2.5.0" />
<!--<PackageReference Include="Elsa.Activities.Sql" Version="2.5.0" />-->
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,8 @@ public interface IWorkflowDefinitionAppService : ICrudAppService<WorkflowDefinit

Task UnPublishAsync(Guid id);
Task PublishAsync(Guid id);

Task ExecuteAsync(Guid id, WorkflowDefinitionExecuteRequestDto input);
Task<WorkflowDefinitionDispatchResultDto> DispatchAsync(Guid id, WorkflowDefinitionDispatchRequestDto input);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System;
using System.ComponentModel.DataAnnotations;

namespace Passingwind.Abp.ElsaModule.WorkflowDefinitions
{
public class WorkflowDefinitionDispatchRequestDto
{
public Guid? ActivityId { get; set; }
[MaxLength(36)]
public string CorrelationId { get; set; }
[MaxLength(36)]
public string ContextId { get; set; }
public object Input { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using System;

namespace Passingwind.Abp.ElsaModule.WorkflowDefinitions
{
public class WorkflowDefinitionDispatchResultDto
{
public Guid WorkflowInstanceId { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System;
using System.ComponentModel.DataAnnotations;

namespace Passingwind.Abp.ElsaModule.WorkflowDefinitions
{
public class WorkflowDefinitionExecuteRequestDto
{
public Guid? ActivityId { get; set; }
[MaxLength(36)]
public string CorrelationId { get; set; }
[MaxLength(36)]
public string ContextId { get; set; }
public object Input { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,10 @@ public interface IWorkflowInstanceAppService : IApplicationService
Task<WorkflowInstanceDto> GetAsync(Guid id);
Task<PagedResultDto<WorkflowInstanceBasicDto>> GetListAsync(WorkflowInstanceListRequestDto input);
Task<ListResultDto<WorkflowExecutionLogDto>> GetExecutionLogsAsync(Guid id);

Task CancelAsync(Guid id);
Task RetryAsync(Guid id, WorkflowInstanceRetryRequestDto input);
Task DispatchAsync(Guid id, WorkflowInstanceDispatchRequestDto input);
Task ExecuteAsync(Guid id, WorkflowInstanceExecuteRequestDto input);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System;
using Elsa.Models;

namespace Passingwind.Abp.ElsaModule.WorkflowInstances
{
public class WorkflowInstanceDispatchRequestDto
{
public Guid? ActivityId { get; set; }
public WorkflowInput Input { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System;
using Elsa.Models;

namespace Passingwind.Abp.ElsaModule.WorkflowInstances
{
public class WorkflowInstanceExecuteRequestDto
{
public Guid? ActivityId { get; set; }
public WorkflowInput Input { get; set; }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Passingwind.Abp.ElsaModule.WorkflowInstances
{
public class WorkflowInstanceRetryRequestDto
{
public bool RunImmediately { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Elsa.Models;
using Elsa.Services;
using Passingwind.Abp.ElsaModule.Workflow;
using Passingwind.Abp.ElsaModule.WorkflowDefinitions;
using Volo.Abp;
Expand All @@ -15,12 +17,14 @@ public class WorkflowDefinitionAppService : ElsaModuleAppService, IWorkflowDefin
private readonly IWorkflowDefinitionRepository _workflowDefinitionRepository;
private readonly IWorkflowDefinitionVersionRepository _workflowDefinitionVersionRepository;
private readonly WorkflowDefinitionManager _workflowDefinitionManager;
private readonly IWorkflowLaunchpad _workflowLaunchpad;

public WorkflowDefinitionAppService(IWorkflowDefinitionRepository workflowDefinitionRepository, IWorkflowDefinitionVersionRepository workflowDefinitionVersionRepository, WorkflowDefinitionManager workflowDefinitionManager)
public WorkflowDefinitionAppService(IWorkflowDefinitionRepository workflowDefinitionRepository, IWorkflowDefinitionVersionRepository workflowDefinitionVersionRepository, WorkflowDefinitionManager workflowDefinitionManager, IWorkflowLaunchpad workflowLaunchpad)
{
_workflowDefinitionRepository = workflowDefinitionRepository;
_workflowDefinitionVersionRepository = workflowDefinitionVersionRepository;
_workflowDefinitionManager = workflowDefinitionManager;
_workflowLaunchpad = workflowLaunchpad;
}

public virtual async Task<WorkflowDefinitionVersionDto> CreateAsync(WorkflowDefinitionVersionCreateOrUpdateDto input)
Expand Down Expand Up @@ -206,5 +210,37 @@ public virtual async Task PublishAsync(Guid id)
}
}

public async Task<WorkflowDefinitionDispatchResultDto> DispatchAsync(Guid id, WorkflowDefinitionDispatchRequestDto input)
{
var entity = await _workflowDefinitionVersionRepository.GetLatestAsync(id);

var tenantId = CurrentTenant.Id?.ToString();

var startableWorkflow = await _workflowLaunchpad.FindStartableWorkflowAsync(id.ToString(), input.ActivityId?.ToString(), input.CorrelationId, input.ContextId, tenantId);

if (startableWorkflow == null)
throw new UserFriendlyException("The workflow is not found.");

var result = await _workflowLaunchpad.DispatchStartableWorkflowAsync(startableWorkflow, new WorkflowInput(input.Input));

return new WorkflowDefinitionDispatchResultDto
{
WorkflowInstanceId = Guid.Parse(result.WorkflowInstanceId),
};
}

public async Task ExecuteAsync(Guid id, WorkflowDefinitionExecuteRequestDto input)
{
var entity = await _workflowDefinitionVersionRepository.GetLatestAsync(id);

var tenantId = CurrentTenant.Id?.ToString();

var startableWorkflow = await _workflowLaunchpad.FindStartableWorkflowAsync(id.ToString(), input.ActivityId?.ToString(), input.CorrelationId, input.ContextId, tenantId);

if (startableWorkflow == null)
throw new UserFriendlyException("The workflow is not found.");

var result = await _workflowLaunchpad.ExecuteStartableWorkflowAsync(startableWorkflow, new WorkflowInput(input.Input));
}
}
}
Original file line number Diff line number Diff line change
@@ -1,29 +1,92 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Elsa.Services;
using Passingwind.Abp.ElsaModule.Stores;
using Passingwind.Abp.ElsaModule.WorkflowInstances;
using Volo.Abp;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Json;

namespace Passingwind.Abp.ElsaModule.Common
{
public class WorkflowInstanceAppService : ElsaModuleAppService, IWorkflowInstanceAppService
{
private readonly IJsonSerializer _jsonSerializer;
private readonly IWorkflowInstanceRepository _workflowInstanceRepository;
private readonly IWorkflowExecutionLogRepository _workflowExecutionLogRepository;
private readonly IJsonSerializer _jsonSerializer;
private readonly IStoreMapper _storeMapper;
private readonly IWorkflowInstanceCanceller _workflowInstanceCanceller;
private readonly IWorkflowReviver _workflowReviver;
private readonly IWorkflowLaunchpad _workflowLaunchpad;

public WorkflowInstanceAppService(IWorkflowInstanceRepository workflowInstanceRepository, IWorkflowExecutionLogRepository workflowExecutionLogRepository, IJsonSerializer jsonSerializer)
public WorkflowInstanceAppService(IJsonSerializer jsonSerializer, IWorkflowInstanceRepository workflowInstanceRepository, IWorkflowExecutionLogRepository workflowExecutionLogRepository, IStoreMapper storeMapper, IWorkflowInstanceCanceller workflowInstanceCanceller, IWorkflowReviver workflowReviver, IWorkflowLaunchpad workflowLaunchpad)
{
_jsonSerializer = jsonSerializer;
_workflowInstanceRepository = workflowInstanceRepository;
_workflowExecutionLogRepository = workflowExecutionLogRepository;
_jsonSerializer = jsonSerializer;
_storeMapper = storeMapper;
_workflowInstanceCanceller = workflowInstanceCanceller;
_workflowReviver = workflowReviver;
_workflowLaunchpad = workflowLaunchpad;
}

public async Task<WorkflowInstanceDto> GetAsync(Guid id)
public async Task CancelAsync(Guid id)
{
var entity = await _workflowInstanceRepository.GetAsync(id);

if (entity.WorkflowStatus == Elsa.Models.WorkflowStatus.Idle || entity.WorkflowStatus == Elsa.Models.WorkflowStatus.Running || entity.WorkflowStatus == Elsa.Models.WorkflowStatus.Suspended)
{
var result = await _workflowInstanceCanceller.CancelAsync(id.ToString());

if (result.Status == CancelWorkflowInstanceResultStatus.InvalidStatus)
{
throw new UserFriendlyException($"Cannot cancel a workflow instance with status {result.WorkflowInstance!.WorkflowStatus}");
}
}
else
throw new UserFriendlyException($"Cannot cancel a workflow instance with status {entity.WorkflowStatus}");
}

public async Task RetryAsync(Guid id, WorkflowInstanceRetryRequestDto input)
{
var entity = await _workflowInstanceRepository.GetAsync(id);

var instance = _storeMapper.MapToModel(entity);

if (input.RunImmediately == false)
{
var workflowInstance = await _workflowReviver.ReviveAndQueueAsync(instance);
}
else
{
var result = await _workflowReviver.ReviveAndRunAsync(instance);

if (result.WorkflowInstance.WorkflowStatus == Elsa.Models.WorkflowStatus.Faulted)
{
throw new UserFriendlyException($"Workflow instance {result.WorkflowInstance.Id} has faulted");
}
}
}

public async Task DispatchAsync(Guid id, WorkflowInstanceDispatchRequestDto input)
{
var entity = await _workflowInstanceRepository.GetAsync(id);
// var instance = _storeMapper.MapToModel(entity);

await _workflowLaunchpad.DispatchPendingWorkflowAsync(id.ToString(), input.ActivityId?.ToString(), input.Input);
}

public async Task ExecuteAsync(Guid id, WorkflowInstanceExecuteRequestDto input)
{
var entity = await _workflowInstanceRepository.GetAsync(id);

await _workflowLaunchpad.ExecutePendingWorkflowAsync(id.ToString(), input.ActivityId?.ToString(), input.Input);
}

public async Task<WorkflowInstanceDto> GetAsync(Guid id)
{
var entity = await _workflowInstanceRepository.GetAsync(id);
return ObjectMapper.Map<WorkflowInstance, WorkflowInstanceDto>(entity);
}

Expand All @@ -41,5 +104,7 @@ public async Task<PagedResultDto<WorkflowInstanceBasicDto>> GetListAsync(Workflo

return new PagedResultDto<WorkflowInstanceBasicDto>(count, ObjectMapper.Map<List<WorkflowInstance>, List<WorkflowInstanceBasicDto>>(list));
}


}
}
Original file line number Diff line number Diff line change
Expand Up @@ -88,5 +88,17 @@ public Task PublishAsync(Guid id)
{
return _service.PublishAsync(id);
}

[HttpPost("{id}/execute")]
public Task ExecuteAsync(Guid id, WorkflowDefinitionExecuteRequestDto input)
{
return _service.ExecuteAsync(id, input);
}

[HttpPost("{id}/dispatch")]
public Task<WorkflowDefinitionDispatchResultDto> DispatchAsync(Guid id, WorkflowDefinitionDispatchRequestDto input)
{
return _service.DispatchAsync(id, input);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,24 @@ public WorkflowInstanceController(IWorkflowInstanceAppService service)
_service = service;
}

[HttpPost("{id}/cancel")]
public Task CancelAsync(Guid id)
{
return _service.CancelAsync(id);
}

[HttpPost("{id}/dispatch")]
public Task DispatchAsync(Guid id, WorkflowInstanceDispatchRequestDto input)
{
return _service.DispatchAsync(id, input);
}

[HttpPost("{id}/execute")]
public Task ExecuteAsync(Guid id, WorkflowInstanceExecuteRequestDto input)
{
return _service.ExecuteAsync(id, input);
}

[HttpGet("{id}")]
public virtual Task<WorkflowInstanceDto> GetAsync(Guid id)
{
Expand All @@ -36,5 +54,10 @@ public virtual Task<PagedResultDto<WorkflowInstanceBasicDto>> GetListAsync(Workf
return _service.GetListAsync(input);
}

[HttpPost("{id}/retry")]
public Task RetryAsync(Guid id, WorkflowInstanceRetryRequestDto input)
{
return _service.RetryAsync(id, input);
}
}
}
Loading

0 comments on commit 30b53b8

Please sign in to comment.