27 changed files with 476 additions and 125 deletions
@ -0,0 +1,10 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Application.Services; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WorkflowManagement.Engine |
||||
|
{ |
||||
|
public interface IEngineAppService : IApplicationService |
||||
|
{ |
||||
|
Task InitializeAsync(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,25 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
using Volo.Abp.Data; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WorkflowManagement.Workflows |
||||
|
{ |
||||
|
public class StepNodeDto : EntityDto<Guid> |
||||
|
{ |
||||
|
public string Name { get; set; } |
||||
|
public string StepType { get; set; } |
||||
|
public string CancelCondition { get; set; } |
||||
|
public TimeSpan? RetryInterval { get; set; } |
||||
|
public bool Saga { get; set; } |
||||
|
public Guid? ParentId { get; set; } |
||||
|
public ExtraPropertyDictionary Inputs { get; set; } |
||||
|
public ExtraPropertyDictionary Outputs { get; set; } |
||||
|
public ExtraPropertyDictionary SelectNextStep { get; set; } |
||||
|
public StepNodeDto() |
||||
|
{ |
||||
|
Inputs = new ExtraPropertyDictionary(); |
||||
|
Outputs = new ExtraPropertyDictionary(); |
||||
|
SelectNextStep = new ExtraPropertyDictionary(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
2
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Workflows/Dto/WorkflowCreateDto.cs → aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Workflows/Dto/WorkflowDefinitionCreateDto.cs
2
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Workflows/Dto/WorkflowCreateDto.cs → aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Workflows/Dto/WorkflowDefinitionCreateDto.cs
@ -1,16 +1,25 @@ |
|||||
using System; |
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using Volo.Abp.Application.Dtos; |
||||
|
|
||||
namespace LINGYUN.Abp.WorkflowManagement.Workflows |
namespace LINGYUN.Abp.WorkflowManagement.Workflows |
||||
{ |
{ |
||||
public class WorkflowDto |
public class WorkflowDto : AuditedEntityDto<Guid> |
||||
{ |
{ |
||||
public string WorkflowId { get; set; } |
public bool IsEnabled { get; set; } |
||||
public object Data { get; set; } |
|
||||
public string DefinitionId { get; set; } |
public string Name { get; set; } |
||||
|
|
||||
|
public string DisplayName { get; set; } |
||||
|
|
||||
|
public string Description { get; set; } |
||||
|
|
||||
public int Version { get; set; } |
public int Version { get; set; } |
||||
public string Status { get; set; } |
|
||||
public string Reference { get; set; } |
public TimeSpan? ErrorRetryInterval { get; set; } |
||||
public DateTime StartTime { get; set; } |
|
||||
public DateTime? EndTime { get; set; } |
public List<StepNodeDto> Steps { get; set; } = new List<StepNodeDto>(); |
||||
|
|
||||
|
public List<StepNodeDto> CompensateNodes { get; set; } = new List<StepNodeDto>(); |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -0,0 +1,16 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WorkflowManagement.Workflows |
||||
|
{ |
||||
|
public class WorkflowInstanceDto |
||||
|
{ |
||||
|
public string WorkflowId { get; set; } |
||||
|
public object Data { get; set; } |
||||
|
public string DefinitionId { get; set; } |
||||
|
public int Version { get; set; } |
||||
|
public string Status { get; set; } |
||||
|
public string Reference { get; set; } |
||||
|
public DateTime StartTime { get; set; } |
||||
|
public DateTime? EndTime { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WorkflowManagement.Workflows |
||||
|
{ |
||||
|
public interface IWorkflowDefinitionAppService |
||||
|
{ |
||||
|
Task<WorkflowDto> CreateAsync(WorkflowDefinitionCreateDto input); |
||||
|
|
||||
|
Task<WorkflowDto> GetAsync(Guid id); |
||||
|
|
||||
|
Task DeleteAsync(Guid id); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,23 @@ |
|||||
|
using LINGYUN.Abp.WorkflowManagement.Authorization; |
||||
|
using Microsoft.AspNetCore.Authorization; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WorkflowManagement.Engine |
||||
|
{ |
||||
|
[Authorize(WorkflowManagementPermissions.Engine.Default)] |
||||
|
public class EngineAppService : WorkflowManagementAppServiceBase, IEngineAppService |
||||
|
{ |
||||
|
private readonly IWorkflowEngineManager _engineManager; |
||||
|
|
||||
|
public EngineAppService(IWorkflowEngineManager engineManager) |
||||
|
{ |
||||
|
_engineManager = engineManager; |
||||
|
} |
||||
|
|
||||
|
[Authorize(WorkflowManagementPermissions.Engine.Initialize)] |
||||
|
public virtual async Task InitializeAsync() |
||||
|
{ |
||||
|
await _engineManager.InitializeAsync(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,142 @@ |
|||||
|
using LINGYUN.Abp.WorkflowManagement.Authorization; |
||||
|
using Microsoft.AspNetCore.Authorization; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WorkflowManagement.Workflows |
||||
|
{ |
||||
|
[Authorize(WorkflowManagementPermissions.WorkflowDef.Default)] |
||||
|
public class WorkflowDefinitionAppService : WorkflowManagementAppServiceBase, IWorkflowDefinitionAppService |
||||
|
{ |
||||
|
private readonly WorkflowManager _workflowManager; |
||||
|
|
||||
|
private readonly IWorkflowRepository _workflowRepository; |
||||
|
private readonly IStepNodeRepository _stepNodeRepository; |
||||
|
private readonly ICompensateNodeRepository _compensateNodeRepository; |
||||
|
|
||||
|
public WorkflowDefinitionAppService( |
||||
|
WorkflowManager workflowManager, |
||||
|
IWorkflowRepository workflowRepository, |
||||
|
IStepNodeRepository stepNodeRepository, |
||||
|
ICompensateNodeRepository compensateNodeRepository) |
||||
|
{ |
||||
|
_workflowManager = workflowManager; |
||||
|
_workflowRepository = workflowRepository; |
||||
|
_stepNodeRepository = stepNodeRepository; |
||||
|
_compensateNodeRepository = compensateNodeRepository; |
||||
|
} |
||||
|
|
||||
|
[Authorize(WorkflowManagementPermissions.WorkflowDef.Create)] |
||||
|
public virtual async Task<WorkflowDto> CreateAsync(WorkflowDefinitionCreateDto input) |
||||
|
{ |
||||
|
if (await _workflowRepository.CheckVersionAsync(input.Name, input.Version)) |
||||
|
{ |
||||
|
throw new BusinessException(); |
||||
|
} |
||||
|
|
||||
|
var workflowDef = new Workflow( |
||||
|
GuidGenerator.Create(), |
||||
|
input.Name, |
||||
|
input.DisplayName, |
||||
|
input.Description, |
||||
|
input.Version, |
||||
|
tenantId: CurrentTenant.Id) |
||||
|
{ |
||||
|
IsEnabled = input.IsEnabled, |
||||
|
}; |
||||
|
|
||||
|
var stepDefNodes = new List<StepNode>(); |
||||
|
var stepCompensateDefNodes = new List<CompensateNode>(); |
||||
|
|
||||
|
ICollection<CompensateNode> CreateCompensateNodes(StepNode node, ICollection<StepDto> steps) |
||||
|
{ |
||||
|
var stepNodes = new List<CompensateNode>(); |
||||
|
foreach (var step in steps) |
||||
|
{ |
||||
|
var stepNode = new CompensateNode( |
||||
|
GuidGenerator.Create(), |
||||
|
workflowDef.Id, |
||||
|
step.Name, |
||||
|
step.StepType, |
||||
|
step.CancelCondition, |
||||
|
saga: step.Saga, |
||||
|
parentId: node.Id, |
||||
|
tenantId: CurrentTenant.Id); |
||||
|
stepNode.Inputs.AddIfNotContains(step.Inputs); |
||||
|
stepNode.Outputs.AddIfNotContains(step.Outputs); |
||||
|
stepNode.SelectNextStep.AddIfNotContains(step.SelectNextStep); |
||||
|
|
||||
|
stepNodes.Add(stepNode); |
||||
|
} |
||||
|
return stepNodes; |
||||
|
} |
||||
|
|
||||
|
foreach (var stepInput in input.Steps) |
||||
|
{ |
||||
|
var stepNode = new StepNode( |
||||
|
GuidGenerator.Create(), |
||||
|
workflowDef.Id, |
||||
|
stepInput.Name, |
||||
|
stepInput.StepType, |
||||
|
stepInput.CancelCondition, |
||||
|
saga: stepInput.Saga, |
||||
|
tenantId: CurrentTenant.Id); |
||||
|
stepNode.Inputs.AddIfNotContains(stepInput.Inputs); |
||||
|
stepNode.Outputs.AddIfNotContains(stepInput.Outputs); |
||||
|
stepNode.SelectNextStep.AddIfNotContains(stepInput.SelectNextStep); |
||||
|
|
||||
|
stepDefNodes.Add(stepNode); |
||||
|
stepCompensateDefNodes.AddRange(CreateCompensateNodes(stepNode, stepInput.CompensateWith)); |
||||
|
} |
||||
|
|
||||
|
await _workflowRepository.InsertAsync(workflowDef); |
||||
|
await _stepNodeRepository.InsertManyAsync(stepDefNodes); |
||||
|
await _compensateNodeRepository.InsertManyAsync(stepCompensateDefNodes); |
||||
|
|
||||
|
_workflowManager.Register(workflowDef, stepDefNodes, stepCompensateDefNodes); |
||||
|
|
||||
|
var workflowDto = ObjectMapper.Map<Workflow, WorkflowDto>(workflowDef); |
||||
|
|
||||
|
workflowDto.Steps.AddRange( |
||||
|
ObjectMapper.Map<List<StepNode>, List<StepNodeDto>>(stepDefNodes)); |
||||
|
|
||||
|
workflowDto.CompensateNodes.AddRange( |
||||
|
ObjectMapper.Map<List<CompensateNode>, List<StepNodeDto>>(stepCompensateDefNodes)); |
||||
|
|
||||
|
return workflowDto; |
||||
|
} |
||||
|
|
||||
|
[Authorize(WorkflowManagementPermissions.WorkflowDef.Delete)] |
||||
|
public virtual async Task DeleteAsync(Guid id) |
||||
|
{ |
||||
|
var workflowDef = await _workflowRepository.GetAsync(id); |
||||
|
var stepDefNodes = await _stepNodeRepository.GetAllChildrenWithWorkflowAsync(workflowDef.Id); |
||||
|
var compensateDefNodes = await _compensateNodeRepository.GetAllChildrenWithWorkflowAsync(workflowDef.Id); |
||||
|
|
||||
|
await _workflowRepository.DeleteAsync(workflowDef); |
||||
|
await _stepNodeRepository.DeleteManyAsync(stepDefNodes); |
||||
|
await _compensateNodeRepository.DeleteManyAsync(compensateDefNodes); |
||||
|
|
||||
|
_workflowManager.UnRegister(workflowDef); |
||||
|
} |
||||
|
|
||||
|
public virtual async Task<WorkflowDto> GetAsync(Guid id) |
||||
|
{ |
||||
|
var workflowDef = await _workflowRepository.GetAsync(id); |
||||
|
var stepDefNodes = await _stepNodeRepository.GetAllChildrenWithWorkflowAsync(workflowDef.Id); |
||||
|
var compensateDefNodes = await _compensateNodeRepository.GetAllChildrenWithWorkflowAsync(workflowDef.Id); |
||||
|
|
||||
|
var workflowDto = ObjectMapper.Map<Workflow, WorkflowDto>(workflowDef); |
||||
|
|
||||
|
workflowDto.Steps.AddRange( |
||||
|
ObjectMapper.Map<List<StepNode>, List<StepNodeDto>>(stepDefNodes)); |
||||
|
|
||||
|
workflowDto.CompensateNodes.AddRange( |
||||
|
ObjectMapper.Map<List<CompensateNode>, List<StepNodeDto>>(compensateDefNodes)); |
||||
|
|
||||
|
return workflowDto; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,7 +1,12 @@ |
|||||
{ |
{ |
||||
"culture": "zh-Hans", |
"culture": "zh-Hans", |
||||
"texts": { |
"texts": { |
||||
"Permission:WorkflowManagement": "WorkflowManagement", |
"Permission:WorkflowManagement": "工作流管理", |
||||
|
"Permission:Engine": "流程引擎", |
||||
|
"Permission:Initialize": "初始化", |
||||
|
"Permission:WorkflowDef": "流程定义", |
||||
|
"Permission:Create": "创建", |
||||
|
"Permission:Delete": "删除", |
||||
"Permission:ManageSettings": "管理设置" |
"Permission:ManageSettings": "管理设置" |
||||
} |
} |
||||
} |
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WorkflowManagement |
||||
|
{ |
||||
|
public interface IWorkflowEngineManager |
||||
|
{ |
||||
|
Task InitializeAsync(CancellationToken cancellationToken = default); |
||||
|
|
||||
|
Task StopAsync(CancellationToken cancellationToken = default); |
||||
|
|
||||
|
Task StartAsync(CancellationToken cancellationToken = default); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,27 @@ |
|||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.AspNetCore.Mvc; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WorkflowManagement.Engine |
||||
|
{ |
||||
|
[RemoteService(Name = WorkflowManagementRemoteServiceConsts.RemoteServiceName)] |
||||
|
[Area("WorkflowManagement")] |
||||
|
[Route("api/workflow-management/engine")] |
||||
|
public class EngineController : AbpControllerBase, IEngineAppService |
||||
|
{ |
||||
|
private readonly IEngineAppService _service; |
||||
|
|
||||
|
public EngineController(IEngineAppService service) |
||||
|
{ |
||||
|
_service = service; |
||||
|
} |
||||
|
|
||||
|
[HttpPost] |
||||
|
[Route("initialize")] |
||||
|
public virtual async Task InitializeAsync() |
||||
|
{ |
||||
|
await _service.InitializeAsync(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,42 @@ |
|||||
|
using Microsoft.AspNetCore.Mvc; |
||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.AspNetCore.Mvc; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WorkflowManagement.Workflows |
||||
|
{ |
||||
|
[RemoteService(Name = WorkflowManagementRemoteServiceConsts.RemoteServiceName)] |
||||
|
[Area("WorkflowManagement")] |
||||
|
[Route("api/workflow-management/workflows/definition")] |
||||
|
public class WorkflowDefinitionController : AbpControllerBase, IWorkflowDefinitionAppService |
||||
|
{ |
||||
|
private readonly IWorkflowDefinitionAppService _service; |
||||
|
|
||||
|
public WorkflowDefinitionController( |
||||
|
IWorkflowDefinitionAppService service) |
||||
|
{ |
||||
|
_service = service; |
||||
|
} |
||||
|
|
||||
|
[HttpPost] |
||||
|
public virtual async Task<WorkflowDto> CreateAsync(WorkflowDefinitionCreateDto input) |
||||
|
{ |
||||
|
return await _service.CreateAsync(input); |
||||
|
} |
||||
|
|
||||
|
[HttpDelete] |
||||
|
[Route("{id}")] |
||||
|
public virtual async Task DeleteAsync(Guid id) |
||||
|
{ |
||||
|
await _service.DeleteAsync(id); |
||||
|
} |
||||
|
|
||||
|
[HttpGet] |
||||
|
[Route("{id}")] |
||||
|
public virtual async Task<WorkflowDto> GetAsync(Guid id) |
||||
|
{ |
||||
|
return await _service.GetAsync(id); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,61 @@ |
|||||
|
using LINGYUN.Abp.Data.DbMigrator; |
||||
|
using LINGYUN.Abp.WorkflowCore.Persistence.EntityFrameworkCore; |
||||
|
using LINGYUN.Abp.WorkflowManagement; |
||||
|
using LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore; |
||||
|
using Microsoft.EntityFrameworkCore; |
||||
|
using Microsoft.Extensions.Logging; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using WorkflowCore.Interface; |
||||
|
|
||||
|
namespace LY.MicroService.WorkflowManagement; |
||||
|
|
||||
|
public class WorkflowEngineManager : IWorkflowEngineManager, ISingletonDependency |
||||
|
{ |
||||
|
private readonly IWorkflowHost _workflowHost; |
||||
|
private readonly IDbSchemaMigrator _dbSchemaMigrator; |
||||
|
private readonly ILogger<WorkflowEngineManager> _logger; |
||||
|
public WorkflowEngineManager( |
||||
|
IWorkflowHost workflowHost, |
||||
|
IDbSchemaMigrator dbSchemaMigrator, |
||||
|
ILogger<WorkflowEngineManager> logger) |
||||
|
{ |
||||
|
_logger = logger; |
||||
|
_workflowHost = workflowHost; |
||||
|
_dbSchemaMigrator = dbSchemaMigrator; |
||||
|
} |
||||
|
|
||||
|
public async Task InitializeAsync(CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
_logger.LogInformation("Migrating workflow core context..."); |
||||
|
await _dbSchemaMigrator.MigrateAsync<WorkflowDbContext>( |
||||
|
(connectionString, builder) => |
||||
|
{ |
||||
|
builder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString)); |
||||
|
|
||||
|
return new WorkflowDbContext(builder.Options); |
||||
|
}); |
||||
|
_logger.LogInformation("Migrated workflow core context."); |
||||
|
|
||||
|
_logger.LogInformation("Migrating workflow management context..."); |
||||
|
await _dbSchemaMigrator.MigrateAsync<WorkflowManagementDbContext>( |
||||
|
(connectionString, builder) => |
||||
|
{ |
||||
|
builder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString)); |
||||
|
|
||||
|
return new WorkflowManagementDbContext(builder.Options); |
||||
|
}); |
||||
|
_logger.LogInformation("Migrated workflow management context."); |
||||
|
} |
||||
|
|
||||
|
public async Task StartAsync(CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
await _workflowHost.StartAsync(cancellationToken); |
||||
|
} |
||||
|
|
||||
|
public async Task StopAsync(CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
await _workflowHost.StopAsync(cancellationToken); |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue