Browse Source

use active apis to solve multi-tenant registration workflow

pull/439/head
cKey 4 years ago
parent
commit
8a0c7b171d
  1. 18
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence.EntityFrameworkCore/LINGYUN/Abp/WorkflowCore/Persistence/EntityFrameworkCore/EfCoreRepositoryExtensions.cs
  2. 19
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence.EntityFrameworkCore/LINGYUN/Abp/WorkflowCore/Persistence/EntityFrameworkCore/EfCoreWorkflowRepository.cs
  3. 1
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Persistence/AbpWorkflowCorePersistenceModule.cs
  4. 28
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Persistence/AbpWorkflowPurger.cs
  5. 7
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Persistence/IWorkflowRepository.cs
  6. 25
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Persistence/PersistedWorkflow.cs
  7. 3
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Authorization/WorkflowManagementPermissionDefinitionProvider.cs
  8. 2
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Authorization/WorkflowManagementPermissions.cs
  9. 2
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Engine/IEngineAppService.cs
  10. 13
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application/LINGYUN/Abp/WorkflowManagement/Engine/EngineAppService.cs
  11. 1
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain.Shared/LINGYUN/Abp/WorkflowManagement/Localization/Resources/en.json
  12. 1
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain.Shared/LINGYUN/Abp/WorkflowManagement/Localization/Resources/zh-Hans.json
  13. 10
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/IWorkflowRegistryManager.cs
  14. 45
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/WorkflowManager.cs
  15. 26
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/WorkflowRegisterService.cs
  16. 48
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/WorkflowRegistryManager.cs
  17. 7
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.HttpApi/LINGYUN/Abp/WorkflowManagement/Engine/EngineController.cs
  18. 6
      aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/WorkflowEngineManager.cs

18
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence.EntityFrameworkCore/LINGYUN/Abp/WorkflowCore/Persistence/EntityFrameworkCore/EfCoreRepositoryExtensions.cs

@ -0,0 +1,18 @@
using Microsoft.EntityFrameworkCore;
using System.Linq;
namespace LINGYUN.Abp.WorkflowCore.Persistence.EntityFrameworkCore
{
public static class EfCoreRepositoryExtensions
{
public static IQueryable<PersistedWorkflow> IncludeIf(
this IQueryable<PersistedWorkflow> quertable,
bool includeDetails = true)
{
return !includeDetails ? quertable :
quertable
.Include(x => x.ExecutionPointers)
.ThenInclude(p => p.ExtensionAttributes);
}
}
}

19
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence.EntityFrameworkCore/LINGYUN/Abp/WorkflowCore/Persistence/EntityFrameworkCore/EfCoreWorkflowRepository.cs

@ -27,8 +27,7 @@ namespace LINGYUN.Abp.WorkflowCore.Persistence
int take, int take,
CancellationToken cancellationToken = default) CancellationToken cancellationToken = default)
{ {
return await (await GetDbSetAsync()) return await (await WithDetailsAsync())
.Include(x => x.ExecutionPointers)
.WhereIf(status.HasValue, x => x.Status == status.Value) .WhereIf(status.HasValue, x => x.Status == status.Value)
.WhereIf(!type.IsNullOrWhiteSpace(), x => x.WorkflowDefinitionId.Equals(type)) .WhereIf(!type.IsNullOrWhiteSpace(), x => x.WorkflowDefinitionId.Equals(type))
.WhereIf(createdFrom.HasValue, x => x.CreationTime >= createdFrom.Value) .WhereIf(createdFrom.HasValue, x => x.CreationTime >= createdFrom.Value)
@ -37,12 +36,22 @@ namespace LINGYUN.Abp.WorkflowCore.Persistence
.ToListAsync(); .ToListAsync();
} }
public virtual async Task<List<PersistedWorkflow>> GetOlderListAsync(
WorkflowStatus status,
DateTime olderThan,
bool includeDetails = false,
int? maxResultCount = null,
CancellationToken cancellationToken = default)
{
return await (await WithDetailsAsync())
.Where(x => x.Status == status && x.CompleteTime < olderThan)
.ToListAsync();
}
public override async Task<IQueryable<PersistedWorkflow>> WithDetailsAsync() public override async Task<IQueryable<PersistedWorkflow>> WithDetailsAsync()
{ {
var quertable = await base.WithDetailsAsync(); var quertable = await base.WithDetailsAsync();
return quertable return quertable.IncludeIf(true);
.Include(x => x.ExecutionPointers)
.ThenInclude(p => p.ExtensionAttributes);
} }
} }
} }

