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.Collections.Generic; |
|||
using Volo.Abp.Application.Dtos; |
|||
|
|||
namespace LINGYUN.Abp.WorkflowManagement.Workflows |
|||
{ |
|||
public class WorkflowDto |
|||
public class WorkflowDto : AuditedEntityDto<Guid> |
|||
{ |
|||
public string WorkflowId { get; set; } |
|||
public object Data { get; set; } |
|||
public string DefinitionId { get; set; } |
|||
public bool IsEnabled { get; set; } |
|||
|
|||
public string Name { get; set; } |
|||
|
|||
public string DisplayName { get; set; } |
|||
|
|||
public string Description { 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; } |
|||
|
|||
public TimeSpan? ErrorRetryInterval { 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", |
|||
"texts": { |
|||
"Permission:WorkflowManagement": "WorkflowManagement", |
|||
"Permission:WorkflowManagement": "工作流管理", |
|||
"Permission:Engine": "流程引擎", |
|||
"Permission:Initialize": "初始化", |
|||
"Permission:WorkflowDef": "流程定义", |
|||
"Permission:Create": "创建", |
|||
"Permission:Delete": "删除", |
|||
"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