1
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Persistence/AbpWorkflowCorePersistenceModule.cs

@ -10,6 +10,7 @@ namespace LINGYUN.Abp.WorkflowCore.Persistence
{ {
public override void PreConfigureServices(ServiceConfigurationContext context) public override void PreConfigureServices(ServiceConfigurationContext context)
{ {
context.Services.AddTransient<IWorkflowPurger, AbpWorkflowPurger>();
context.Services.AddTransient<IPersistenceProvider, AbpWorkflowPersistenceProvider>(); context.Services.AddTransient<IPersistenceProvider, AbpWorkflowPersistenceProvider>();
context.Services.AddTransient<AbpWorkflowPersistenceProvider>(); context.Services.AddTransient<AbpWorkflowPersistenceProvider>();

28
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Persistence/AbpWorkflowPurger.cs

@ -0,0 +1,28 @@
using System;
using System.Threading.Tasks;
using WorkflowCore.Interface;
using WorkflowCore.Models;
namespace LINGYUN.Abp.WorkflowCore.Persistence
{
public class AbpWorkflowPurger : IWorkflowPurger
{
private readonly IWorkflowRepository _workflowRepository;
public AbpWorkflowPurger(
IWorkflowRepository workflowRepository)
{
_workflowRepository = workflowRepository;
}
public virtual async Task PurgeWorkflows(WorkflowStatus status, DateTime olderThan)
{
var olderThanUtc = olderThan.ToUniversalTime();
var workflows = await _workflowRepository
.GetOlderListAsync(status, olderThanUtc, includeDetails: true);
await _workflowRepository.DeleteManyAsync(workflows);
}
}
}

7
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Persistence/IWorkflowRepository.cs

@ -17,5 +17,12 @@ namespace LINGYUN.Abp.WorkflowCore.Persistence
int skip, int skip,
int take, int take,
CancellationToken cancellationToken = default); CancellationToken cancellationToken = default);
Task<List<PersistedWorkflow>> GetOlderListAsync(
WorkflowStatus status,
DateTime olderThan,
bool includeDetails = false,
int? maxResultCount = null,
CancellationToken cancellationToken = default);
} }
} }

25
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Persistence/PersistedWorkflow.cs

@ -1,7 +1,9 @@
using System; using JetBrains.Annotations;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;
using Volo.Abp;
using Volo.Abp.Domain.Entities.Auditing; using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy; using Volo.Abp.MultiTenancy;
using WorkflowCore.Models; using WorkflowCore.Models;
@ -53,8 +55,10 @@ namespace LINGYUN.Abp.WorkflowCore.Persistence
ExecutionPointers = new Collection<PersistedExecutionPointer>(); ExecutionPointers = new Collection<PersistedExecutionPointer>();
} }
public void AddPointer(PersistedExecutionPointer pointer) public void AddPointer([NotNull] PersistedExecutionPointer pointer)
{ {
Check.NotNull(pointer, nameof(pointer));
ExecutionPointers.Add(pointer); ExecutionPointers.Add(pointer);
} }
@ -62,5 +66,22 @@ namespace LINGYUN.Abp.WorkflowCore.Persistence
{ {
return ExecutionPointers.FirstOrDefault(point => point.Id.Equals(id)); return ExecutionPointers.FirstOrDefault(point => point.Id.Equals(id));
} }
public void RemovePointers([NotNull] IEnumerable<PersistedExecutionPointer> pointers)
{
Check.NotNull(pointers, nameof(pointers));
foreach (var pointer in pointers)
{
RemovePointer(pointer);
}
}
public virtual void RemovePointer([NotNull] PersistedExecutionPointer pointer)
{
Check.NotNull(pointer, nameof(pointer));
ExecutionPointers.RemoveAll(c => c.Id == pointer.Id);
}
} }
} }

3
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Authorization/WorkflowManagementPermissionDefinitionProvider.cs

@ -16,6 +16,9 @@ namespace LINGYUN.Abp.WorkflowManagement.Authorization
engine.AddChild( engine.AddChild(
WorkflowManagementPermissions.Engine.Initialize, WorkflowManagementPermissions.Engine.Initialize,
L("Permission:Initialize")); L("Permission:Initialize"));
engine.AddChild(
WorkflowManagementPermissions.Engine.Register,
L("Permission:Register"));
var workflow = group.AddPermission( var workflow = group.AddPermission(
WorkflowManagementPermissions.WorkflowDef.Default, WorkflowManagementPermissions.WorkflowDef.Default,

2
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Authorization/WorkflowManagementPermissions.cs

@ -11,6 +11,8 @@
public const string Default = GroupName + ".Engine"; public const string Default = GroupName + ".Engine";
public const string Initialize = Default + ".Initialize"; public const string Initialize = Default + ".Initialize";
public const string Register = Default + ".Register";
} }
public static class WorkflowDef public static class WorkflowDef

2
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Engine/IEngineAppService.cs

@ -6,5 +6,7 @@ namespace LINGYUN.Abp.WorkflowManagement.Engine
public interface IEngineAppService : IApplicationService public interface IEngineAppService : IApplicationService
{ {
Task InitializeAsync(); Task InitializeAsync();
Task RegisterAsync();
} }
} }

13
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application/LINGYUN/Abp/WorkflowManagement/Engine/EngineAppService.cs

@ -8,10 +8,14 @@ namespace LINGYUN.Abp.WorkflowManagement.Engine
public class EngineAppService : WorkflowManagementAppServiceBase, IEngineAppService public class EngineAppService : WorkflowManagementAppServiceBase, IEngineAppService
{ {
private readonly IWorkflowEngineManager _engineManager; private readonly IWorkflowEngineManager _engineManager;
private readonly IWorkflowRegistryManager _registryManager;
public EngineAppService(IWorkflowEngineManager engineManager) public EngineAppService(
IWorkflowEngineManager engineManager,
IWorkflowRegistryManager registryManager)
{ {
_engineManager = engineManager; _engineManager = engineManager;
_registryManager = registryManager;
} }
[Authorize(WorkflowManagementPermissions.Engine.Initialize)] [Authorize(WorkflowManagementPermissions.Engine.Initialize)]
@ -19,5 +23,12 @@ namespace LINGYUN.Abp.WorkflowManagement.Engine
{ {
await _engineManager.InitializeAsync(); await _engineManager.InitializeAsync();
} }
[Authorize(WorkflowManagementPermissions.Engine.Register)]
public virtual async Task RegisterAsync()
{
// 暂时没有解决多租户自动注册工作流,管理员可以通过api主动注册
await _registryManager.RegisterAsync();
}
} }
} }

1
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain.Shared/LINGYUN/Abp/WorkflowManagement/Localization/Resources/en.json

@ -4,6 +4,7 @@
"Permission:WorkflowManagement": "WorkflowManagement", "Permission:WorkflowManagement": "WorkflowManagement",
"Permission:Engine": "Engine", "Permission:Engine": "Engine",
"Permission:Initialize": "Initialize", "Permission:Initialize": "Initialize",
"Permission:Register": "Register",
"Permission:WorkflowDef": "Definition", "Permission:WorkflowDef": "Definition",
"Permission:Create": "Create", "Permission:Create": "Create",
"Permission:Delete": "Delete", "Permission:Delete": "Delete",

1
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain.Shared/LINGYUN/Abp/WorkflowManagement/Localization/Resources/zh-Hans.json

@ -4,6 +4,7 @@
"Permission:WorkflowManagement": "工作流管理", "Permission:WorkflowManagement": "工作流管理",
"Permission:Engine": "流程引擎", "Permission:Engine": "流程引擎",
"Permission:Initialize": "初始化", "Permission:Initialize": "初始化",
"Permission:Register": "注册组件",
"Permission:WorkflowDef": "流程定义", "Permission:WorkflowDef": "流程定义",
"Permission:Create": "创建", "Permission:Create": "创建",
"Permission:Delete": "删除", "Permission:Delete": "删除",

10
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/IWorkflowRegistryManager.cs

@ -0,0 +1,10 @@
using System.Threading;
using System.Threading.Tasks;
namespace LINGYUN.Abp.WorkflowManagement
{
public interface IWorkflowRegistryManager
{
Task RegisterAsync(CancellationToken cancellationToken = default);
}
}

45
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/WorkflowManager.cs

@ -19,19 +19,20 @@ namespace LINGYUN.Abp.WorkflowManagement
public class WorkflowManager : DomainService, ITransientDependency public class WorkflowManager : DomainService, ITransientDependency
{ {
private readonly IWorkflowRegistry _registry; private readonly IWorkflowRegistry _registry;
private readonly IPersistenceProvider _persistenceProvider;
public WorkflowManager( public WorkflowManager(IWorkflowRegistry registry)
IWorkflowRegistry registry,
IPersistenceProvider persistenceProvider)
{ {
_registry = registry; _registry = registry;
_persistenceProvider = persistenceProvider; }
public virtual bool IsRegistered(Workflow workflow)
{
return _registry.IsRegistered(workflow.Id.ToString(), workflow.Version);
} }
public virtual void UnRegister(Workflow workflow) public virtual void UnRegister(Workflow workflow)
{ {
if (_registry.IsRegistered(workflow.Id.ToString(), workflow.Version)) if (IsRegistered(workflow))
{ {
_registry.DeregisterWorkflow(workflow.Id.ToString(), workflow.Version); _registry.DeregisterWorkflow(workflow.Id.ToString(), workflow.Version);
} }
@ -42,22 +43,28 @@ namespace LINGYUN.Abp.WorkflowManagement
ICollection<StepNode> steps, ICollection<StepNode> steps,
ICollection<CompensateNode> compensates) ICollection<CompensateNode> compensates)
{ {
var dataType = typeof(Dictionary<string, object>); if (!IsRegistered(workflow))
var source = new DefinitionSourceV1
{ {
Id = workflow.Id.ToString(), var dataType = typeof(Dictionary<string, object>);
Version = workflow.Version, var source = new DefinitionSourceV1
Description = workflow.Description ?? workflow.DisplayName, {
DataType = $"{dataType.FullName}, {dataType.Assembly}", Id = workflow.Id.ToString(),
DefaultErrorBehavior = workflow.ErrorBehavior, Version = workflow.Version,
DefaultErrorRetryInterval = workflow.ErrorRetryInterval, Description = workflow.Description ?? workflow.DisplayName,
Steps = ConvertSteps(steps, compensates) DataType = $"{dataType.FullName}, {dataType.Assembly}",
}; DefaultErrorBehavior = workflow.ErrorBehavior,
DefaultErrorRetryInterval = workflow.ErrorRetryInterval,
Steps = ConvertSteps(steps, compensates)
};
var def = Convert(source);
var def = Convert(source); _registry.RegisterWorkflow(def);
_registry.RegisterWorkflow(def);
return def;
}
return def; return _registry.GetDefinition(workflow.Id.ToString(), workflow.Version);
} }
private List<StepSourceV1> ConvertSteps( private List<StepSourceV1> ConvertSteps(

26
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/WorkflowRegisterService.cs

@ -6,35 +6,17 @@ namespace LINGYUN.Abp.WorkflowManagement
{ {
public class WorkflowRegisterService : BackgroundService public class WorkflowRegisterService : BackgroundService
{ {
private readonly WorkflowManager _workflowManager; private readonly IWorkflowRegistryManager _registryManager;
private readonly IWorkflowRepository _workflowRepository;
private readonly IStepNodeRepository _stepNodeRepository;
private readonly ICompensateNodeRepository _compensateNodeRepository;
public WorkflowRegisterService( public WorkflowRegisterService(
WorkflowManager workflowManager, IWorkflowRegistryManager registryManager)
IWorkflowRepository workflowRepository,
IStepNodeRepository stepNodeRepository,
ICompensateNodeRepository compensateNodeRepository)
{ {
_workflowManager = workflowManager; _registryManager = registryManager;
_workflowRepository = workflowRepository;
_stepNodeRepository = stepNodeRepository;
_compensateNodeRepository = compensateNodeRepository;
} }
protected override async Task ExecuteAsync(CancellationToken stoppingToken) protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{ {
var workflows = await _workflowRepository.GetListAsync(x => x.IsEnabled, cancellationToken: stoppingToken); await _registryManager.RegisterAsync(stoppingToken);
foreach (var workflow in workflows)
{
var stepNodes = await _stepNodeRepository.GetAllChildrenWithWorkflowAsync(workflow.Id, cancellationToken: stoppingToken);
var compensateNodes = await _compensateNodeRepository.GetAllChildrenWithWorkflowAsync(workflow.Id, cancellationToken: stoppingToken);
_workflowManager.Register(workflow, stepNodes, compensateNodes);
}
} }
} }
} }

48
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/WorkflowRegistryManager.cs

@ -0,0 +1,48 @@
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.WorkflowManagement
{
public class WorkflowRegistryManager : IWorkflowRegistryManager, ITransientDependency
{
private readonly WorkflowManager _workflowManager;
private readonly IWorkflowRepository _workflowRepository;
private readonly IStepNodeRepository _stepNodeRepository;
private readonly ICompensateNodeRepository _compensateNodeRepository;
public WorkflowRegistryManager(
WorkflowManager workflowManager,
IWorkflowRepository workflowRepository,
IStepNodeRepository stepNodeRepository,
ICompensateNodeRepository compensateNodeRepository)
{
_workflowManager = workflowManager;
_workflowRepository = workflowRepository;
_stepNodeRepository = stepNodeRepository;
_compensateNodeRepository = compensateNodeRepository;
}
public virtual async Task RegisterAsync(CancellationToken cancellationToken = default)
{
// TODO: 多租户如何注册?
var workflows = await _workflowRepository
.GetListAsync(x => x.IsEnabled, cancellationToken: cancellationToken);
foreach (var workflow in workflows)
{
if (!_workflowManager.IsRegistered(workflow))
{
var stepNodes = await _stepNodeRepository
.GetAllChildrenWithWorkflowAsync(workflow.Id, cancellationToken: cancellationToken);
var compensateNodes = await _compensateNodeRepository
.GetAllChildrenWithWorkflowAsync(workflow.Id, cancellationToken: cancellationToken);
_workflowManager.Register(workflow, stepNodes, compensateNodes);
}
}
}
}
}

7
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.HttpApi/LINGYUN/Abp/WorkflowManagement/Engine/EngineController.cs

@ -23,5 +23,12 @@ namespace LINGYUN.Abp.WorkflowManagement.Engine
{ {
await _service.InitializeAsync(); await _service.InitializeAsync();
} }
[HttpPost]
[Route("register")]
public virtual async Task RegisterAsync()
{
await _service.RegisterAsync();
}
} }
} }

6
aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/WorkflowEngineManager.cs

@ -15,6 +15,7 @@ public class WorkflowEngineManager : IWorkflowEngineManager, ISingletonDependenc
{ {
private readonly IWorkflowHost _workflowHost; private readonly IWorkflowHost _workflowHost;
private readonly IDbSchemaMigrator _dbSchemaMigrator; private readonly IDbSchemaMigrator _dbSchemaMigrator;
private readonly ILogger<WorkflowEngineManager> _logger; private readonly ILogger<WorkflowEngineManager> _logger;
public WorkflowEngineManager( public WorkflowEngineManager(
IWorkflowHost workflowHost, IWorkflowHost workflowHost,
@ -49,6 +50,11 @@ public class WorkflowEngineManager : IWorkflowEngineManager, ISingletonDependenc
_logger.LogInformation("Migrated workflow management context."); _logger.LogInformation("Migrated workflow management context.");
} }
public async Task RegisterAsync(CancellationToken cancellationToken = default)
{
}
public async Task StartAsync(CancellationToken cancellationToken = default) public async Task StartAsync(CancellationToken cancellationToken = default)
{ {
await _workflowHost.StartAsync(cancellationToken); await _workflowHost.StartAsync(cancellationToken);

Loading…
Cancel
Save