Browse Source

add workflow management service

pull/439/head
cKey 4 years ago
parent
commit
7d5d2efae9
  1. 2
      apps/vue/src/views/account/center/index.vue
  2. 1
      aspnet-core/Directory.Build.props
  3. 13
      aspnet-core/LINGYUN.MicroService.Workflow.sln
  4. 4
      aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IndexInitializer.cs
  5. 4
      aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application.Contracts/LINGYUN/Abp/SettingManagement/Localization/ApplicationContracts/en.json
  6. 4
      aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application.Contracts/LINGYUN/Abp/SettingManagement/Localization/ApplicationContracts/zh-Hans.json
  7. 2
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.DistributedLock/LINGYUN.Abp.WorkflowCore.DistributedLock.csproj
  8. 1
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.DistributedLock/LINGYUN/Abp/WorkflowCore/DistributedLock/AbpWorkflowCoreDistributedLockModule.cs
  9. 63
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Persistence/AbpWorkflowPersistenceProvider.cs
  10. 9
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.RabbitMQ/LINGYUN/Abp/WorkflowCore/RabbitMQ/AbpRabbitMqQueueProvider.cs
  11. 25
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.RabbitMQ/LINGYUN/Abp/WorkflowCore/RabbitMQ/AbpWorkflowCoreRabbitMQModule.cs
  12. 67
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/AbpUnitOfWorkQueueProvider.cs
  13. 11
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/AbpWorkflowCoreModule.cs
  14. 20
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/IQueueAdapterProvider.cs
  15. 50
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/SingleNodeQueueAdapterProvider.cs
  16. 13
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Activitys/Dto/ActivityFailureInput.cs
  17. 7
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Activitys/Dto/ActivityReleaseInput.cs
  18. 13
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Activitys/Dto/ActivitySuccessInput.cs
  19. 13
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Activitys/Dto/GetPendingActivityInput.cs
  20. 15
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Activitys/Dto/PendingActivityDto.cs
  21. 16
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Activitys/IActivityAppService.cs
  22. 19
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Events/Dto/EventPublishInput.cs
  23. 10
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Events/IEventAppService.cs
  24. 20
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Workflows/Dto/StepDto.cs
  25. 30
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Workflows/Dto/WorkflowCreateDto.cs
  26. 18
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Workflows/Dto/WorkflowDefinitionDto.cs
  27. 16
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Workflows/Dto/WorkflowDto.cs
  28. 9
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Workflows/Dto/WorkflowStartInput.cs
  29. 20
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Workflows/IWorkflowAppService.cs
  30. 40
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application/LINGYUN/Abp/WorkflowManagement/Activitys/ActivityAppService.cs
  31. 22
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application/LINGYUN/Abp/WorkflowManagement/Events/EventAppService.cs
  32. 10
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application/LINGYUN/Abp/WorkflowManagement/WorkflowManagementApplicationMapperProfile.cs
  33. 165
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application/LINGYUN/Abp/WorkflowManagement/Workflows/WorkflowAppService.cs
  34. 11
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain.Shared/LINGYUN/Abp/WorkflowManagement/WorkflowConsts.cs
  35. 27
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/CompensateNode.cs
  36. 15
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/ICompensateNodeRepository.cs
  37. 21
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/IStep.cs
  38. 15
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/IStepNodeRepository.cs
  39. 15
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/IWorkflowRepository.cs
  40. 14
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/Step.cs
  41. 27
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/StepNode.cs
  42. 22
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/Workflow.cs
  43. 2
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/WorkflowManagementDbProperties.cs
  44. 3
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/WorkflowManagementDomainModule.cs
  45. 530
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/WorkflowManager.cs
  46. 40
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/WorkflowRegisterService.cs
  47. 27
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore/LINGYUN/Abp/WorkflowManagement/EntityFrameworkCore/EfCoreCompensateNodeRepository.cs
  48. 27
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore/LINGYUN/Abp/WorkflowManagement/EntityFrameworkCore/EfCoreStepNodeRepository.cs
  49. 25
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore/LINGYUN/Abp/WorkflowManagement/EntityFrameworkCore/EfCoreWorkflowRepository.cs
  50. 50
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore/LINGYUN/Abp/WorkflowManagement/EntityFrameworkCore/WorkflowManagementDbContextModelCreatingExtensions.cs
  51. 4
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore/LINGYUN/Abp/WorkflowManagement/EntityFrameworkCore/WorkflowManagementEntityFrameworkCoreModule.cs
  52. 44
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.HttpApi/LINGYUN/Abp/WorkflowManagement/Activitys/ActivityController.cs
  53. 27
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.HttpApi/LINGYUN/Abp/WorkflowManagement/Events/EventController.cs
  54. 61
      aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.HttpApi/LINGYUN/Abp/WorkflowManagement/Workflows/WorkflowController.cs
  55. 13
      aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/Controllers/HomeController.cs
  56. 15
      aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/Dockerfile
  57. 24
      aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/EntityFrameworkCore/WorkflowManagementMigrationsDbContext.cs
  58. 31
      aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/EntityFrameworkCore/WorkflowManagementMigrationsDbContextFactory.cs
  59. 70
      aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/EventBus/Handlers/TenantSynchronizer.cs
  60. 58
      aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/LY.MicroService.WorkflowManagement.HttpApi.Host.csproj
  61. 557
      aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/Migrations/20211212074420_Add-Module-Workflow-Management.Designer.cs
  62. 385
      aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/Migrations/20211212074420_Add-Module-Workflow-Management.cs
  63. 555
      aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/Migrations/WorkflowManagementMigrationsDbContextModelSnapshot.cs
  64. 45
      aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/Program.cs
  65. 21
      aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/Properties/launchSettings.json
  66. 18
      aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/Startup.cs
  67. 32
      aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/TenantHeaderParamter.cs
  68. 223
      aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/WorkflowManagementHttpApiHostModule.Configure.cs
  69. 21
      aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/WorkflowManagementHttpApiHostModule.DataSeeder.cs
  70. 124
      aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/WorkflowManagementHttpApiHostModule.cs
  71. 108
      aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/appsettings.Development.json
  72. 80
      aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/appsettings.json
  73. 1
      aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/dapr.sh

2
apps/vue/src/views/account/center/index.vue

@ -59,7 +59,7 @@
},
{
key: 'setting',
name: L('User'),
name: L('DisplayName:UserSetting'),
component: 'setting',
},
];

1
aspnet-core/Directory.Build.props

@ -3,6 +3,7 @@
<VoloAbpPackageVersion>5.0.0-rc.2</VoloAbpPackageVersion>
<LINGYUNAbpPackageVersion>5.0.0-rc.2</LINGYUNAbpPackageVersion>
<DaprPackageVersion>1.5.0</DaprPackageVersion>
<DistributedLockRedisPackageVersion>1.0.1</DistributedLockRedisPackageVersion>
<DotNetCoreCAPPackageVersion>5.2.0</DotNetCoreCAPPackageVersion>
<AliyunSDKPackageVersion>1.5.10</AliyunSDKPackageVersion>
<AliyunOSSSDKPackageVersion>2.13.0</AliyunOSSSDKPackageVersion>

13
aspnet-core/LINGYUN.MicroService.Workflow.sln

@ -17,7 +17,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WorkflowCore.Pe
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WorkflowCore.RabbitMQ", "modules\workflow\LINGYUN.Abp.WorkflowCore.RabbitMQ\LINGYUN.Abp.WorkflowCore.RabbitMQ.csproj", "{8F904E49-E6DA-499D-8127-DB60DA6B2EE9}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "components", "components", "{15F788FB-C7D0-4EE2-B1D9-EB9F3CCB7F33}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "workflow-components", "workflow-components", "{15F788FB-C7D0-4EE2-B1D9-EB9F3CCB7F33}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WorkflowCore.Components", "modules\workflow\LINGYUN.Abp.WorkflowCore.Components\LINGYUN.Abp.WorkflowCore.Components.csproj", "{13D116F7-C158-48D3-A78A-6F2BFAED1CDF}"
EndProject
@ -37,7 +37,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WorkflowManagem
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore", "modules\workflow\LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore\LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore.csproj", "{C4B1160A-BF25-4868-B962-342ABA4A96EF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LINGYUN.Abp.WorkflowCore.Persistence.Elasticsearch", "modules\workflow\LINGYUN.Abp.WorkflowCore.Persistence.Elasticsearch\LINGYUN.Abp.WorkflowCore.Persistence.Elasticsearch.csproj", "{9F9453F3-7124-4C22-91E3-0DC41A4FD8AB}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.WorkflowCore.Persistence.Elasticsearch", "modules\workflow\LINGYUN.Abp.WorkflowCore.Persistence.Elasticsearch\LINGYUN.Abp.WorkflowCore.Persistence.Elasticsearch.csproj", "{9F9453F3-7124-4C22-91E3-0DC41A4FD8AB}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "host", "host", "{6CB521FC-AC40-49A6-B9A5-91399CAA59AB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LY.MicroService.WorkflowManagement.HttpApi.Host", "services\LY.MicroService.WorkflowManagement.HttpApi.Host\LY.MicroService.WorkflowManagement.HttpApi.Host.csproj", "{D5ED348D-D6F0-4093-BD7D-20E05AA1EB7B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -105,6 +109,10 @@ Global
{9F9453F3-7124-4C22-91E3-0DC41A4FD8AB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9F9453F3-7124-4C22-91E3-0DC41A4FD8AB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9F9453F3-7124-4C22-91E3-0DC41A4FD8AB}.Release|Any CPU.Build.0 = Release|Any CPU
{D5ED348D-D6F0-4093-BD7D-20E05AA1EB7B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D5ED348D-D6F0-4093-BD7D-20E05AA1EB7B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D5ED348D-D6F0-4093-BD7D-20E05AA1EB7B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D5ED348D-D6F0-4093-BD7D-20E05AA1EB7B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -125,6 +133,7 @@ Global
{99BDFED5-907F-44C9-8BA0-90E1725BE211} = {C4496993-41F5-4821-829E-B80A8B3BC260}
{C4B1160A-BF25-4868-B962-342ABA4A96EF} = {C4496993-41F5-4821-829E-B80A8B3BC260}
{9F9453F3-7124-4C22-91E3-0DC41A4FD8AB} = {A2963E0D-D290-40B2-9B36-75F4A5922ABF}
{D5ED348D-D6F0-4093-BD7D-20E05AA1EB7B} = {6CB521FC-AC40-49A6-B9A5-91399CAA59AB}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {6BB7A5DE-DA12-44DC-BC9B-0F6CA524346F}

4
aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IndexInitializer.cs

@ -74,7 +74,7 @@ namespace LINGYUN.Abp.AuditLogging.Elasticsearch
.Properties((np =>
np.Object<ExtraPropertyDictionary>(p => p.Name(n => n.ExtraProperties))
.Date(p => p.Name(n => n.ExecutionTime).Format(dateTimeFormat))))))));
if (indexCreateResponse.IsValid)
if (!indexCreateResponse.IsValid)
{
Logger.LogWarning("Failed to initialize index and audit log may not be retrieved.");
Logger.LogWarning(indexCreateResponse.OriginalException.ToString());
@ -96,7 +96,7 @@ namespace LINGYUN.Abp.AuditLogging.Elasticsearch
.Properties(mp =>
mp.Object<ExtraPropertyDictionary>(p => p.Name(n => n.ExtraProperties))
.Date(p => p.Name(n => n.CreationTime).Format(dateTimeFormat)))));
if (indexCreateResponse.IsValid)
if (!indexCreateResponse.IsValid)
{
Logger.LogWarning("Failed to initialize index and security log may not be retrieved.");
Logger.LogWarning(indexCreateResponse.OriginalException.ToString());

4
aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application.Contracts/LINGYUN/Abp/SettingManagement/Localization/ApplicationContracts/en.json

@ -5,8 +5,8 @@
"Permission:Settings": "Settings",
"Permission:Update": "Update",
"Permission:Manager": "Manager",
"DisplayName:User": "User Settings",
"Description:User": "User defined settings",
"DisplayName:UserSetting": "User Settings",
"Description:UserSetting": "User defined settings",
"DisplayName:System": "System",
"Description:System": "System",
"DisplayName:System.Language": "Language",

4
aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application.Contracts/LINGYUN/Abp/SettingManagement/Localization/ApplicationContracts/zh-Hans.json

@ -5,8 +5,8 @@
"Permission:Settings": "配置管理",
"Permission:Update": "变更",
"Permission:Manager": "管理",
"DisplayName:User": "用户设置",
"Description:User": "用户自定义的设置项",
"DisplayName:UserSetting": "用户设置",
"Description:UserSetting": "用户自定义的设置项",
"DisplayName:System": "系统设置",
"Description:System": "与系统相关的配置项",
"DisplayName:System.Language": "语言",

2
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.DistributedLock/LINGYUN.Abp.WorkflowCore.DistributedLock.csproj

@ -9,7 +9,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="$(MicrosoftPackageVersion)" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="$(MicrosoftPackageVersion)" />
<PackageReference Include="Volo.Abp.DistributedLocking" Version="$(VoloAbpPackageVersion)" />
</ItemGroup>

1
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.DistributedLock/LINGYUN/Abp/WorkflowCore/DistributedLock/AbpWorkflowCoreDistributedLockModule.cs

@ -12,6 +12,7 @@ namespace LINGYUN.Abp.WorkflowCore.DistributedLock
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddMemoryCache();
context.Services.AddSingleton<IDistributedLockProvider, AbpDistributedLockProvider>();
context.Services.AddSingleton<AbpDistributedLockProvider>();

63
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Persistence/AbpWorkflowPersistenceProvider.cs

@ -2,6 +2,7 @@
using Microsoft.Extensions.Logging.Abstractions;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@ -20,6 +21,7 @@ namespace LINGYUN.Abp.WorkflowCore.Persistence
private readonly ICurrentTenant _currentTenant;
private readonly IGuidGenerator _guidGenerator;
//private readonly IUnitOfWorkManager _unitOfWorkManager;
private readonly IWorkflowRepository _workflowRepository;
private readonly IWorkflowEventRepository _workflowEventRepository;
private readonly IWorkflowExecutionErrorRepository _executionErrorRepository;
@ -33,6 +35,7 @@ namespace LINGYUN.Abp.WorkflowCore.Persistence
public AbpWorkflowPersistenceProvider(
ICurrentTenant currentTenant,
IGuidGenerator guidGenerator,
//IUnitOfWorkManager unitOfWorkManager,
IAsyncQueryableExecuter asyncQueryableExecuter,
IWorkflowRepository workflowRepository,
IWorkflowEventRepository workflowEventRepository,
@ -42,6 +45,7 @@ namespace LINGYUN.Abp.WorkflowCore.Persistence
{
_currentTenant = currentTenant;
_guidGenerator = guidGenerator;
//_unitOfWorkManager = unitOfWorkManager;
_asyncQueryableExecuter = asyncQueryableExecuter;
_workflowRepository = workflowRepository;
@ -58,6 +62,8 @@ namespace LINGYUN.Abp.WorkflowCore.Persistence
string token,
CancellationToken cancellationToken = default)
{
//using var unitOfWork = _unitOfWorkManager.Begin();
var uid = Guid.Parse(eventSubscriptionId);
var existingEntity = await _subscriptionRepository.GetAsync(uid, cancellationToken: cancellationToken);
@ -67,16 +73,22 @@ namespace LINGYUN.Abp.WorkflowCore.Persistence
existingEntity.SetSubscriptionToken(null, null, null);
await _subscriptionRepository.UpdateAsync(existingEntity, cancellationToken: cancellationToken);
//await unitOfWork.SaveChangesAsync();
}
public virtual async Task<string> CreateEvent(
Event newEvent,
CancellationToken cancellationToken = default)
{
//using var unitOfWork = _unitOfWorkManager.Begin();
var we = newEvent.ToPersistable(_guidGenerator, _currentTenant);
await _workflowEventRepository.InsertAsync(we, cancellationToken: cancellationToken);
//await unitOfWork.SaveChangesAsync();
newEvent.Id = we.Id.ToString();
return newEvent.Id;
@ -86,10 +98,14 @@ namespace LINGYUN.Abp.WorkflowCore.Persistence
EventSubscription subscription,
CancellationToken cancellationToken = default)
{
//using var unitOfWork = _unitOfWorkManager.Begin();
var wes = subscription.ToPersistable(_guidGenerator, _currentTenant);
await _subscriptionRepository.InsertAsync(wes, cancellationToken: cancellationToken);
//await unitOfWork.SaveChangesAsync();
subscription.Id = wes.Id.ToString();
return subscription.Id;
@ -99,21 +115,25 @@ namespace LINGYUN.Abp.WorkflowCore.Persistence
WorkflowInstance workflow,
CancellationToken cancellationToken = default)
{
//using var unitOfWork = _unitOfWorkManager.Begin();
var wf = workflow.ToPersistable(_guidGenerator, _currentTenant);
await _workflowRepository.InsertAsync(wf, cancellationToken: cancellationToken);
//await unitOfWork.SaveChangesAsync();
workflow.Id = wf.Id.ToString();
return workflow.Id;
}
[UnitOfWork(IsDisabled = true)]
public void EnsureStoreExists()
{
// TODO:
}
//[UnitOfWork]
public virtual async Task<Event> GetEvent(string id, CancellationToken cancellationToken = default)
{
var eventId = Guid.Parse(id);
@ -123,6 +143,7 @@ namespace LINGYUN.Abp.WorkflowCore.Persistence
return workflowEvent.ToEvent();
}
//[UnitOfWork]
public virtual async Task<IEnumerable<string>> GetEvents(
string eventName,
string eventKey,
@ -139,6 +160,7 @@ namespace LINGYUN.Abp.WorkflowCore.Persistence
return workflowEventIds.Select(e => e.ToString());
}
//[UnitOfWork]
public virtual async Task<EventSubscription> GetFirstOpenSubscription(
string eventName,
string eventKey,
@ -153,6 +175,7 @@ namespace LINGYUN.Abp.WorkflowCore.Persistence
return workflowEventSubscription?.ToEventSubscription();
}
//[UnitOfWork]
public virtual async Task<IEnumerable<string>> GetRunnableEvents(
DateTime asAt,
CancellationToken cancellationToken = default)
@ -170,6 +193,7 @@ namespace LINGYUN.Abp.WorkflowCore.Persistence
return workflowEventIdList.Select(e => e.ToString());
}
//[UnitOfWork]
public virtual async Task<IEnumerable<string>> GetRunnableInstances(
DateTime asAt,
CancellationToken cancellationToken = default)
@ -185,6 +209,7 @@ namespace LINGYUN.Abp.WorkflowCore.Persistence
return workflowIdList.Select(e => e.ToString());
}
//[UnitOfWork]
public virtual async Task<EventSubscription> GetSubscription(
string eventSubscriptionId,
CancellationToken cancellationToken = default)
@ -195,6 +220,7 @@ namespace LINGYUN.Abp.WorkflowCore.Persistence
return subscription?.ToEventSubscription();
}
//[UnitOfWork]
public virtual async Task<IEnumerable<EventSubscription>> GetSubscriptions(
string eventName,
string eventKey,
@ -210,6 +236,7 @@ namespace LINGYUN.Abp.WorkflowCore.Persistence
return eventSubscriptions.Select(x => x.ToEventSubscription());
}
[UnitOfWork(true, IsolationLevel.ReadUncommitted)]
public virtual async Task<WorkflowInstance> GetWorkflowInstance(
string Id,
CancellationToken cancellationToken = default)
@ -223,6 +250,7 @@ namespace LINGYUN.Abp.WorkflowCore.Persistence
return workflow?.ToWorkflowInstance();
}
//[UnitOfWork]
public virtual async Task<IEnumerable<WorkflowInstance>> GetWorkflowInstances(
WorkflowStatus? status,
string type,
@ -236,6 +264,7 @@ namespace LINGYUN.Abp.WorkflowCore.Persistence
return workflows.Select(x => x.ToWorkflowInstance());
}
//[UnitOfWork]
public virtual async Task<IEnumerable<WorkflowInstance>> GetWorkflowInstances(
IEnumerable<string> ids,
CancellationToken cancellationToken = default)
@ -252,36 +281,50 @@ namespace LINGYUN.Abp.WorkflowCore.Persistence
public virtual async Task MarkEventProcessed(string id, CancellationToken cancellationToken = default)
{
//using var unitOfWork = _unitOfWorkManager.Begin();
var eventId = Guid.Parse(id);
var workflowEvent = await _workflowEventRepository.GetAsync(eventId, cancellationToken: cancellationToken);
workflowEvent.IsProcessed = true;
await _workflowEventRepository.UpdateAsync(workflowEvent, cancellationToken: cancellationToken);
//await unitOfWork.SaveChangesAsync(cancellationToken);
}
public virtual async Task MarkEventUnprocessed(string id, CancellationToken cancellationToken = default)
{
//using var unitOfWork = _unitOfWorkManager.Begin();
var eventId = Guid.Parse(id);
var workflowEvent = await _workflowEventRepository.GetAsync(eventId, cancellationToken: cancellationToken);
workflowEvent.IsProcessed = false;
await _workflowEventRepository.UpdateAsync(workflowEvent, cancellationToken: cancellationToken);
//await unitOfWork.SaveChangesAsync(cancellationToken);
}
public virtual async Task PersistErrors(IEnumerable<ExecutionError> errors, CancellationToken cancellationToken = default)
{
if (errors.Any())
{
//using var unitOfWork = _unitOfWorkManager.Begin();
var workflowExecutionErrors = errors.Select(x => x.ToPersistable(_currentTenant));
await _executionErrorRepository.InsertManyAsync(workflowExecutionErrors, cancellationToken: cancellationToken);
//await unitOfWork.SaveChangesAsync(cancellationToken);
}
}
public virtual async Task PersistWorkflow(WorkflowInstance workflow, CancellationToken cancellationToken = default)
{
//using var unitOfWork = _unitOfWorkManager.Begin();
if (!Guid.TryParse(workflow.Id, out Guid workflowId))
{
workflowId = _guidGenerator.Create();
@ -300,6 +343,8 @@ namespace LINGYUN.Abp.WorkflowCore.Persistence
await _workflowRepository.UpdateAsync(wf, cancellationToken: cancellationToken);
}
//await unitOfWork.SaveChangesAsync(cancellationToken);
}
public virtual async Task ProcessCommands(
@ -309,6 +354,8 @@ namespace LINGYUN.Abp.WorkflowCore.Persistence
{
try
{
//using var unitOfWork = _unitOfWorkManager.Begin();
var quertable = await _scheduledCommandRepository.GetQueryableAsync();
var commands = await _asyncQueryableExecuter.ToListAsync(
quertable.Where(x => x.ExecuteTime < asOf.UtcDateTime.Ticks),
@ -320,6 +367,8 @@ namespace LINGYUN.Abp.WorkflowCore.Persistence
}
await _scheduledCommandRepository.DeleteManyAsync(commands, cancellationToken: cancellationToken);
//await unitOfWork.SaveChangesAsync(cancellationToken);
}
catch(Exception ex)
{
@ -332,9 +381,13 @@ namespace LINGYUN.Abp.WorkflowCore.Persistence
{
if (!await _scheduledCommandRepository.CheckExistsAsync(command.CommandName, command.Data))
{
//using var unitOfWork = _unitOfWorkManager.Begin();
var workflowCommand = command.ToPersistable(_currentTenant);
await _scheduledCommandRepository.InsertAsync(workflowCommand);
//await unitOfWork.SaveChangesAsync();
}
}
@ -347,12 +400,16 @@ namespace LINGYUN.Abp.WorkflowCore.Persistence
{
var uid = Guid.Parse(eventSubscriptionId);
//using var unitOfWork = _unitOfWorkManager.Begin();
var existingEntity = await _subscriptionRepository.GetAsync(uid, cancellationToken: cancellationToken);
existingEntity.SetSubscriptionToken(token, workerId, expiry);
await _subscriptionRepository.UpdateAsync(existingEntity, cancellationToken: cancellationToken);
//await unitOfWork.SaveChangesAsync(cancellationToken);
return true;
}
@ -362,9 +419,13 @@ namespace LINGYUN.Abp.WorkflowCore.Persistence
{
var uid = Guid.Parse(eventSubscriptionId);
//using var unitOfWork = _unitOfWorkManager.Begin();
var existingEntity = await _subscriptionRepository.GetAsync(uid, cancellationToken: cancellationToken);
await _subscriptionRepository.DeleteAsync(existingEntity, cancellationToken: cancellationToken);
//await unitOfWork.SaveChangesAsync(cancellationToken);
}
}
}

9
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.RabbitMQ/LINGYUN/Abp/WorkflowCore/RabbitMQ/AbpRabbitMqQueueProvider.cs

@ -6,13 +6,15 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.DependencyInjection;
using Volo.Abp.RabbitMQ;
using Volo.Abp.Threading;
using WorkflowCore.Interface;
namespace LINGYUN.Abp.WorkflowCore.RabbitMQ
{
public class AbpRabbitMqQueueProvider : IQueueProvider
[Dependency(ReplaceServices = true)]
public class AbpRabbitMqQueueProvider : IQueueAdapterProvider, ISingletonDependency
{
protected bool IsDiposed { get; private set; }
protected SemaphoreSlim SyncObj = new SemaphoreSlim(1, 1);
@ -61,6 +63,11 @@ namespace LINGYUN.Abp.WorkflowCore.RabbitMQ
}
public async Task QueueWork(string id, QueueType queue)
{
await QueueWorkAsync(id, queue);
}
protected virtual async Task QueueWorkAsync(string id, QueueType queue)
{
CheckDisposed();

25
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.RabbitMQ/LINGYUN/Abp/WorkflowCore/RabbitMQ/AbpWorkflowCoreRabbitMQModule.cs

@ -1,32 +1,13 @@
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp;
using Volo.Abp.Modularity;
using Volo.Abp.Modularity;
using Volo.Abp.RabbitMQ;
using WorkflowCore.Interface;
using WorkflowCore.Models;
using Volo.Abp.Uow;
namespace LINGYUN.Abp.WorkflowCore.RabbitMQ
{
[DependsOn(typeof(AbpUnitOfWorkModule))]
[DependsOn(typeof(AbpRabbitMqModule))]
[DependsOn(typeof(AbpWorkflowCoreModule))]
public class AbpWorkflowCoreRabbitMQModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddSingleton<IQueueProvider, AbpRabbitMqQueueProvider>();
context.Services.AddSingleton<AbpRabbitMqQueueProvider>();
PreConfigure<WorkflowOptions>(options =>
{
options.UseQueueProvider(provider => provider.GetRequiredService<AbpRabbitMqQueueProvider>());
});
}
public override void OnApplicationShutdown(ApplicationShutdownContext context)
{
context.ServiceProvider
.GetRequiredService<AbpRabbitMqQueueProvider>()
.Dispose();
}
}
}

67
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/AbpUnitOfWorkQueueProvider.cs

@ -0,0 +1,67 @@
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Uow;
using WorkflowCore.Interface;
namespace LINGYUN.Abp.WorkflowCore
{
/// <summary>
/// 当触发新的工作流时,如果持久层在事务中会导致默认队列获取工作流实例失败
/// 建立一个事务适配队列在工作单元结束时再将消息入队
/// </summary>
public class AbpUnitOfWorkQueueProvider : IQueueProvider
{
private readonly IUnitOfWorkManager _unitOfWorkManager;
private readonly IQueueAdapterProvider _queueProvider;
public AbpUnitOfWorkQueueProvider(
IQueueAdapterProvider queueProvider,
IUnitOfWorkManager unitOfWorkManager)
{
_queueProvider = queueProvider;
_unitOfWorkManager = unitOfWorkManager;
}
public bool IsDequeueBlocking => _queueProvider.IsDequeueBlocking;
public virtual async Task<string> DequeueWork(QueueType queue, CancellationToken cancellationToken)
{
if (_unitOfWorkManager.Current != null && !_unitOfWorkManager.Current.IsCompleted)
{
return null;
}
return await _queueProvider.DequeueWork(queue, cancellationToken);
}
public void Dispose()
{
_queueProvider.Dispose();
}
public async Task QueueWork(string id, QueueType queue)
{
if (_unitOfWorkManager.Current != null)
{
_unitOfWorkManager.Current.OnCompleted(async () =>
{
await _queueProvider.QueueWork(id, queue);
});
}
else
{
await _queueProvider.QueueWork(id, queue);
}
}
public async Task Start()
{
await _queueProvider.Start();
}
public async Task Stop()
{
await _queueProvider.Stop();
}
}
}

11
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/AbpWorkflowCoreModule.cs

@ -2,13 +2,12 @@
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Volo.Abp;
using Volo.Abp.Modularity;
using Volo.Abp.Threading;
using Volo.Abp.Timing;
using WorkflowCore.Interface;
using WorkflowCore.Models;
namespace LINGYUN.Abp.WorkflowCore
{
@ -23,6 +22,14 @@ namespace LINGYUN.Abp.WorkflowCore
{
context.Services.AddConventionalRegistrar(new AbpWorkflowCoreConventionalRegistrar());
context.Services.AddSingleton<IQueueProvider, AbpUnitOfWorkQueueProvider>();
context.Services.AddSingleton<AbpUnitOfWorkQueueProvider>();
PreConfigure<WorkflowOptions>(options =>
{
options.UseQueueProvider(provider => provider.GetRequiredService<AbpUnitOfWorkQueueProvider>());
});
AutoAddDefinitionWorkflows(context.Services);
}

20
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/IQueueAdapterProvider.cs

@ -0,0 +1,20 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using WorkflowCore.Interface;
namespace LINGYUN.Abp.WorkflowCore
{
public interface IQueueAdapterProvider : IDisposable
{
bool IsDequeueBlocking { get; }
Task QueueWork(string id, QueueType queue);
Task<string> DequeueWork(QueueType queue, CancellationToken cancellationToken);
Task Start();
Task Stop();
}
}

50
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/SingleNodeQueueAdapterProvider.cs

@ -0,0 +1,50 @@
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using WorkflowCore.Interface;
using Volo.Abp.DependencyInjection;
namespace LINGYUN.Abp.WorkflowCore
{
[Dependency(TryRegister = true)]
public class SingleNodeQueueAdapterProvider : IQueueAdapterProvider, ISingletonDependency
{
private readonly Dictionary<QueueType, BlockingCollection<string>> _queues = new Dictionary<QueueType, BlockingCollection<string>>
{
[QueueType.Workflow] = new BlockingCollection<string>(),
[QueueType.Event] = new BlockingCollection<string>(),
[QueueType.Index] = new BlockingCollection<string>()
};
public bool IsDequeueBlocking => true;
public Task QueueWork(string id, QueueType queue)
{
_queues[queue].Add(id);
return Task.CompletedTask;
}
public Task<string> DequeueWork(QueueType queue, CancellationToken cancellationToken)
{
if (_queues[queue].TryTake(out string id, 100, cancellationToken))
return Task.FromResult(id);
return Task.FromResult<string>(null);
}
public Task Start()
{
return Task.CompletedTask;
}
public Task Stop()
{
return Task.CompletedTask;
}
public void Dispose()
{
}
}
}

13
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Activitys/Dto/ActivityFailureInput.cs

@ -0,0 +1,13 @@
using System.ComponentModel.DataAnnotations;
namespace LINGYUN.Abp.WorkflowManagement.Activitys
{
public class ActivityFailureInput
{
[Required]
public string Token { get; set; }
[Required]
public object Result { get; set; }
}
}

7
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Activitys/Dto/ActivityReleaseInput.cs

@ -0,0 +1,7 @@
namespace LINGYUN.Abp.WorkflowManagement.Activitys
{
public class ActivityReleaseInput
{
public string Token { get; set; }
}
}

13
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Activitys/Dto/ActivitySuccessInput.cs

@ -0,0 +1,13 @@
using System.ComponentModel.DataAnnotations;
namespace LINGYUN.Abp.WorkflowManagement.Activitys
{
public class ActivitySuccessInput
{
[Required]
public string Token { get; set; }
[Required]
public object Result { get; set; }
}
}

13
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Activitys/Dto/GetPendingActivityInput.cs

@ -0,0 +1,13 @@
using System;
namespace LINGYUN.Abp.WorkflowManagement.Activitys
{
public class GetPendingActivityInput
{
public string ActivityName { get; set; }
public string WorkflowId { get; set; }
public TimeSpan? Timeout { get; set; }
}
}

15
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Activitys/Dto/PendingActivityDto.cs

@ -0,0 +1,15 @@
using System;
namespace LINGYUN.Abp.WorkflowManagement.Activitys
{
public class PendingActivityDto
{
public string Token { get; set; }
public string ActivityName { get; set; }
public object Parameters { get; set; }
public DateTime TokenExpiry { get; set; }
}
}

16
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Activitys/IActivityAppService.cs

@ -0,0 +1,16 @@
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
namespace LINGYUN.Abp.WorkflowManagement.Activitys
{
public interface IActivityAppService : IApplicationService
{
Task<PendingActivityDto> GetAsync(GetPendingActivityInput input);
Task DeleteAsync(ActivityReleaseInput input);
Task SuccessAsync(ActivitySuccessInput input);
Task FailureAsync(ActivityFailureInput input);
}
}

19
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Events/Dto/EventPublishInput.cs

@ -0,0 +1,19 @@
using System;
using System.ComponentModel.DataAnnotations;
namespace LINGYUN.Abp.WorkflowManagement.Events
{
public class EventPublishInput
{
[Required]
public string EventName { get; set; }
[Required]
public string EventKey { get; set; }
[Required]
public object EventData { get; set; }
public DateTime? EffectiveDate { get; set; }
}
}

10
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Events/IEventAppService.cs

@ -0,0 +1,10 @@
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
namespace LINGYUN.Abp.WorkflowManagement.Events
{
public interface IEventAppService : IApplicationService
{
Task PublishAsync(EventPublishInput input);
}
}

20
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Workflows/Dto/StepDto.cs

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using Volo.Abp.Data;
namespace LINGYUN.Abp.WorkflowManagement.Workflows
{
public class StepDto
{
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 string NextStep { get; set; }
public List<StepDto> CompensateWith { get; set; } = new List<StepDto>();
public ExtraPropertyDictionary Inputs { get; set; } = new ExtraPropertyDictionary();
public ExtraPropertyDictionary Outputs { get; set; } = new ExtraPropertyDictionary();
public ExtraPropertyDictionary SelectNextStep { get; set; } = new ExtraPropertyDictionary();
}
}

30
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Workflows/Dto/WorkflowCreateDto.cs

@ -0,0 +1,30 @@
using System.Collections.Generic;
namespace LINGYUN.Abp.WorkflowManagement.Workflows
{
public class WorkflowCreateDto
{
/// <summary>
/// 是否启用
/// </summary>
public bool IsEnabled { get; set; }
/// <summary>
/// 名称
/// </summary>
public string Name { get; set; }
/// <summary>
/// 显示名称
/// </summary>
public string DisplayName { get; set; }
/// <summary>
/// 描述
/// </summary>
public string Description { get; set; }
/// <summary>
/// 版本号
/// </summary>
public int Version { get; set; }
public List<StepDto> Steps { get; set; } = new List<StepDto>();
}
}

18
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Workflows/Dto/WorkflowDefinitionDto.cs

@ -0,0 +1,18 @@
using System.Collections.Generic;
namespace LINGYUN.Abp.WorkflowManagement.Workflows
{
public class WorkflowDefinitionDto
{
/// <summary>
/// 描述
/// </summary>
public string Description { get; set; }
/// <summary>
/// 版本号
/// </summary>
public int Version { get; set; }
public List<StepDto> Steps { get; set; } = new List<StepDto>();
}
}

16
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Workflows/Dto/WorkflowDto.cs

@ -0,0 +1,16 @@
using System;
namespace LINGYUN.Abp.WorkflowManagement.Workflows
{
public class WorkflowDto
{
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; }
}
}

9
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Workflows/Dto/WorkflowStartInput.cs

@ -0,0 +1,9 @@
using System.Collections.Generic;
namespace LINGYUN.Abp.WorkflowManagement.Workflows
{
public class WorkflowStartInput
{
public Dictionary<string, object> Data { get; set; }
}
}

20
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Workflows/IWorkflowAppService.cs

@ -0,0 +1,20 @@
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
namespace LINGYUN.Abp.WorkflowManagement.Workflows
{
public interface IWorkflowAppService : IApplicationService
{
Task<WorkflowDto> GetAsync(string id);
Task CreateAsync(WorkflowCreateDto input);
Task<WorkflowDto> StartAsync(string id, WorkflowStartInput input);
Task SuspendAsync(string id);
Task ResumeAsync(string id);
Task TerminateAsync(string id);
}
}

40
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application/LINGYUN/Abp/WorkflowManagement/Activitys/ActivityAppService.cs

@ -0,0 +1,40 @@
using Microsoft.AspNetCore.Authorization;
using System.Threading.Tasks;
using WorkflowCore.Interface;
namespace LINGYUN.Abp.WorkflowManagement.Activitys
{
[Authorize]
public class ActivityAppService : WorkflowManagementAppServiceBase, IActivityAppService
{
private readonly IActivityController _controller;
public ActivityAppService(IActivityController controller)
{
_controller = controller;
}
public virtual async Task FailureAsync(ActivityFailureInput input)
{
await _controller.SubmitActivityFailure(input.Token, input.Result);
}
public virtual async Task<PendingActivityDto> GetAsync(GetPendingActivityInput input)
{
var activity = await _controller.GetPendingActivity(
input.ActivityName, input.WorkflowId, input.Timeout);
return ObjectMapper.Map<PendingActivity, PendingActivityDto>(activity);
}
public virtual async Task DeleteAsync(ActivityReleaseInput input)
{
await _controller.ReleaseActivityToken(input.Token);
}
public virtual async Task SuccessAsync(ActivitySuccessInput input)
{
await _controller.SubmitActivitySuccess(input.Token, input.Result);
}
}
}

22
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application/LINGYUN/Abp/WorkflowManagement/Events/EventAppService.cs

@ -0,0 +1,22 @@
using Microsoft.AspNetCore.Authorization;
using System.Threading.Tasks;
using WorkflowCore.Interface;
namespace LINGYUN.Abp.WorkflowManagement.Events
{
[Authorize]
public class EventAppService : WorkflowManagementAppServiceBase, IEventAppService
{
private readonly IWorkflowController _controller;
public EventAppService(IWorkflowController controller)
{
_controller = controller;
}
public virtual async Task PublishAsync(EventPublishInput input)
{
await _controller.PublishEvent(input.EventName, input.EventKey, input.EventData, input.EffectiveDate);
}
}
}

10
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application/LINGYUN/Abp/WorkflowManagement/WorkflowManagementApplicationMapperProfile.cs

@ -1,4 +1,8 @@
using AutoMapper;
using LINGYUN.Abp.WorkflowManagement.Activitys;
using LINGYUN.Abp.WorkflowManagement.Workflows;
using WorkflowCore.Interface;
using WorkflowCore.Models;
namespace LINGYUN.Abp.WorkflowManagement
{
@ -6,6 +10,12 @@ namespace LINGYUN.Abp.WorkflowManagement
{
public WorkflowManagementApplicationMapperProfile()
{
CreateMap<WorkflowInstance, WorkflowDto>()
.ForMember(dto => dto.WorkflowId, map => map.MapFrom(src => src.Id.ToString()))
.ForMember(dto => dto.DefinitionId, map => map.MapFrom(src => src.Id.ToString()))
.ForMember(dto => dto.StartTime, map => map.MapFrom(src => src.CreateTime))
.ForMember(dto => dto.EndTime, map => map.MapFrom(src => src.CompleteTime));
CreateMap<PendingActivity, PendingActivityDto>();
}
}
}

165
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application/LINGYUN/Abp/WorkflowManagement/Workflows/WorkflowAppService.cs

@ -0,0 +1,165 @@
using Newtonsoft.Json;
using System.Collections.Generic;
using System.Text.Json;
using System.Threading.Tasks;
using Volo.Abp;
using WorkflowCore.Interface;
using WorkflowCore.Models;
namespace LINGYUN.Abp.WorkflowManagement.Workflows
{
//[Authorize]
public class WorkflowAppService : WorkflowManagementAppServiceBase, IWorkflowAppService
{
private readonly WorkflowManager _workflowManager;
private readonly IWorkflowController _controller;
private readonly IPersistenceProvider _persistence;
private readonly IWorkflowRepository _workflowRepository;
private readonly IStepNodeRepository _stepNodeRepository;
private readonly ICompensateNodeRepository _compensateNodeRepository;
public WorkflowAppService(
IWorkflowController controller,
IPersistenceProvider persistence,
WorkflowManager workflowManager,
IWorkflowRepository workflowRepository,
IStepNodeRepository stepNodeRepository,
ICompensateNodeRepository compensateNodeRepository)
{
_controller = controller;
_persistence = persistence;
_workflowManager = workflowManager;
_workflowRepository = workflowRepository;
_stepNodeRepository = stepNodeRepository;
_compensateNodeRepository = compensateNodeRepository;
}
public virtual async Task<WorkflowDto> GetAsync(string id)
{
var workflow = await _persistence.GetWorkflowInstance(id);
return ObjectMapper.Map<WorkflowInstance, WorkflowDto>(workflow);
}
public virtual async Task ResumeAsync(string id)
{
var result = await _controller.ResumeWorkflow(id);
if (!result)
{
throw new BusinessException();
}
}
public virtual async Task CreateAsync(WorkflowCreateDto input)
{
if (await _workflowRepository.CheckVersionAsync(input.Name, input.Version))
{
throw new BusinessException();
}
var workflow = new Workflow(
GuidGenerator.Create(),
input.Name,
input.Description,
input.Description,
input.Version,
tenantId: CurrentTenant.Id);
var stepNodes = new List<StepNode>();
var stepCompensateNodes = 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(),
workflow.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(),
workflow.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);
stepNodes.Add(stepNode);
stepCompensateNodes.AddRange(CreateCompensateNodes(stepNode, stepInput.CompensateWith));
}
await _workflowRepository.InsertAsync(workflow);
await _stepNodeRepository.InsertManyAsync(stepNodes);
await _compensateNodeRepository.InsertManyAsync(stepCompensateNodes);
_workflowManager.Register(workflow, stepNodes, stepCompensateNodes);
}
public virtual async Task<WorkflowDto> StartAsync(string id, WorkflowStartInput input)
{
var workflowData = new Dictionary<string, object>();
foreach (var data in input.Data)
{
if (data.Value is JsonElement element)
{
//var dataDic = new Dictionary<string, object>();
//var children = element.EnumerateObject();
//while (children.MoveNext())
//{
// dataDic.TryAdd(children.Current.Name, children.Current.Value.ToString());
//}
//JsonConvert.DeserializeObject(element.ToString())
workflowData.TryAdd(data.Key, JsonConvert.DeserializeObject(element.ToString()));
}
else
{
workflowData.TryAdd(data.Key, data.Value);
}
}
var instanceId = await _controller.StartWorkflow(id, workflowData);
var result = await _persistence.GetWorkflowInstance(instanceId);
return ObjectMapper.Map<WorkflowInstance, WorkflowDto>(result);
}
public virtual async Task SuspendAsync(string id)
{
var result = await _controller.SuspendWorkflow(id);
if (!result)
{
throw new BusinessException();
}
}
public virtual async Task TerminateAsync(string id)
{
var result = await _controller.TerminateWorkflow(id);
if (!result)
{
throw new BusinessException();
}
}
}
}

11
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain.Shared/LINGYUN/Abp/WorkflowManagement/WorkflowConsts.cs

@ -0,0 +1,11 @@
namespace LINGYUN.Abp.WorkflowManagement
{
public static class WorkflowConsts
{
public static int MaxCancelConditionLength { get; set; } = 200;
public static int MaxNameLength { get; set; } = 100;
public static int MaxDisplayNameLength { get; set; } = 200;
public static int MaxDescriptionLength { get; set; } = 200;
public static int MaxStepTypeLength { get; set; } = 100;
}
}

27
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/CompensateNode.cs

@ -0,0 +1,27 @@
using System;
using WorkflowCore.Models;
namespace LINGYUN.Abp.WorkflowManagement
{
public class CompensateNode : Step
{
public CompensateNode()
{
}
public CompensateNode(
Guid id,
Guid workflowId,
string name,
string stepType,
string cancelCondition,
WorkflowErrorHandling? errorBehavior = null,
TimeSpan? retryInterval = null,
bool saga = false,
Guid? parentId = null,
Guid? tenantId = null)
: base(id, workflowId, name, stepType, cancelCondition, errorBehavior, retryInterval, saga, parentId, tenantId)
{
}
}
}

15
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/ICompensateNodeRepository.cs

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
namespace LINGYUN.Abp.WorkflowManagement
{
public interface ICompensateNodeRepository : IRepository<CompensateNode, Guid>
{
Task<List<CompensateNode>> GetAllChildrenWithWorkflowAsync(
Guid workflowId,
CancellationToken cancellationToken = default);
}
}

21
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/IStep.cs

@ -0,0 +1,21 @@
using System;
using Volo.Abp.Data;
using WorkflowCore.Models;
namespace LINGYUN.Abp.WorkflowManagement
{
public interface IStep
{
Guid WorkflowId { get; }
string Name { get; }
string StepType { get; }
Guid? ParentId { get; }
WorkflowErrorHandling? ErrorBehavior { get; }
string CancelCondition { get; set; }
TimeSpan? RetryInterval { get; set; }
bool Saga { get; set; }
ExtraPropertyDictionary Inputs { get; set; }
ExtraPropertyDictionary Outputs { get; set; }
ExtraPropertyDictionary SelectNextStep { get; set; }
}
}

15
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/IStepNodeRepository.cs

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
namespace LINGYUN.Abp.WorkflowManagement
{
public interface IStepNodeRepository : IRepository<StepNode, Guid>
{
Task<List<StepNode>> GetAllChildrenWithWorkflowAsync(
Guid workflowId,
CancellationToken cancellationToken = default);
}
}

15
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/IWorkflowRepository.cs

@ -0,0 +1,15 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories;
namespace LINGYUN.Abp.WorkflowManagement
{
public interface IWorkflowRepository : IRepository<Workflow, Guid>
{
Task<bool> CheckVersionAsync(
string name,
int version,
CancellationToken cancellationToken = default);
}
}

14
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/Step.cs

@ -6,7 +6,7 @@ using WorkflowCore.Models;
namespace LINGYUN.Abp.WorkflowManagement
{
public class Step : Entity<Guid>, IMultiTenant
public abstract class Step : Entity<Guid>, IMultiTenant
{
public virtual Guid? TenantId { get; protected set; }
public virtual Guid WorkflowId { get; protected set; }
@ -14,9 +14,9 @@ namespace LINGYUN.Abp.WorkflowManagement
public virtual string StepType { get; protected set; }
public virtual string CancelCondition { get; set; }
public virtual WorkflowErrorHandling? ErrorBehavior { get; protected set; }
public virtual int? RetryInterval { get; set; }
public virtual TimeSpan? RetryInterval { get; set; }
public virtual bool Saga { get; set; }
public virtual Guid? NextStep { get; protected set; }
public virtual Guid? ParentId { get; protected set; }
public virtual ExtraPropertyDictionary Inputs { get; set; }
public virtual ExtraPropertyDictionary Outputs { get; set; }
public virtual ExtraPropertyDictionary SelectNextStep { get; set; }
@ -27,16 +27,16 @@ namespace LINGYUN.Abp.WorkflowManagement
SelectNextStep = new ExtraPropertyDictionary();
}
public Step(
protected Step(
Guid id,
Guid workflowId,
string name,
string stepType,
string cancelCondition,
WorkflowErrorHandling? errorBehavior = null,
int? retryInterval = null,
TimeSpan? retryInterval = null,
bool saga = false,
Guid? nextStep = null,
Guid? parentId = null,
Guid? tenantId = null) : base(id)
{
Name = name;
@ -46,7 +46,7 @@ namespace LINGYUN.Abp.WorkflowManagement
ErrorBehavior = errorBehavior;
RetryInterval = retryInterval;
Saga = saga;
NextStep = nextStep;
ParentId = parentId;
TenantId = tenantId;
Inputs = new ExtraPropertyDictionary();

27
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/StepNode.cs

@ -0,0 +1,27 @@
using System;
using WorkflowCore.Models;
namespace LINGYUN.Abp.WorkflowManagement
{
public class StepNode : Step
{
protected StepNode()
{
}
public StepNode(
Guid id,
Guid workflowId,
string name,
string stepType,
string cancelCondition,
WorkflowErrorHandling? errorBehavior = null,
TimeSpan? retryInterval = null,
bool saga = false,
Guid? parentId = null,
Guid? tenantId = null)
: base(id, workflowId, name, stepType, cancelCondition, errorBehavior, retryInterval, saga, parentId, tenantId)
{
}
}
}

22
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/Workflow.cs

@ -1,6 +1,7 @@
using System;
using Volo.Abp.Domain.Entities.Auditing;
using Volo.Abp.MultiTenancy;
using WorkflowCore.Models;
namespace LINGYUN.Abp.WorkflowManagement
{
@ -18,6 +19,10 @@ namespace LINGYUN.Abp.WorkflowManagement
/// </summary>
public virtual bool IsEnabled { get; protected set; }
/// <summary>
/// 名称
/// </summary>
public virtual string Name { get; set; }
/// <summary>
/// 显示名称
/// </summary>
public virtual string DisplayName { get; set; }
@ -30,16 +35,31 @@ namespace LINGYUN.Abp.WorkflowManagement
/// </summary>
public virtual int Version { get; protected set; }
public virtual WorkflowErrorHandling ErrorBehavior { get; set; }
public virtual TimeSpan? ErrorRetryInterval { get; set; }
protected Workflow()
{
}
public Workflow(
Guid id,
string name,
string displayName,
string description = "",
int version = 1) : base(id)
int version = 1,
WorkflowErrorHandling errorBehavior = WorkflowErrorHandling.Retry,
TimeSpan? errorRetryInterval = null,
Guid? tenantId = null) : base(id)
{
Name = name;
DisplayName = displayName;
Description = description;
Version = version;
ErrorBehavior = errorBehavior;
ErrorRetryInterval = errorRetryInterval;
TenantId = tenantId;
}
}
}

2
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/WorkflowManagementDbProperties.cs

@ -2,7 +2,7 @@
{
public static class WorkflowManagementDbProperties
{
public static string DbTablePrefix { get; set; } = "WorkflowManagement_";
public static string DbTablePrefix { get; set; } = "WF_";
public static string DbSchema { get; set; } = null;

3
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/WorkflowManagementDomainModule.cs

@ -21,7 +21,10 @@ namespace LINGYUN.Abp.WorkflowManagement
Configure<AbpDistributedEntityEventOptions>(options =>
{
});
context.Services.AddHostedService<WorkflowRegisterService>();
}
}
}

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

@ -0,0 +1,530 @@
using Newtonsoft.Json.Linq;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Linq.Expressions;
using System.Reflection;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Domain.Services;
using WorkflowCore.Exceptions;
using WorkflowCore.Interface;
using WorkflowCore.Models;
using WorkflowCore.Models.DefinitionStorage.v1;
using WorkflowCore.Primitives;
namespace LINGYUN.Abp.WorkflowManagement
{
public class WorkflowManager : DomainService, ITransientDependency
{
private readonly IWorkflowRegistry _registry;
private readonly IPersistenceProvider _persistenceProvider;
public WorkflowManager(
IWorkflowRegistry registry,
IPersistenceProvider persistenceProvider)
{
_registry = registry;
_persistenceProvider = persistenceProvider;
}
public virtual WorkflowDefinition Register(
Workflow workflow,
ICollection<StepNode> steps,
ICollection<CompensateNode> compensates)
{
var dataType = typeof(Dictionary<string, object>);
var source = new DefinitionSourceV1
{
Id = workflow.Id.ToString(),
Version = workflow.Version,
Description = workflow.Description ?? workflow.DisplayName,
DataType = $"{dataType.FullName}, {dataType.Assembly}",
DefaultErrorBehavior = workflow.ErrorBehavior,
DefaultErrorRetryInterval = workflow.ErrorRetryInterval,
Steps = ConvertSteps(steps, compensates)
};
var def = Convert(source);
_registry.RegisterWorkflow(def);
return def;
}
private List<StepSourceV1> ConvertSteps(
ICollection<StepNode> steps,
ICollection<CompensateNode> compensates)
{
var nodes = new List<StepSourceV1>();
foreach (var step in steps)
{
var source = new StepSourceV1
{
Id = step.Id.ToString(),
Saga = step.Saga,
StepType = step.StepType,
CancelCondition = step.CancelCondition,
ErrorBehavior = step.ErrorBehavior,
RetryInterval = step.RetryInterval,
Name = step.Name
};
foreach (var input in step.Inputs)
{
source.Inputs.AddIfNotContains(input);
}
foreach (var output in step.Outputs)
{
source.Outputs.Add(output.Key, output.Value.ToString());
}
foreach (var nextStep in step.SelectNextStep)
{
source.SelectNextStep.Add(nextStep.Key, nextStep.Value.ToString());
}
var childrenNodes = steps.Where(x => Equals(x.ParentId, step.Id)).ToArray();
if (childrenNodes.Any())
{
source.NextStepId = childrenNodes[0].Id.ToString();
nodes.AddRange(ConvertSteps(childrenNodes, compensates));
}
var stepCps = compensates.Where(x => Equals(x.ParentId, step.Id)).ToArray();
if (stepCps.Any())
{
source.CompensateWith.AddRange(ConvertCompensateSteps(stepCps));
}
nodes.Add(source);
}
return nodes;
}
private List<StepSourceV1> ConvertCompensateSteps(
ICollection<CompensateNode> compensates)
{
var nodes = new List<StepSourceV1>();
foreach (var step in compensates)
{
var source = new StepSourceV1
{
Id = step.Id.ToString(),
Saga = step.Saga,
StepType = step.StepType,
CancelCondition = step.CancelCondition,
ErrorBehavior = step.ErrorBehavior,
RetryInterval = step.RetryInterval,
Name = step.Name
};
foreach (var input in step.Inputs)
{
source.Inputs.AddIfNotContains(input);
}
foreach (var output in step.Outputs)
{
source.Outputs.Add(output.Key, output.Value.ToString());
}
foreach (var nextStep in step.SelectNextStep)
{
source.SelectNextStep.Add(nextStep.Key, nextStep.Value.ToString());
}
var stepCps = compensates.Where(x => Equals(x.ParentId, step.Id)).ToArray();
if (stepCps.Any())
{
source.CompensateWith.AddRange(ConvertCompensateSteps(stepCps));
}
nodes.Add(source);
}
return nodes;
}
private WorkflowDefinition Convert(DefinitionSourceV1 source)
{
var dataType = typeof(object);
if (!string.IsNullOrEmpty(source.DataType))
dataType = FindType(source.DataType);
var result = new WorkflowDefinition
{
Id = source.Id,
Version = source.Version,
Steps = ConvertSteps(source.Steps, dataType),
DefaultErrorBehavior = source.DefaultErrorBehavior,
DefaultErrorRetryInterval = source.DefaultErrorRetryInterval,
Description = source.Description,
DataType = dataType
};
return result;
}
private WorkflowStepCollection ConvertSteps(ICollection<StepSourceV1> source, Type dataType)
{
var result = new WorkflowStepCollection();
int i = 0;
var stack = new Stack<StepSourceV1>(source.Reverse<StepSourceV1>());
var parents = new List<StepSourceV1>();
var compensatables = new List<StepSourceV1>();
while (stack.Count > 0)
{
var nextStep = stack.Pop();
var stepType = FindType(nextStep.StepType);
WorkflowStep targetStep;
Type containerType;
if (stepType.GetInterfaces().Contains(typeof(IStepBody)))
{
containerType = typeof(WorkflowStep<>).MakeGenericType(stepType);
targetStep = (containerType.GetConstructor(new Type[] { }).Invoke(null) as WorkflowStep);
}
else
{
targetStep = stepType.GetConstructor(new Type[] { }).Invoke(null) as WorkflowStep;
if (targetStep != null)
stepType = targetStep.BodyType;
}
if (nextStep.Saga)
{
containerType = typeof(SagaContainer<>).MakeGenericType(stepType);
targetStep = (containerType.GetConstructor(new Type[] { }).Invoke(null) as WorkflowStep);
}
if (!string.IsNullOrEmpty(nextStep.CancelCondition))
{
var cancelExprType = typeof(Expression<>).MakeGenericType(typeof(Func<,>).MakeGenericType(dataType, typeof(bool)));
var dataParameter = Expression.Parameter(dataType, "data");
var cancelExpr = DynamicExpressionParser.ParseLambda(new[] { dataParameter }, typeof(bool), nextStep.CancelCondition);
targetStep.CancelCondition = cancelExpr;
}
targetStep.Id = i;
targetStep.Name = nextStep.Name;
targetStep.ErrorBehavior = nextStep.ErrorBehavior;
targetStep.RetryInterval = nextStep.RetryInterval;
targetStep.ExternalId = $"{nextStep.Id}";
AttachInputs(nextStep, dataType, stepType, targetStep);
AttachOutputs(nextStep, dataType, stepType, targetStep);
if (nextStep.Do != null)
{
foreach (var branch in nextStep.Do)
{
foreach (var child in branch.Reverse<StepSourceV1>())
stack.Push(child);
}
if (nextStep.Do.Count > 0)
parents.Add(nextStep);
}
if (nextStep.CompensateWith != null)
{
foreach (var compChild in nextStep.CompensateWith.Reverse<StepSourceV1>())
stack.Push(compChild);
if (nextStep.CompensateWith.Count > 0)
compensatables.Add(nextStep);
}
AttachOutcomes(nextStep, dataType, targetStep);
result.Add(targetStep);
i++;
}
foreach (var step in result)
{
if (result.Any(x => x.ExternalId == step.ExternalId && x.Id != step.Id))
throw new WorkflowDefinitionLoadException($"Duplicate step Id {step.ExternalId}");
foreach (var outcome in step.Outcomes)
{
if (result.All(x => x.ExternalId != outcome.ExternalNextStepId))
throw new WorkflowDefinitionLoadException($"Cannot find step id {outcome.ExternalNextStepId}");
outcome.NextStep = result.Single(x => x.ExternalId == outcome.ExternalNextStepId).Id;
}
}
foreach (var parent in parents)
{
var target = result.Single(x => x.ExternalId == parent.Id);
foreach (var branch in parent.Do)
{
var childTags = branch.Select(x => x.Id).ToList();
target.Children.AddRange(result
.Where(x => childTags.Contains(x.ExternalId))
.OrderBy(x => x.Id)
.Select(x => x.Id)
.Take(1)
.ToList());
}
}
foreach (var item in compensatables)
{
var target = result.Single(x => x.ExternalId == item.Id);
var tag = item.CompensateWith.Select(x => x.Id).FirstOrDefault();
if (tag != null)
{
var compStep = result.FirstOrDefault(x => x.ExternalId == tag);
if (compStep != null)
target.CompensationStepId = compStep.Id;
}
}
return result;
}
private void AttachInputs(StepSourceV1 source, Type dataType, Type stepType, WorkflowStep step)
{
foreach (var input in source.Inputs)
{
var dataParameter = Expression.Parameter(dataType, "data");
var contextParameter = Expression.Parameter(typeof(IStepExecutionContext), "context");
var environmentVarsParameter = Expression.Parameter(typeof(IDictionary), "environment");
var stepProperty = stepType.GetProperty(input.Key);
if (stepProperty == null)
{
throw new ArgumentException($"Unknown property for input {input.Key} on {source.Id}");
}
if (input.Value is string)
{
var acn = BuildScalarInputAction(input, dataParameter, contextParameter, environmentVarsParameter, stepProperty);
step.Inputs.Add(new ActionParameter<IStepBody, object>(acn));
continue;
}
if ((input.Value is IDictionary<string, object>) || (input.Value is IDictionary<object, object>))
{
var acn = BuildObjectInputAction(input, dataParameter, contextParameter, environmentVarsParameter, stepProperty);
step.Inputs.Add(new ActionParameter<IStepBody, object>(acn));
continue;
}
throw new ArgumentException($"Unknown type for input {input.Key} on {source.Id}");
}
}
private void AttachOutputs(StepSourceV1 source, Type dataType, Type stepType, WorkflowStep step)
{
foreach (var output in source.Outputs)
{
var stepParameter = Expression.Parameter(stepType, "step");
var sourceExpr = DynamicExpressionParser.ParseLambda(new[] { stepParameter }, typeof(object), output.Value);
var dataParameter = Expression.Parameter(dataType, "data");
if (output.Key.Contains(".") || output.Key.Contains("["))
{
AttachNestedOutput(output, step, source, sourceExpr, dataParameter);
}
else
{
AttachDirectlyOutput(output, step, dataType, sourceExpr, dataParameter);
}
}
}
private void AttachDirectlyOutput(KeyValuePair<string, string> output, WorkflowStep step, Type dataType, LambdaExpression sourceExpr, ParameterExpression dataParameter)
{
Expression targetProperty;
// Check if our datatype has a matching property
var propertyInfo = dataType.GetProperty(output.Key);
if (propertyInfo != null)
{
targetProperty = Expression.Property(dataParameter, propertyInfo);
var targetExpr = Expression.Lambda(targetProperty, dataParameter);
step.Outputs.Add(new MemberMapParameter(sourceExpr, targetExpr));
}
else
{
// If we did not find a matching property try to find a Indexer with string parameter
propertyInfo = dataType.GetProperty("Item");
targetProperty = Expression.Property(dataParameter, propertyInfo, Expression.Constant(output.Key));
Action<IStepBody, object> acn = (pStep, pData) =>
{
object resolvedValue = sourceExpr.Compile().DynamicInvoke(pStep); ;
propertyInfo.SetValue(pData, resolvedValue, new object[] { output.Key });
};
step.Outputs.Add(new ActionParameter<IStepBody, object>(acn));
}
}
private void AttachNestedOutput(KeyValuePair<string, string> output, WorkflowStep step, StepSourceV1 source, LambdaExpression sourceExpr, ParameterExpression dataParameter)
{
PropertyInfo propertyInfo = null;
String[] paths = output.Key.Split('.');
Expression targetProperty = dataParameter;
bool hasAddOutput = false;
foreach (String propertyName in paths)
{
if (hasAddOutput)
{
throw new ArgumentException($"Unknown property for output {output.Key} on {source.Id}");
}
if (targetProperty == null)
{
break;
}
if (propertyName.Contains("["))
{
String[] items = propertyName.Split('[');
if (items.Length != 2)
{
throw new ArgumentException($"Unknown property for output {output.Key} on {source.Id}");
}
items[1] = items[1].Trim().TrimEnd(']').Trim().Trim('"');
MemberExpression memberExpression = Expression.Property(targetProperty, items[0]);
if (memberExpression == null)
{
throw new ArgumentException($"Unknown property for output {output.Key} on {source.Id}");
}
propertyInfo = ((PropertyInfo)memberExpression.Member).PropertyType.GetProperty("Item");
Action<IStepBody, object> acn = (pStep, pData) =>
{
var targetExpr = Expression.Lambda(memberExpression, dataParameter);
object data = targetExpr.Compile().DynamicInvoke(pData);
object resolvedValue = sourceExpr.Compile().DynamicInvoke(pStep); ;
propertyInfo.SetValue(data, resolvedValue, new object[] { items[1] });
};
step.Outputs.Add(new ActionParameter<IStepBody, object>(acn));
hasAddOutput = true;
}
else
{
try
{
targetProperty = Expression.Property(targetProperty, propertyName);
}
catch
{
targetProperty = null;
break;
}
}
}
if (targetProperty != null && !hasAddOutput)
{
var targetExpr = Expression.Lambda(targetProperty, dataParameter);
step.Outputs.Add(new MemberMapParameter(sourceExpr, targetExpr));
}
}
private void AttachOutcomes(StepSourceV1 source, Type dataType, WorkflowStep step)
{
if (!string.IsNullOrEmpty(source.NextStepId))
step.Outcomes.Add(new ValueOutcome { ExternalNextStepId = $"{source.NextStepId}" });
var dataParameter = Expression.Parameter(dataType, "data");
var outcomeParameter = Expression.Parameter(typeof(object), "outcome");
foreach (var nextStep in source.SelectNextStep)
{
var sourceDelegate = DynamicExpressionParser.ParseLambda(new[] { dataParameter, outcomeParameter }, typeof(object), nextStep.Value).Compile();
Expression<Func<object, object, bool>> sourceExpr = (data, outcome) => System.Convert.ToBoolean(sourceDelegate.DynamicInvoke(data, outcome));
step.Outcomes.Add(new ExpressionOutcome<object>(sourceExpr)
{
ExternalNextStepId = $"{nextStep.Key}"
});
}
}
private Type FindType(string name)
{
return Type.GetType(name, true, true);
}
private static Action<IStepBody, object, IStepExecutionContext> BuildScalarInputAction(KeyValuePair<string, object> input, ParameterExpression dataParameter, ParameterExpression contextParameter, ParameterExpression environmentVarsParameter, PropertyInfo stepProperty)
{
var expr = System.Convert.ToString(input.Value);
var sourceExpr = DynamicExpressionParser.ParseLambda(new[] { dataParameter, contextParameter, environmentVarsParameter }, typeof(object), expr);
void acn(IStepBody pStep, object pData, IStepExecutionContext pContext)
{
object resolvedValue = sourceExpr.Compile().DynamicInvoke(pData, pContext, Environment.GetEnvironmentVariables());
if (stepProperty.PropertyType.IsEnum)
stepProperty.SetValue(pStep, Enum.Parse(stepProperty.PropertyType, (string)resolvedValue, true));
else
{
if ((resolvedValue != null) && (stepProperty.PropertyType.IsAssignableFrom(resolvedValue.GetType())))
stepProperty.SetValue(pStep, resolvedValue);
else
stepProperty.SetValue(pStep, System.Convert.ChangeType(resolvedValue, stepProperty.PropertyType));
}
}
return acn;
}
private static Action<IStepBody, object, IStepExecutionContext> BuildObjectInputAction(KeyValuePair<string, object> input, ParameterExpression dataParameter, ParameterExpression contextParameter, ParameterExpression environmentVarsParameter, PropertyInfo stepProperty)
{
void acn(IStepBody pStep, object pData, IStepExecutionContext pContext)
{
var stack = new Stack<JObject>();
var destObj = JObject.FromObject(input.Value);
stack.Push(destObj);
while (stack.Count > 0)
{
var subobj = stack.Pop();
foreach (var prop in subobj.Properties().ToList())
{
if (prop.Name.StartsWith("@"))
{
var sourceExpr = DynamicExpressionParser.ParseLambda(new[] { dataParameter, contextParameter, environmentVarsParameter }, typeof(object), prop.Value.ToString());
object resolvedValue = sourceExpr.Compile().DynamicInvoke(pData, pContext, Environment.GetEnvironmentVariables());
subobj.Remove(prop.Name);
subobj.Add(prop.Name.TrimStart('@'), JToken.FromObject(resolvedValue));
}
}
foreach (var child in subobj.Children<JObject>())
stack.Push(child);
}
stepProperty.SetValue(pStep, destObj);
}
return acn;
}
}
}

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

@ -0,0 +1,40 @@
using Microsoft.Extensions.Hosting;
using System.Threading;
using System.Threading.Tasks;
namespace LINGYUN.Abp.WorkflowManagement
{
public class WorkflowRegisterService : BackgroundService
{
private readonly WorkflowManager _workflowManager;
private readonly IWorkflowRepository _workflowRepository;
private readonly IStepNodeRepository _stepNodeRepository;
private readonly ICompensateNodeRepository _compensateNodeRepository;
public WorkflowRegisterService(
WorkflowManager workflowManager,
IWorkflowRepository workflowRepository,
IStepNodeRepository stepNodeRepository,
ICompensateNodeRepository compensateNodeRepository)
{
_workflowManager = workflowManager;
_workflowRepository = workflowRepository;
_stepNodeRepository = stepNodeRepository;
_compensateNodeRepository = compensateNodeRepository;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
var workflows = await _workflowRepository.GetListAsync(cancellationToken: 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);
}
}
}
}

27
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore/LINGYUN/Abp/WorkflowManagement/EntityFrameworkCore/EfCoreCompensateNodeRepository.cs

@ -0,0 +1,27 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
namespace LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore
{
public class EfCoreCompensateNodeRepository : EfCoreRepository<WorkflowManagementDbContext, CompensateNode, Guid>, ICompensateNodeRepository
{
public EfCoreCompensateNodeRepository(
IDbContextProvider<WorkflowManagementDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
public virtual async Task<List<CompensateNode>> GetAllChildrenWithWorkflowAsync(Guid workflowId, CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync())
.Where(x => x.WorkflowId.Equals(workflowId))
.ToListAsync(GetCancellationToken(cancellationToken));
}
}
}

27
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore/LINGYUN/Abp/WorkflowManagement/EntityFrameworkCore/EfCoreStepNodeRepository.cs

@ -0,0 +1,27 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
namespace LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore
{
public class EfCoreStepNodeRepository : EfCoreRepository<WorkflowManagementDbContext, StepNode, Guid>, IStepNodeRepository
{
public EfCoreStepNodeRepository(
IDbContextProvider<WorkflowManagementDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
public virtual async Task<List<StepNode>> GetAllChildrenWithWorkflowAsync(Guid workflowId, CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync())
.Where(x => x.WorkflowId.Equals(workflowId))
.ToListAsync(GetCancellationToken(cancellationToken));
}
}
}

25
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore/LINGYUN/Abp/WorkflowManagement/EntityFrameworkCore/EfCoreWorkflowRepository.cs

@ -0,0 +1,25 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.Threading;
using System.Threading.Tasks;
using Volo.Abp.Domain.Repositories.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
namespace LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore
{
public class EfCoreWorkflowRepository : EfCoreRepository<WorkflowManagementDbContext, Workflow, Guid>, IWorkflowRepository
{
public EfCoreWorkflowRepository(
IDbContextProvider<WorkflowManagementDbContext> dbContextProvider)
: base(dbContextProvider)
{
}
public virtual async Task<bool> CheckVersionAsync(string name, int version, CancellationToken cancellationToken = default)
{
return await (await GetDbSetAsync())
.AnyAsync(x => x.Name.Equals(name) && x.Version == version,
GetCancellationToken(cancellationToken));
}
}
}

50
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore/LINGYUN/Abp/WorkflowManagement/EntityFrameworkCore/WorkflowManagementDbContextModelCreatingExtensions.cs

@ -1,6 +1,10 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using System;
using Volo.Abp;
using Volo.Abp.EntityFrameworkCore.Modeling;
using Volo.Abp.EntityFrameworkCore.ValueComparers;
using Volo.Abp.EntityFrameworkCore.ValueConverters;
namespace LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore
{
@ -17,6 +21,52 @@ namespace LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore
WorkflowManagementDbProperties.DbSchema
);
optionsAction?.Invoke(options);
builder.Entity<Workflow>(b =>
{
b.ToTable(options.TablePrefix + "Definition", options.Schema);
b.Property(p => p.DisplayName).HasMaxLength(WorkflowConsts.MaxDisplayNameLength);
b.Property(p => p.Name).HasMaxLength(WorkflowConsts.MaxNameLength).IsRequired();
b.Property(p => p.Description).HasMaxLength(WorkflowConsts.MaxDescriptionLength);
b.ConfigureByConvention();
});
builder.Entity<StepNode>(b =>
{
b.ToTable(options.TablePrefix + "Step", options.Schema);
b.ConfigureStep();
b.ConfigureByConvention();
});
builder.Entity<CompensateNode>(b =>
{
b.ToTable(options.TablePrefix + "Compensate", options.Schema);
b.ConfigureStep();
b.ConfigureByConvention();
});
}
public static void ConfigureStep<TStep>(
this EntityTypeBuilder<TStep> builder)
where TStep : Step
{
builder.Property(p => p.CancelCondition).HasMaxLength(WorkflowConsts.MaxCancelConditionLength);
builder.Property(p => p.Name).HasMaxLength(WorkflowConsts.MaxNameLength);
builder.Property(p => p.StepType).HasMaxLength(WorkflowConsts.MaxStepTypeLength);
builder.Property(p => p.Inputs)
.HasConversion(new ExtraPropertiesValueConverter(builder.Metadata.ClrType))
.Metadata.SetValueComparer(new ExtraPropertyDictionaryValueComparer());
builder.Property(p => p.Outputs)
.HasConversion(new ExtraPropertiesValueConverter(builder.Metadata.ClrType))
.Metadata.SetValueComparer(new ExtraPropertyDictionaryValueComparer());
builder.Property(p => p.SelectNextStep)
.HasConversion(new ExtraPropertiesValueConverter(builder.Metadata.ClrType))
.Metadata.SetValueComparer(new ExtraPropertyDictionaryValueComparer());
}
}
}

4
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore/LINGYUN/Abp/WorkflowManagement/EntityFrameworkCore/WorkflowManagementEntityFrameworkCoreModule.cs

@ -13,7 +13,9 @@ namespace LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore
{
context.Services.AddAbpDbContext<WorkflowManagementDbContext>(options =>
{
options.AddDefaultRepositories(includeAllEntities: true);
options.AddRepository<Workflow, EfCoreWorkflowRepository>();
options.AddRepository<StepNode, EfCoreStepNodeRepository>();
options.AddRepository<CompensateNode, EfCoreCompensateNodeRepository>();
});
}
}

44
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.HttpApi/LINGYUN/Abp/WorkflowManagement/Activitys/ActivityController.cs

@ -0,0 +1,44 @@
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.AspNetCore.Mvc;
namespace LINGYUN.Abp.WorkflowManagement.Activitys
{
[RemoteService(Name = WorkflowManagementRemoteServiceConsts.RemoteServiceName)]
[Area("WorkflowManagement")]
[Route("api/workflow-management/activitys")]
public class ActivityController : AbpControllerBase, IActivityAppService
{
private readonly IActivityAppService _service;
public ActivityController(IActivityAppService service)
{
_service = service;
}
[HttpPost("fail/{token}")]
public virtual async Task FailureAsync(ActivityFailureInput input)
{
await _service.FailureAsync(input);
}
[HttpGet("{ActivityName}")]
public virtual async Task<PendingActivityDto> GetAsync(GetPendingActivityInput input)
{
return await _service.GetAsync(input);
}
[HttpDelete("{Token}")]
public virtual async Task DeleteAsync(ActivityReleaseInput input)
{
await _service.DeleteAsync(input);
}
[HttpPost("success/{Token}")]
public virtual async Task SuccessAsync(ActivitySuccessInput input)
{
await _service.SuccessAsync(input);
}
}
}

27
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.HttpApi/LINGYUN/Abp/WorkflowManagement/Events/EventController.cs

@ -0,0 +1,27 @@
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.AspNetCore.Mvc;
namespace LINGYUN.Abp.WorkflowManagement.Events
{
[RemoteService(Name = WorkflowManagementRemoteServiceConsts.RemoteServiceName)]
[Area("WorkflowManagement")]
[Route("api/workflow-management/events")]
public class EventController : AbpControllerBase, IEventAppService
{
private readonly IEventAppService _service;
public EventController(IEventAppService service)
{
_service = service;
}
[HttpPost]
[Route("{EventName}/{EventKey}")]
public virtual async Task PublishAsync(EventPublishInput input)
{
await _service.PublishAsync(input);
}
}
}

61
aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.HttpApi/LINGYUN/Abp/WorkflowManagement/Workflows/WorkflowController.cs

@ -0,0 +1,61 @@
using Microsoft.AspNetCore.Mvc;
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")]
public class WorkflowController : AbpControllerBase, IWorkflowAppService
{
private readonly IWorkflowAppService _service;
public WorkflowController(IWorkflowAppService service)
{
_service = service;
}
[HttpGet]
[Route("{id}")]
public virtual async Task<WorkflowDto> GetAsync(string id)
{
return await _service.GetAsync(id);
}
[HttpPut]
[Route("{id}/resume")]
public virtual async Task ResumeAsync(string id)
{
await _service.ResumeAsync(id);
}
[HttpPost]
public virtual async Task CreateAsync(WorkflowCreateDto input)
{
await _service.CreateAsync(input);
}
[HttpPost]
[Route("{id}/start")]
public virtual async Task<WorkflowDto> StartAsync(string id, WorkflowStartInput input)
{
return await _service.StartAsync(id, input);
}
[HttpPut]
[Route("{id}/suspend")]
public virtual async Task SuspendAsync(string id)
{
await _service.SuspendAsync(id);
}
[HttpPut]
[Route("{id}/terminate")]
public virtual async Task TerminateAsync(string id)
{
await _service.TerminateAsync(id);
}
}
}

13
aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/Controllers/HomeController.cs

@ -0,0 +1,13 @@
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc;
namespace LY.MicroService.WorkflowManagement.Controllers
{
public class HomeController : AbpController
{
public IActionResult Index()
{
return Redirect("/swagger/index.html");
}
}
}

15
aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/Dockerfile

@ -0,0 +1,15 @@
FROM mcr.microsoft.com/dotnet/aspnet:5.0
LABEL maintainer="colin.in@foxmail.com"
WORKDIR /app
COPY . /app
#�Ϻ�ʱ��
#ENV TZ=Asia/Shanghai
#RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo '$TZ' > /etc/timezone
EXPOSE 80/tcp
VOLUME [ "./app/Logs" ]
VOLUME [ "./app/Modules" ]
ENTRYPOINT ["dotnet", "LY.MicroService.WorkflowManagement.HttpApi.Host.dll"]

24
aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/EntityFrameworkCore/WorkflowManagementMigrationsDbContext.cs

@ -0,0 +1,24 @@
using LINGYUN.Abp.WorkflowCore.Persistence.EntityFrameworkCore;
using LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore;
namespace LY.MicroService.WorkflowManagement.EntityFrameworkCore
{
public class WorkflowManagementMigrationsDbContext : AbpDbContext<WorkflowManagementMigrationsDbContext>
{
public WorkflowManagementMigrationsDbContext(DbContextOptions<WorkflowManagementMigrationsDbContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.ConfigureWorkflow();
modelBuilder.ConfigureWorkflowManagement();
}
}
}

31
aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/EntityFrameworkCore/WorkflowManagementMigrationsDbContextFactory.cs

@ -0,0 +1,31 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.Configuration;
using System.IO;
namespace LY.MicroService.WorkflowManagement.EntityFrameworkCore
{
public class WorkflowManagementMigrationsDbContextFactory : IDesignTimeDbContextFactory<WorkflowManagementMigrationsDbContext>
{
public WorkflowManagementMigrationsDbContext CreateDbContext(string[] args)
{
var configuration = BuildConfiguration();
var connectionString = configuration.GetConnectionString("WorkflowManagement");
var builder = new DbContextOptionsBuilder<WorkflowManagementMigrationsDbContext>()
.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));
return new WorkflowManagementMigrationsDbContext(builder.Options);
}
private static IConfigurationRoot BuildConfiguration()
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: false)
.AddJsonFile("appsettings.Development.json", optional: true);
return builder.Build();
}
}
}

70
aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/EventBus/Handlers/TenantSynchronizer.cs

@ -0,0 +1,70 @@
using LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore;
using LINGYUN.Abp.Data.DbMigrator;
using LINGYUN.Abp.MultiTenancy;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using System.Threading.Tasks;
using Volo.Abp.Data;
using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus.Distributed;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Uow;
namespace LY.MicroService.WorkflowManagement.EventBus.Handlers
{
public class TenantSynchronizer :
IDistributedEventHandler<CreateEventData>,
ITransientDependency
{
protected IDataSeeder DataSeeder { get; }
protected ICurrentTenant CurrentTenant { get; }
protected IDbSchemaMigrator DbSchemaMigrator { get; }
protected IUnitOfWorkManager UnitOfWorkManager { get; }
protected ILogger<TenantSynchronizer> Logger { get; }
public TenantSynchronizer(
IDataSeeder dataSeeder,
ICurrentTenant currentTenant,
IDbSchemaMigrator dbSchemaMigrator,
IUnitOfWorkManager unitOfWorkManager,
ILogger<TenantSynchronizer> logger)
{
DataSeeder = dataSeeder;
CurrentTenant = currentTenant;
DbSchemaMigrator = dbSchemaMigrator;
UnitOfWorkManager = unitOfWorkManager;
Logger = logger;
}
/// <summary>
/// 租户创建之后需要预置种子数据
/// </summary>
/// <param name="eventData"></param>
/// <returns></returns>
public virtual async Task HandleEventAsync(CreateEventData eventData)
{
using (var unitOfWork = UnitOfWorkManager.Begin())
{
using (CurrentTenant.Change(eventData.Id, eventData.Name))
{
Logger.LogInformation("Migrating the new tenant database with WorkflowManagement...");
// 迁移租户数据
await DbSchemaMigrator.MigrateAsync<WorkflowManagementDbContext>(
(connectionString, builder) =>
{
builder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));
return new WorkflowManagementDbContext(builder.Options);
});
Logger.LogInformation("Migrated the new tenant database with WorkflowManagement...");
await DataSeeder.SeedAsync(new DataSeedContext(eventData.Id));
await unitOfWork.SaveChangesAsync();
}
}
}
}
}

58
aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/LY.MicroService.WorkflowManagement.HttpApi.Host.csproj

@ -0,0 +1,58 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<RootNamespace>LY.MicroService.WorkflowManagement</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AgileConfig.Client" Version="$(AgileConfigClientPackageVersion)" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="$(MicrosoftPackageVersion)">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.AspNetCore.DataProtection.StackExchangeRedis" Version="$(MicrosoftPackageVersion)" />
<PackageReference Include="DistributedLock.Redis" Version="$(DistributedLockRedisPackageVersion)" />
<PackageReference Include="Serilog.AspNetCore" Version="$(SerilogAspNetCorePackageVersion)" />
<PackageReference Include="Serilog.Enrichers.Environment" Version="$(SerilogEnrichersEnvironmentPackageVersion)" />
<PackageReference Include="Serilog.Enrichers.Assembly" Version="$(SerilogEnrichersAssemblyPackageVersion)" />
<PackageReference Include="Serilog.Enrichers.Process" Version="$(SerilogEnrichersProcessPackageVersion)" />
<PackageReference Include="Serilog.Enrichers.Thread" Version="$(SerilogEnrichersThreadPackageVersion)" />
<PackageReference Include="Serilog.Settings.Configuration" Version="$(SerilogSettingsConfigurationPackageVersion)" />
<PackageReference Include="Serilog.Sinks.Elasticsearch" Version="$(SerilogSinksElasticsearchPackageVersion)" />
<PackageReference Include="Serilog.Sinks.File" Version="$(SerilogSinksFilePackageVersion)" />
<PackageReference Include="Volo.Abp.AspNetCore.Serilog" Version="$(VoloAbpPackageVersion)" />
<PackageReference Include="Volo.Abp.Caching.StackExchangeRedis" Version="$(VoloAbpPackageVersion)" />
<PackageReference Include="Volo.Abp.AspNetCore.MultiTenancy" Version="$(VoloAbpPackageVersion)" />
<PackageReference Include="Volo.Abp.AspNetCore.Authentication.JwtBearer" Version="$(VoloAbpPackageVersion)" />
<PackageReference Include="Volo.Abp.Autofac" Version="$(VoloAbpPackageVersion)" />
<PackageReference Include="Volo.Abp.EventBus.RabbitMQ" Version="$(VoloAbpPackageVersion)" />
<PackageReference Include="Volo.Abp.Swashbuckle" Version="$(VoloAbpPackageVersion)" />
<PackageReference Include="Volo.Abp.EntityFrameworkCore.MySql" Version="$(VoloAbpPackageVersion)" />
<PackageReference Include="Volo.Abp.Http.Client.IdentityModel.Web" Version="$(VoloAbpPackageVersion)" />
<PackageReference Include="Volo.Abp.FeatureManagement.EntityFrameworkCore" Version="$(VoloAbpPackageVersion)" />
<PackageReference Include="Volo.Abp.PermissionManagement.EntityFrameworkCore" Version="$(VoloAbpPackageVersion)" />
<PackageReference Include="Volo.Abp.SettingManagement.EntityFrameworkCore" Version="$(VoloAbpPackageVersion)" />
<PackageReference Include="Volo.Abp.TenantManagement.EntityFrameworkCore" Version="$(VoloAbpPackageVersion)" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\modules\common\LINGYUN.Abp.Data.DbMigrator\LINGYUN.Abp.Data.DbMigrator.csproj" />
<ProjectReference Include="..\..\modules\common\LINGYUN.Abp.ExceptionHandling.Emailing\LINGYUN.Abp.ExceptionHandling.Emailing.csproj" />
<ProjectReference Include="..\..\modules\tenants\LINGYUN.Abp.MultiTenancy\LINGYUN.Abp.MultiTenancy.csproj" />
<ProjectReference Include="..\..\modules\tenants\LINGYUN.Abp.MultiTenancy.DbFinder\LINGYUN.Abp.MultiTenancy.DbFinder.csproj" />
<ProjectReference Include="..\..\modules\auditing\LINGYUN.Abp.AuditLogging.Elasticsearch\LINGYUN.Abp.AuditLogging.Elasticsearch.csproj" />
<ProjectReference Include="..\..\modules\logging\LINGYUN.Abp.Serilog.Enrichers.Application\LINGYUN.Abp.Serilog.Enrichers.Application.csproj" />
<ProjectReference Include="..\..\modules\lt\LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore\LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\modules\workflow\LINGYUN.Abp.WorkflowCore.Components\LINGYUN.Abp.WorkflowCore.Components.csproj" />
<ProjectReference Include="..\..\modules\workflow\LINGYUN.Abp.WorkflowCore.DistributedLock\LINGYUN.Abp.WorkflowCore.DistributedLock.csproj" />
<ProjectReference Include="..\..\modules\workflow\LINGYUN.Abp.WorkflowCore.Elasticsearch\LINGYUN.Abp.WorkflowCore.Elasticsearch.csproj" />
<ProjectReference Include="..\..\modules\workflow\LINGYUN.Abp.WorkflowCore.LifeCycleEvent\LINGYUN.Abp.WorkflowCore.LifeCycleEvent.csproj" />
<ProjectReference Include="..\..\modules\workflow\LINGYUN.Abp.WorkflowCore.Persistence.EntityFrameworkCore\LINGYUN.Abp.WorkflowCore.Persistence.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\modules\workflow\LINGYUN.Abp.WorkflowCore.RabbitMQ\LINGYUN.Abp.WorkflowCore.RabbitMQ.csproj" />
<ProjectReference Include="..\..\modules\workflow\LINGYUN.Abp.WorkflowManagement.Application\LINGYUN.Abp.WorkflowManagement.Application.csproj" />
<ProjectReference Include="..\..\modules\workflow\LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore\LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore.csproj" />
<ProjectReference Include="..\..\modules\workflow\LINGYUN.Abp.WorkflowManagement.HttpApi\LINGYUN.Abp.WorkflowManagement.HttpApi.csproj" />
</ItemGroup>
</Project>

557
aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/Migrations/20211212074420_Add-Module-Workflow-Management.Designer.cs

@ -0,0 +1,557 @@
// <auto-generated />
using System;
using LY.MicroService.WorkflowManagement.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Volo.Abp.EntityFrameworkCore;
#nullable disable
namespace LY.MicroService.WorkflowManagement.Migrations
{
[DbContext(typeof(WorkflowManagementMigrationsDbContext))]
[Migration("20211212074420_Add-Module-Workflow-Management")]
partial class AddModuleWorkflowManagement
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.MySql)
.HasAnnotation("ProductVersion", "6.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("LINGYUN.Abp.WorkflowCore.Persistence.PersistedEvent", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)")
.HasColumnName("CreationTime");
b.Property<string>("EventData")
.HasColumnType("longtext");
b.Property<string>("EventKey")
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<string>("EventName")
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<bool>("IsProcessed")
.HasColumnType("tinyint(1)");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.HasKey("Id");
b.HasIndex("CreationTime");
b.HasIndex("IsProcessed");
b.HasIndex("EventName", "EventKey");
b.ToTable("WF_Event", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.WorkflowCore.Persistence.PersistedExecutionError", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<DateTime>("ErrorTime")
.HasColumnType("datetime(6)");
b.Property<Guid>("ExecutionPointerId")
.HasMaxLength(50)
.HasColumnType("char(50)");
b.Property<string>("Message")
.HasColumnType("longtext");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.Property<Guid>("WorkflowId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.ToTable("WF_ExecutionError", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.WorkflowCore.Persistence.PersistedExecutionPointer", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasMaxLength(50)
.HasColumnType("char(50)");
b.Property<bool>("Active")
.HasColumnType("tinyint(1)");
b.Property<string>("Children")
.HasColumnType("longtext");
b.Property<string>("ContextItem")
.HasColumnType("longtext");
b.Property<DateTime?>("EndTime")
.HasColumnType("datetime(6)");
b.Property<string>("EventData")
.HasColumnType("longtext");
b.Property<string>("EventKey")
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<string>("EventName")
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<bool>("EventPublished")
.HasColumnType("tinyint(1)");
b.Property<string>("Outcome")
.HasColumnType("longtext");
b.Property<string>("PersistenceData")
.HasColumnType("longtext");
b.Property<string>("PredecessorId")
.HasMaxLength(100)
.HasColumnType("varchar(100)");
b.Property<int>("RetryCount")
.HasColumnType("int");
b.Property<string>("Scope")
.HasColumnType("longtext");
b.Property<DateTime?>("SleepUntil")
.HasColumnType("datetime(6)");
b.Property<DateTime?>("StartTime")
.HasColumnType("datetime(6)");
b.Property<int>("Status")
.HasColumnType("int");
b.Property<int>("StepId")
.HasColumnType("int");
b.Property<string>("StepName")
.HasMaxLength(100)
.HasColumnType("varchar(100)");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.Property<Guid>("WorkflowId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("WorkflowId");
b.ToTable("WF_ExecutionPointer", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.WorkflowCore.Persistence.PersistedExtensionAttribute", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<Guid>("ExecutionPointerId")
.HasMaxLength(50)
.HasColumnType("char(50)");
b.Property<string>("Key")
.HasMaxLength(100)
.HasColumnType("varchar(100)");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.Property<string>("Value")
.HasColumnType("longtext");
b.HasKey("Id");
b.HasIndex("ExecutionPointerId");
b.ToTable("WF_ExtensionAttribute", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.WorkflowCore.Persistence.PersistedScheduledCommand", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<string>("CommandName")
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<string>("Data")
.HasMaxLength(500)
.HasColumnType("varchar(500)");
b.Property<long>("ExecuteTime")
.HasColumnType("bigint");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.HasKey("Id");
b.HasIndex("ExecuteTime");
b.HasIndex("CommandName", "Data")
.IsUnique();
b.ToTable("WF_ScheduledCommand", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.WorkflowCore.Persistence.PersistedSubscription", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<string>("EventKey")
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<string>("EventName")
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<Guid>("ExecutionPointerId")
.HasMaxLength(50)
.HasColumnType("char(50)");
b.Property<string>("ExternalToken")
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<DateTime?>("ExternalTokenExpiry")
.HasColumnType("datetime(6)");
b.Property<string>("ExternalWorkerId")
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<int>("StepId")
.HasColumnType("int");
b.Property<DateTime>("SubscribeAsOf")
.HasColumnType("datetime(6)");
b.Property<string>("SubscriptionData")
.HasColumnType("longtext");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.Property<Guid>("WorkflowId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("EventKey");
b.HasIndex("EventName");
b.ToTable("WF_Subscription", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.WorkflowCore.Persistence.PersistedWorkflow", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<DateTime?>("CompleteTime")
.HasColumnType("datetime(6)");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("varchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)")
.HasColumnName("CreatorId");
b.Property<string>("Data")
.HasColumnType("longtext");
b.Property<string>("Description")
.HasMaxLength(500)
.HasColumnType("varchar(500)");
b.Property<string>("ExtraProperties")
.HasColumnType("longtext")
.HasColumnName("ExtraProperties");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime(6)")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("char(36)")
.HasColumnName("LastModifierId");
b.Property<long?>("NextExecution")
.HasColumnType("bigint");
b.Property<string>("Reference")
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<int>("Status")
.HasColumnType("int");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.Property<int>("Version")
.HasColumnType("int");
b.Property<string>("WorkflowDefinitionId")
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.HasKey("Id");
b.HasIndex("NextExecution");
b.ToTable("WF_Workflow", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.WorkflowManagement.CompensateNode", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<string>("CancelCondition")
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<int?>("ErrorBehavior")
.HasColumnType("int");
b.Property<string>("Inputs")
.HasColumnType("longtext");
b.Property<string>("Name")
.HasMaxLength(100)
.HasColumnType("varchar(100)");
b.Property<string>("Outputs")
.HasColumnType("longtext");
b.Property<Guid?>("ParentId")
.HasColumnType("char(36)");
b.Property<TimeSpan?>("RetryInterval")
.HasColumnType("time(6)");
b.Property<bool>("Saga")
.HasColumnType("tinyint(1)");
b.Property<string>("SelectNextStep")
.HasColumnType("longtext");
b.Property<string>("StepType")
.HasMaxLength(100)
.HasColumnType("varchar(100)");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.Property<Guid>("WorkflowId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.ToTable("WF_Compensate", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.WorkflowManagement.StepNode", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<string>("CancelCondition")
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<int?>("ErrorBehavior")
.HasColumnType("int");
b.Property<string>("Inputs")
.HasColumnType("longtext");
b.Property<string>("Name")
.HasMaxLength(100)
.HasColumnType("varchar(100)");
b.Property<string>("Outputs")
.HasColumnType("longtext");
b.Property<Guid?>("ParentId")
.HasColumnType("char(36)");
b.Property<TimeSpan?>("RetryInterval")
.HasColumnType("time(6)");
b.Property<bool>("Saga")
.HasColumnType("tinyint(1)");
b.Property<string>("SelectNextStep")
.HasColumnType("longtext");
b.Property<string>("StepType")
.HasMaxLength(100)
.HasColumnType("varchar(100)");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.Property<Guid>("WorkflowId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.ToTable("WF_Step", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.WorkflowManagement.Workflow", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("varchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)")
.HasColumnName("CreatorId");
b.Property<string>("Description")
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<string>("DisplayName")
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<int>("ErrorBehavior")
.HasColumnType("int");
b.Property<TimeSpan?>("ErrorRetryInterval")
.HasColumnType("time(6)");
b.Property<string>("ExtraProperties")
.HasColumnType("longtext")
.HasColumnName("ExtraProperties");
b.Property<bool>("IsEnabled")
.HasColumnType("tinyint(1)");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime(6)")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("char(36)")
.HasColumnName("LastModifierId");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("varchar(100)");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.Property<int>("Version")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("WF_Definition", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.WorkflowCore.Persistence.PersistedExecutionPointer", b =>
{
b.HasOne("LINGYUN.Abp.WorkflowCore.Persistence.PersistedWorkflow", "Workflow")
.WithMany("ExecutionPointers")
.HasForeignKey("WorkflowId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Workflow");
});
modelBuilder.Entity("LINGYUN.Abp.WorkflowCore.Persistence.PersistedExtensionAttribute", b =>
{
b.HasOne("LINGYUN.Abp.WorkflowCore.Persistence.PersistedExecutionPointer", "ExecutionPointer")
.WithMany("ExtensionAttributes")
.HasForeignKey("ExecutionPointerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("ExecutionPointer");
});
modelBuilder.Entity("LINGYUN.Abp.WorkflowCore.Persistence.PersistedExecutionPointer", b =>
{
b.Navigation("ExtensionAttributes");
});
modelBuilder.Entity("LINGYUN.Abp.WorkflowCore.Persistence.PersistedWorkflow", b =>
{
b.Navigation("ExecutionPointers");
});
#pragma warning restore 612, 618
}
}
}

385
aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/Migrations/20211212074420_Add-Module-Workflow-Management.cs

@ -0,0 +1,385 @@
using System;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace LY.MicroService.WorkflowManagement.Migrations
{
public partial class AddModuleWorkflowManagement : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterDatabase()
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "WF_Compensate",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
TenantId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
WorkflowId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
Name = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
StepType = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
CancelCondition = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
ErrorBehavior = table.Column<int>(type: "int", nullable: true),
RetryInterval = table.Column<TimeSpan>(type: "time(6)", nullable: true),
Saga = table.Column<bool>(type: "tinyint(1)", nullable: false),
ParentId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
Inputs = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
Outputs = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
SelectNextStep = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4")
},
constraints: table =>
{
table.PrimaryKey("PK_WF_Compensate", x => x.Id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "WF_Definition",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
TenantId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
IsEnabled = table.Column<bool>(type: "tinyint(1)", nullable: false),
Name = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
DisplayName = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
Description = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
Version = table.Column<int>(type: "int", nullable: false),
ErrorBehavior = table.Column<int>(type: "int", nullable: false),
ErrorRetryInterval = table.Column<TimeSpan>(type: "time(6)", nullable: true),
ExtraProperties = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
ConcurrencyStamp = table.Column<string>(type: "varchar(40)", maxLength: 40, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
CreationTime = table.Column<DateTime>(type: "datetime(6)", nullable: false),
CreatorId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
LastModificationTime = table.Column<DateTime>(type: "datetime(6)", nullable: true),
LastModifierId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci")
},
constraints: table =>
{
table.PrimaryKey("PK_WF_Definition", x => x.Id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "WF_Event",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
TenantId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
EventName = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
EventKey = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
EventData = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
IsProcessed = table.Column<bool>(type: "tinyint(1)", nullable: false),
CreationTime = table.Column<DateTime>(type: "datetime(6)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_WF_Event", x => x.Id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "WF_ExecutionError",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
TenantId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
WorkflowId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
ExecutionPointerId = table.Column<Guid>(type: "char(50)", maxLength: 50, nullable: false, collation: "ascii_general_ci"),
ErrorTime = table.Column<DateTime>(type: "datetime(6)", nullable: false),
Message = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4")
},
constraints: table =>
{
table.PrimaryKey("PK_WF_ExecutionError", x => x.Id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "WF_ScheduledCommand",
columns: table => new
{
Id = table.Column<long>(type: "bigint", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
TenantId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
CommandName = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
Data = table.Column<string>(type: "varchar(500)", maxLength: 500, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
ExecuteTime = table.Column<long>(type: "bigint", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_WF_ScheduledCommand", x => x.Id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "WF_Step",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
TenantId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
WorkflowId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
Name = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
StepType = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
CancelCondition = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
ErrorBehavior = table.Column<int>(type: "int", nullable: true),
RetryInterval = table.Column<TimeSpan>(type: "time(6)", nullable: true),
Saga = table.Column<bool>(type: "tinyint(1)", nullable: false),
ParentId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
Inputs = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
Outputs = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
SelectNextStep = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4")
},
constraints: table =>
{
table.PrimaryKey("PK_WF_Step", x => x.Id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "WF_Subscription",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
TenantId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
WorkflowId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
StepId = table.Column<int>(type: "int", nullable: false),
ExecutionPointerId = table.Column<Guid>(type: "char(50)", maxLength: 50, nullable: false, collation: "ascii_general_ci"),
EventName = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
EventKey = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
SubscribeAsOf = table.Column<DateTime>(type: "datetime(6)", nullable: false),
SubscriptionData = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
ExternalToken = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
ExternalWorkerId = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
ExternalTokenExpiry = table.Column<DateTime>(type: "datetime(6)", nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_WF_Subscription", x => x.Id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "WF_Workflow",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
TenantId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
WorkflowDefinitionId = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
Version = table.Column<int>(type: "int", nullable: false),
Description = table.Column<string>(type: "varchar(500)", maxLength: 500, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
Reference = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
NextExecution = table.Column<long>(type: "bigint", nullable: true),
Status = table.Column<int>(type: "int", nullable: false),
Data = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
CompleteTime = table.Column<DateTime>(type: "datetime(6)", nullable: true),
ExtraProperties = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
ConcurrencyStamp = table.Column<string>(type: "varchar(40)", maxLength: 40, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
CreationTime = table.Column<DateTime>(type: "datetime(6)", nullable: false),
CreatorId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
LastModificationTime = table.Column<DateTime>(type: "datetime(6)", nullable: true),
LastModifierId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci")
},
constraints: table =>
{
table.PrimaryKey("PK_WF_Workflow", x => x.Id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "WF_ExecutionPointer",
columns: table => new
{
Id = table.Column<Guid>(type: "char(50)", maxLength: 50, nullable: false, collation: "ascii_general_ci"),
TenantId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
WorkflowId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
StepId = table.Column<int>(type: "int", nullable: false),
Active = table.Column<bool>(type: "tinyint(1)", nullable: false),
SleepUntil = table.Column<DateTime>(type: "datetime(6)", nullable: true),
PersistenceData = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
StartTime = table.Column<DateTime>(type: "datetime(6)", nullable: true),
EndTime = table.Column<DateTime>(type: "datetime(6)", nullable: true),
EventName = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
EventKey = table.Column<string>(type: "varchar(200)", maxLength: 200, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
EventPublished = table.Column<bool>(type: "tinyint(1)", nullable: false),
EventData = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
StepName = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
RetryCount = table.Column<int>(type: "int", nullable: false),
Children = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
ContextItem = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
PredecessorId = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
Outcome = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
Status = table.Column<int>(type: "int", nullable: false),
Scope = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4")
},
constraints: table =>
{
table.PrimaryKey("PK_WF_ExecutionPointer", x => x.Id);
table.ForeignKey(
name: "FK_WF_ExecutionPointer_WF_Workflow_WorkflowId",
column: x => x.WorkflowId,
principalTable: "WF_Workflow",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "WF_ExtensionAttribute",
columns: table => new
{
Id = table.Column<long>(type: "bigint", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
TenantId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
ExecutionPointerId = table.Column<Guid>(type: "char(50)", maxLength: 50, nullable: false, collation: "ascii_general_ci"),
Key = table.Column<string>(type: "varchar(100)", maxLength: 100, nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
Value = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4")
},
constraints: table =>
{
table.PrimaryKey("PK_WF_ExtensionAttribute", x => x.Id);
table.ForeignKey(
name: "FK_WF_ExtensionAttribute_WF_ExecutionPointer_ExecutionPointerId",
column: x => x.ExecutionPointerId,
principalTable: "WF_ExecutionPointer",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateIndex(
name: "IX_WF_Event_CreationTime",
table: "WF_Event",
column: "CreationTime");
migrationBuilder.CreateIndex(
name: "IX_WF_Event_EventName_EventKey",
table: "WF_Event",
columns: new[] { "EventName", "EventKey" });
migrationBuilder.CreateIndex(
name: "IX_WF_Event_IsProcessed",
table: "WF_Event",
column: "IsProcessed");
migrationBuilder.CreateIndex(
name: "IX_WF_ExecutionPointer_WorkflowId",
table: "WF_ExecutionPointer",
column: "WorkflowId");
migrationBuilder.CreateIndex(
name: "IX_WF_ExtensionAttribute_ExecutionPointerId",
table: "WF_ExtensionAttribute",
column: "ExecutionPointerId");
migrationBuilder.CreateIndex(
name: "IX_WF_ScheduledCommand_CommandName_Data",
table: "WF_ScheduledCommand",
columns: new[] { "CommandName", "Data" },
unique: true);
migrationBuilder.CreateIndex(
name: "IX_WF_ScheduledCommand_ExecuteTime",
table: "WF_ScheduledCommand",
column: "ExecuteTime");
migrationBuilder.CreateIndex(
name: "IX_WF_Subscription_EventKey",
table: "WF_Subscription",
column: "EventKey");
migrationBuilder.CreateIndex(
name: "IX_WF_Subscription_EventName",
table: "WF_Subscription",
column: "EventName");
migrationBuilder.CreateIndex(
name: "IX_WF_Workflow_NextExecution",
table: "WF_Workflow",
column: "NextExecution");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "WF_Compensate");
migrationBuilder.DropTable(
name: "WF_Definition");
migrationBuilder.DropTable(
name: "WF_Event");
migrationBuilder.DropTable(
name: "WF_ExecutionError");
migrationBuilder.DropTable(
name: "WF_ExtensionAttribute");
migrationBuilder.DropTable(
name: "WF_ScheduledCommand");
migrationBuilder.DropTable(
name: "WF_Step");
migrationBuilder.DropTable(
name: "WF_Subscription");
migrationBuilder.DropTable(
name: "WF_ExecutionPointer");
migrationBuilder.DropTable(
name: "WF_Workflow");
}
}
}

555
aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/Migrations/WorkflowManagementMigrationsDbContextModelSnapshot.cs

@ -0,0 +1,555 @@
// <auto-generated />
using System;
using LY.MicroService.WorkflowManagement.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Volo.Abp.EntityFrameworkCore;
#nullable disable
namespace LY.MicroService.WorkflowManagement.Migrations
{
[DbContext(typeof(WorkflowManagementMigrationsDbContext))]
partial class WorkflowManagementMigrationsDbContextModelSnapshot : ModelSnapshot
{
protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("_Abp_DatabaseProvider", EfCoreDatabaseProvider.MySql)
.HasAnnotation("ProductVersion", "6.0.0")
.HasAnnotation("Relational:MaxIdentifierLength", 64);
modelBuilder.Entity("LINGYUN.Abp.WorkflowCore.Persistence.PersistedEvent", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)")
.HasColumnName("CreationTime");
b.Property<string>("EventData")
.HasColumnType("longtext");
b.Property<string>("EventKey")
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<string>("EventName")
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<bool>("IsProcessed")
.HasColumnType("tinyint(1)");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.HasKey("Id");
b.HasIndex("CreationTime");
b.HasIndex("IsProcessed");
b.HasIndex("EventName", "EventKey");
b.ToTable("WF_Event", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.WorkflowCore.Persistence.PersistedExecutionError", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
b.Property<DateTime>("ErrorTime")
.HasColumnType("datetime(6)");
b.Property<Guid>("ExecutionPointerId")
.HasMaxLength(50)
.HasColumnType("char(50)");
b.Property<string>("Message")
.HasColumnType("longtext");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.Property<Guid>("WorkflowId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.ToTable("WF_ExecutionError", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.WorkflowCore.Persistence.PersistedExecutionPointer", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasMaxLength(50)
.HasColumnType("char(50)");
b.Property<bool>("Active")
.HasColumnType("tinyint(1)");
b.Property<string>("Children")
.HasColumnType("longtext");
b.Property<string>("ContextItem")
.HasColumnType("longtext");
b.Property<DateTime?>("EndTime")
.HasColumnType("datetime(6)");
b.Property<string>("EventData")
.HasColumnType("longtext");
b.Property<string>("EventKey")
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<string>("EventName")
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<bool>("EventPublished")
.HasColumnType("tinyint(1)");
b.Property<string>("Outcome")
.HasColumnType("longtext");
b.Property<string>("PersistenceData")
.HasColumnType("longtext");
b.Property<string>("PredecessorId")
.HasMaxLength(100)
.HasColumnType("varchar(100)");
b.Property<int>("RetryCount")
.HasColumnType("int");
b.Property<string>("Scope")
.HasColumnType("longtext");
b.Property<DateTime?>("SleepUntil")
.HasColumnType("datetime(6)");
b.Property<DateTime?>("StartTime")
.HasColumnType("datetime(6)");
b.Property<int>("Status")
.HasColumnType("int");
b.Property<int>("StepId")
.HasColumnType("int");
b.Property<string>("StepName")
.HasMaxLength(100)
.HasColumnType("varchar(100)");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.Property<Guid>("WorkflowId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("WorkflowId");
b.ToTable("WF_ExecutionPointer", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.WorkflowCore.Persistence.PersistedExtensionAttribute", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<Guid>("ExecutionPointerId")
.HasMaxLength(50)
.HasColumnType("char(50)");
b.Property<string>("Key")
.HasMaxLength(100)
.HasColumnType("varchar(100)");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.Property<string>("Value")
.HasColumnType("longtext");
b.HasKey("Id");
b.HasIndex("ExecutionPointerId");
b.ToTable("WF_ExtensionAttribute", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.WorkflowCore.Persistence.PersistedScheduledCommand", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint");
b.Property<string>("CommandName")
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<string>("Data")
.HasMaxLength(500)
.HasColumnType("varchar(500)");
b.Property<long>("ExecuteTime")
.HasColumnType("bigint");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.HasKey("Id");
b.HasIndex("ExecuteTime");
b.HasIndex("CommandName", "Data")
.IsUnique();
b.ToTable("WF_ScheduledCommand", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.WorkflowCore.Persistence.PersistedSubscription", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<string>("EventKey")
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<string>("EventName")
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<Guid>("ExecutionPointerId")
.HasMaxLength(50)
.HasColumnType("char(50)");
b.Property<string>("ExternalToken")
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<DateTime?>("ExternalTokenExpiry")
.HasColumnType("datetime(6)");
b.Property<string>("ExternalWorkerId")
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<int>("StepId")
.HasColumnType("int");
b.Property<DateTime>("SubscribeAsOf")
.HasColumnType("datetime(6)");
b.Property<string>("SubscriptionData")
.HasColumnType("longtext");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.Property<Guid>("WorkflowId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("EventKey");
b.HasIndex("EventName");
b.ToTable("WF_Subscription", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.WorkflowCore.Persistence.PersistedWorkflow", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<DateTime?>("CompleteTime")
.HasColumnType("datetime(6)");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("varchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)")
.HasColumnName("CreatorId");
b.Property<string>("Data")
.HasColumnType("longtext");
b.Property<string>("Description")
.HasMaxLength(500)
.HasColumnType("varchar(500)");
b.Property<string>("ExtraProperties")
.HasColumnType("longtext")
.HasColumnName("ExtraProperties");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime(6)")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("char(36)")
.HasColumnName("LastModifierId");
b.Property<long?>("NextExecution")
.HasColumnType("bigint");
b.Property<string>("Reference")
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<int>("Status")
.HasColumnType("int");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.Property<int>("Version")
.HasColumnType("int");
b.Property<string>("WorkflowDefinitionId")
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.HasKey("Id");
b.HasIndex("NextExecution");
b.ToTable("WF_Workflow", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.WorkflowManagement.CompensateNode", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<string>("CancelCondition")
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<int?>("ErrorBehavior")
.HasColumnType("int");
b.Property<string>("Inputs")
.HasColumnType("longtext");
b.Property<string>("Name")
.HasMaxLength(100)
.HasColumnType("varchar(100)");
b.Property<string>("Outputs")
.HasColumnType("longtext");
b.Property<Guid?>("ParentId")
.HasColumnType("char(36)");
b.Property<TimeSpan?>("RetryInterval")
.HasColumnType("time(6)");
b.Property<bool>("Saga")
.HasColumnType("tinyint(1)");
b.Property<string>("SelectNextStep")
.HasColumnType("longtext");
b.Property<string>("StepType")
.HasMaxLength(100)
.HasColumnType("varchar(100)");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.Property<Guid>("WorkflowId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.ToTable("WF_Compensate", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.WorkflowManagement.StepNode", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<string>("CancelCondition")
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<int?>("ErrorBehavior")
.HasColumnType("int");
b.Property<string>("Inputs")
.HasColumnType("longtext");
b.Property<string>("Name")
.HasMaxLength(100)
.HasColumnType("varchar(100)");
b.Property<string>("Outputs")
.HasColumnType("longtext");
b.Property<Guid?>("ParentId")
.HasColumnType("char(36)");
b.Property<TimeSpan?>("RetryInterval")
.HasColumnType("time(6)");
b.Property<bool>("Saga")
.HasColumnType("tinyint(1)");
b.Property<string>("SelectNextStep")
.HasColumnType("longtext");
b.Property<string>("StepType")
.HasMaxLength(100)
.HasColumnType("varchar(100)");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.Property<Guid>("WorkflowId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.ToTable("WF_Step", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.WorkflowManagement.Workflow", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<string>("ConcurrencyStamp")
.IsConcurrencyToken()
.HasMaxLength(40)
.HasColumnType("varchar(40)")
.HasColumnName("ConcurrencyStamp");
b.Property<DateTime>("CreationTime")
.HasColumnType("datetime(6)")
.HasColumnName("CreationTime");
b.Property<Guid?>("CreatorId")
.HasColumnType("char(36)")
.HasColumnName("CreatorId");
b.Property<string>("Description")
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<string>("DisplayName")
.HasMaxLength(200)
.HasColumnType("varchar(200)");
b.Property<int>("ErrorBehavior")
.HasColumnType("int");
b.Property<TimeSpan?>("ErrorRetryInterval")
.HasColumnType("time(6)");
b.Property<string>("ExtraProperties")
.HasColumnType("longtext")
.HasColumnName("ExtraProperties");
b.Property<bool>("IsEnabled")
.HasColumnType("tinyint(1)");
b.Property<DateTime?>("LastModificationTime")
.HasColumnType("datetime(6)")
.HasColumnName("LastModificationTime");
b.Property<Guid?>("LastModifierId")
.HasColumnType("char(36)")
.HasColumnName("LastModifierId");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(100)
.HasColumnType("varchar(100)");
b.Property<Guid?>("TenantId")
.HasColumnType("char(36)")
.HasColumnName("TenantId");
b.Property<int>("Version")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("WF_Definition", (string)null);
});
modelBuilder.Entity("LINGYUN.Abp.WorkflowCore.Persistence.PersistedExecutionPointer", b =>
{
b.HasOne("LINGYUN.Abp.WorkflowCore.Persistence.PersistedWorkflow", "Workflow")
.WithMany("ExecutionPointers")
.HasForeignKey("WorkflowId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Workflow");
});
modelBuilder.Entity("LINGYUN.Abp.WorkflowCore.Persistence.PersistedExtensionAttribute", b =>
{
b.HasOne("LINGYUN.Abp.WorkflowCore.Persistence.PersistedExecutionPointer", "ExecutionPointer")
.WithMany("ExtensionAttributes")
.HasForeignKey("ExecutionPointerId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("ExecutionPointer");
});
modelBuilder.Entity("LINGYUN.Abp.WorkflowCore.Persistence.PersistedExecutionPointer", b =>
{
b.Navigation("ExtensionAttributes");
});
modelBuilder.Entity("LINGYUN.Abp.WorkflowCore.Persistence.PersistedWorkflow", b =>
{
b.Navigation("ExecutionPointers");
});
#pragma warning restore 612, 618
}
}
}

45
aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/Program.cs

@ -0,0 +1,45 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Serilog;
namespace LY.MicroService.WorkflowManagement
{
public class Program
{
public static int Main(string[] args)
{
try
{
var host = CreateHostBuilder(args).Build();
Log.Information("Starting web host.");
host.Run();
return 0;
}
finally
{
Log.CloseAndFlush();
}
}
internal static IHostBuilder CreateHostBuilder(string[] args) =>
Microsoft.Extensions.Hosting.Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
})
.ConfigureAppConfiguration((context, config) =>
{
var configuration = config.Build();
if (configuration.GetSection("AgileConfig").Exists())
{
config.AddAgileConfig(new AgileConfig.Client.ConfigClient(configuration));
}
})
.UseSerilog((context, config) =>
{
config.ReadFrom.Configuration(context.Configuration);
})
.UseAutofac();
}
}

21
aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/Properties/launchSettings.json

@ -0,0 +1,21 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:20890",
"sslPort": 0
}
},
"profiles": {
"LINGYUN.Abp.WorkflowManagement.HttpApi.Host": {
"commandName": "Project",
"launchBrowser": false,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://127.0.0.1:30035",
"dotnetRunMessages": "true"
}
}
}

18
aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/Startup.cs

@ -0,0 +1,18 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
namespace LY.MicroService.WorkflowManagement
{
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddApplication<WorkflowManagementHttpApiHostModule>();
}
public void Configure(IApplicationBuilder app)
{
app.InitializeApplication();
}
}
}

32
aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/TenantHeaderParamter.cs

@ -0,0 +1,32 @@
using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;
using System.Collections.Generic;
using Volo.Abp.MultiTenancy;
namespace LY.MicroService.WorkflowManagement
{
public class TenantHeaderParamter : IOperationFilter
{
private readonly AbpMultiTenancyOptions _options;
public TenantHeaderParamter(
IOptions<AbpMultiTenancyOptions> options)
{
_options = options.Value;
}
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
if (_options.IsEnabled)
{
operation.Parameters = operation.Parameters ?? new List<OpenApiParameter>();
operation.Parameters.Add(new OpenApiParameter
{
Name = TenantResolverConsts.DefaultTenantKey,
In = ParameterLocation.Header,
Description = "Tenant Id/Name",
Required = false
});
}
}
}
}

223
aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/WorkflowManagementHttpApiHostModule.Configure.cs

@ -0,0 +1,223 @@
using LINGYUN.Abp.ExceptionHandling;
using LINGYUN.Abp.ExceptionHandling.Emailing;
using LINGYUN.Abp.Serilog.Enrichers.Application;
using Medallion.Threading;
using Medallion.Threading.Redis;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.Caching.StackExchangeRedis;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
using StackExchange.Redis;
using System;
using System.Text.Encodings.Web;
using System.Text.Unicode;
using Volo.Abp;
using Volo.Abp.Auditing;
using Volo.Abp.Caching;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.Json;
using Volo.Abp.Json.SystemTextJson;
using Volo.Abp.Localization;
using Volo.Abp.MultiTenancy;
using Volo.Abp.Uow;
using Volo.Abp.VirtualFileSystem;
namespace LY.MicroService.WorkflowManagement
{
public partial class WorkflowManagementHttpApiHostModule
{
private void PreConfigureApp()
{
AbpSerilogEnrichersConsts.ApplicationName = "WorkflowManagement";
}
private void ConfigureDistributedLock(IServiceCollection services, IConfiguration configuration)
{
var redis = ConnectionMultiplexer.Connect(configuration["DistributedLock:Redis:Configuration"]);
services.AddSingleton<IDistributedLockProvider>(_ => new RedisDistributedSynchronizationProvider(redis.GetDatabase()));
}
private void ConfigureDbContext()
{
// 配置Ef
Configure<AbpDbContextOptions>(options =>
{
options.UseMySQL();
});
Configure<AbpUnitOfWorkOptions>(options =>
{
});
}
private void ConfigureJsonSerializer()
{
// 解决某些不支持类型的序列化
Configure<AbpJsonOptions>(options =>
{
options.DefaultDateTimeFormat = "yyyy-MM-dd HH:mm:ss";
});
// 中文序列化的编码问题
Configure<AbpSystemTextJsonSerializerOptions>(options =>
{
options.JsonSerializerOptions.Encoder = JavaScriptEncoder.Create(UnicodeRanges.All);
});
}
private void ConfigureExceptionHandling()
{
// 自定义需要处理的异常
Configure<AbpExceptionHandlingOptions>(options =>
{
// 加入需要处理的异常类型
options.Handlers.Add<Volo.Abp.Data.AbpDbConcurrencyException>();
options.Handlers.Add<AbpInitializationException>();
options.Handlers.Add<OutOfMemoryException>();
options.Handlers.Add<System.Data.Common.DbException>();
options.Handlers.Add<Microsoft.EntityFrameworkCore.DbUpdateException>();
options.Handlers.Add<System.Data.DBConcurrencyException>();
});
// 自定义需要发送邮件通知的异常类型
Configure<AbpEmailExceptionHandlingOptions>(options =>
{
// 是否发送堆栈信息
options.SendStackTrace = true;
// 未指定异常接收者的默认接收邮件
// 指定自己的邮件地址
});
}
private void ConfigureAuditing(IConfiguration configuration)
{
Configure<AbpAuditingOptions>(options =>
{
options.ApplicationName = "WorkflowManagement";
// 是否启用实体变更记录
var entitiesChangedConfig = configuration.GetSection("App:TrackingEntitiesChanged");
if (entitiesChangedConfig.Exists() && entitiesChangedConfig.Get<bool>())
{
options
.EntityHistorySelectors
.AddAllEntities();
}
});
}
private void ConfigureCaching(IConfiguration configuration)
{
Configure<AbpDistributedCacheOptions>(options =>
{
// 最好统一命名,不然某个缓存变动其他应用服务有例外发生
options.KeyPrefix = "LINGYUN.Abp.Application";
// 滑动过期30天
options.GlobalCacheEntryOptions.SlidingExpiration = TimeSpan.FromDays(30d);
// 绝对过期60天
options.GlobalCacheEntryOptions.AbsoluteExpiration = DateTimeOffset.Now.AddDays(60d);
});
Configure<RedisCacheOptions>(options =>
{
var redisConfig = ConfigurationOptions.Parse(options.Configuration);
options.ConfigurationOptions = redisConfig;
options.InstanceName = configuration["Redis:InstanceName"];
});
}
private void ConfigureVirtualFileSystem()
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<WorkflowManagementHttpApiHostModule>("LINGYUN.Abp.WorkflowManagement");
});
}
private void ConfigureMultiTenancy(IConfiguration configuration)
{
// 多租户
Configure<AbpMultiTenancyOptions>(options =>
{
options.IsEnabled = true;
});
var tenantResolveCfg = configuration.GetSection("App:Domains");
if (tenantResolveCfg.Exists())
{
Configure<AbpTenantResolveOptions>(options =>
{
var domains = tenantResolveCfg.Get<string[]>();
foreach (var domain in domains)
{
options.AddDomainTenantResolver(domain);
}
});
}
}
private void ConfigureSwagger(IServiceCollection services)
{
// Swagger
services.AddSwaggerGen(
options =>
{
options.SwaggerDoc("v1", new OpenApiInfo { Title = "WorkflowManagement API", Version = "v1" });
options.DocInclusionPredicate((docName, description) => true);
options.CustomSchemaIds(type => type.FullName);
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Description = "JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
Name = "Authorization",
In = ParameterLocation.Header,
Scheme = "bearer",
Type = SecuritySchemeType.Http,
BearerFormat = "JWT"
});
options.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" }
},
new string[] { }
}
});
options.OperationFilter<TenantHeaderParamter>();
});
}
private void ConfigureLocalization()
{
// 支持本地化语言类型
Configure<AbpLocalizationOptions>(options =>
{
options.Languages.Add(new LanguageInfo("en", "en", "English"));
options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文"));
// 动态语言支持
options.Resources.AddDynamic();
});
}
private void ConfigureSecurity(IServiceCollection services, IConfiguration configuration, bool isDevelopment = false)
{
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.Authority = configuration["AuthServer:Authority"];
options.RequireHttpsMetadata = false;
options.Audience = configuration["AuthServer:ApiName"];
});
if (!isDevelopment)
{
var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]);
services
.AddDataProtection()
.SetApplicationName("LINGYUN.Abp.Application")
.PersistKeysToStackExchangeRedis(redis, "LINGYUN.Abp.Application:DataProtection:Protection-Keys");
}
}
}
}

21
aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/WorkflowManagementHttpApiHostModule.DataSeeder.cs

@ -0,0 +1,21 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Volo.Abp;
using Volo.Abp.Data;
using Volo.Abp.Threading;
namespace LY.MicroService.WorkflowManagement
{
public partial class WorkflowManagementHttpApiHostModule
{
private void SeedData(ApplicationInitializationContext context)
{
if (context.GetEnvironment().IsDevelopment())
{
AsyncHelper.RunSync(async () =>
await context.ServiceProvider.GetRequiredService<IDataSeeder>()
.SeedAsync());
}
}
}
}

124
aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/WorkflowManagementHttpApiHostModule.cs

@ -0,0 +1,124 @@
using LINGYUN.Abp.AuditLogging.Elasticsearch;
using LINGYUN.Abp.ExceptionHandling.Emailing;
using LINGYUN.Abp.LocalizationManagement.EntityFrameworkCore;
using LINGYUN.Abp.MultiTenancy.DbFinder;
using LINGYUN.Abp.Serilog.Enrichers.Application;
using LINGYUN.Abp.WorkflowCore.Components;
using LINGYUN.Abp.WorkflowCore.DistributedLock;
using LINGYUN.Abp.WorkflowCore.LifeCycleEvent;
using LINGYUN.Abp.WorkflowCore.Persistence.EntityFrameworkCore;
using LINGYUN.Abp.WorkflowCore.RabbitMQ;
using LINGYUN.Abp.WorkflowManagement;
using LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System.Globalization;
using Volo.Abp;
using Volo.Abp.AspNetCore.Authentication.JwtBearer;
using Volo.Abp.AspNetCore.MultiTenancy;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Serilog;
using Volo.Abp.Autofac;
using Volo.Abp.Caching.StackExchangeRedis;
using Volo.Abp.EntityFrameworkCore.MySQL;
using Volo.Abp.EventBus.RabbitMq;
using Volo.Abp.FeatureManagement.EntityFrameworkCore;
using Volo.Abp.Http.Client.IdentityModel.Web;
using Volo.Abp.Modularity;
using Volo.Abp.PermissionManagement.EntityFrameworkCore;
using Volo.Abp.SettingManagement.EntityFrameworkCore;
using Volo.Abp.Swashbuckle;
using Volo.Abp.TenantManagement.EntityFrameworkCore;
namespace LY.MicroService.WorkflowManagement
{
[DependsOn(
typeof(AbpSerilogEnrichersApplicationModule),
typeof(AbpAuditLoggingElasticsearchModule),
typeof(AbpAspNetCoreSerilogModule),
typeof(AbpEventBusRabbitMqModule),
typeof(WorkflowManagementApplicationModule),
typeof(WorkflowManagementHttpApiModule),
typeof(WorkflowManagementEntityFrameworkCoreModule),
typeof(AbpWorkflowCoreComponentsModule),
typeof(AbpWorkflowCoreDistributedLockModule),
typeof(AbpWorkflowCoreLifeCycleEventModule),
typeof(AbpWorkflowCoreRabbitMQModule),
typeof(AbpWorkflowCorePersistenceEntityFrameworkCoreModule),
typeof(AbpEntityFrameworkCoreMySQLModule),
typeof(AbpAspNetCoreAuthenticationJwtBearerModule),
typeof(AbpEmailingExceptionHandlingModule),
typeof(AbpHttpClientIdentityModelWebModule),
typeof(AbpAspNetCoreMultiTenancyModule),
typeof(AbpDbFinderMultiTenancyModule),
typeof(AbpFeatureManagementEntityFrameworkCoreModule),
typeof(AbpPermissionManagementEntityFrameworkCoreModule),
typeof(AbpSettingManagementEntityFrameworkCoreModule),
typeof(AbpTenantManagementEntityFrameworkCoreModule),
typeof(AbpLocalizationManagementEntityFrameworkCoreModule),
typeof(AbpCachingStackExchangeRedisModule),
typeof(AbpAspNetCoreMvcModule),
typeof(AbpSwashbuckleModule),
typeof(AbpAutofacModule)
)]
public partial class WorkflowManagementHttpApiHostModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
context.Services.AddAlwaysAllowAuthorization();
PreConfigureApp();
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
var hostingEnvironment = context.Services.GetHostingEnvironment();
var configuration = hostingEnvironment.BuildConfiguration();
ConfigureDbContext();
ConfigureLocalization();
ConfigureJsonSerializer();
ConfigureExceptionHandling();
ConfigureVirtualFileSystem();
ConfigureCaching(configuration);
ConfigureAuditing(configuration);
ConfigureMultiTenancy(configuration);
ConfigureSwagger(context.Services);
ConfigureDistributedLock(context.Services, configuration);
ConfigureSecurity(context.Services, configuration, hostingEnvironment.IsDevelopment());
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
var env = context.GetEnvironment();
app.UseStaticFiles();
app.UseCorrelationId();
app.UseRouting();
app.UseCors();
app.UseAuthentication();
app.UseJwtTokenMiddleware();
app.UseMultiTenancy();
app.UseAbpRequestLocalization(options => options.SetDefaultCulture(CultureInfo.CurrentCulture.Name));
app.UseAuthorization();
app.UseSwagger();
app.UseAbpSwaggerUI(options =>
{
options.SwaggerEndpoint("/swagger/v1/swagger.json", "Support APP API");
var configuration = context.GetConfiguration();
options.OAuthClientId(configuration["AuthServer:SwaggerClientId"]);
options.OAuthClientSecret(configuration["AuthServer:SwaggerClientSecret"]);
options.OAuthScopes("WorkflowManagement");
});
app.UseAuditing();
app.UseAbpSerilogEnrichers();
app.UseConfiguredEndpoints();
SeedData(context);
}
}
}

108
aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/appsettings.Development.json

@ -0,0 +1,108 @@
{
"AgileConfig": {
"env": "DEV",
"appId": "LINGYUN.Abp.WorkflowManagement",
"secret": "1q2w3E*",
"nodes": "http://127.0.0.1:15000",
"name": "LINGYUN.Abp.WorkflowManagement",
"tag": "LINGYUN.Abp.WorkflowManagement"
},
"App": {
"TrackingEntitiesChanged": true
},
"ConnectionStrings": {
"Default": "Server=127.0.0.1;Database=Workflow;User Id=root;Password=123456",
"WorkflowManagement": "Server=127.0.0.1;Database=Workflow;User Id=root;Password=123456",
"AbpWorkflowCore": "Server=127.0.0.1;Database=Workflow;User Id=root;Password=123456",
"AbpFeatureManagement": "Server=127.0.0.1;Database=Platform;User Id=root;Password=123456",
"AbpPermissionManagement": "Server=127.0.0.1;Database=Platform;User Id=root;Password=123456",
"AbpLocalizationManagement": "Server=127.0.0.1;Database=Platform;User Id=root;Password=123456",
"AbpSettingManagement": "Server=127.0.0.1;Database=Platform;User Id=root;Password=123456",
"AbpTenantManagement": "Server=127.0.0.1;Database=Platform;User Id=root;Password=123456"
},
"RemoteServices": {},
"IdentityClients": {
"InternalServiceClient": {
"Authority": "http://127.0.0.1:44385",
"RequireHttps": false,
"GrantType": "client_credentials",
"Scope": "lingyun-abp-application",
"ClientId": "InternalServiceClient",
"ClientSecret": "1q2w3E*"
}
},
"RabbitMQ": {
"Connections": {
"AbpWorkflowCore": {
"HostName": "127.0.0.1",
"Port": 5672,
"UserName": "admin",
"Password": "123456",
"VirtualHost": "/"
}
},
"EventBus": {
"ConnectionName": "AbpWorkflowCore",
"ClientName": "workflow.server",
"ExchangeName": "AbpWorkflowCore"
}
},
"DistributedLock": {
"Redis": {
"Configuration": "127.0.0.1,defaultDatabase=15"
}
},
"Redis": {
"Configuration": "127.0.0.1,defaultDatabase=10",
"InstanceName": "LINGYUN.Abp.Application"
},
"AuthServer": {
"Authority": "http://127.0.0.1:44385/",
"ApiName": "lingyun-abp-application",
"SwaggerClientId": "InternalServiceClient",
"SwaggerClientSecret": "1q2w3E*"
},
"Logging": {
"Serilog": {
"Elasticsearch": {
"IndexFormat": "abp.dev.logging-{0:yyyy.MM.dd}"
}
}
},
"AuditLogging": {
"Elasticsearch": {
"IndexPrefix": "abp.dev.auditing"
}
},
"Elasticsearch": {
"NodeUris": "http://127.0.0.1:9200"
},
"Serilog": {
"MinimumLevel": {
"Default": "Debug",
"Override": {
"System": "Warning",
"Microsoft": "Warning",
"DotNetCore": "Debug"
}
},
"WriteTo": [
{
"Name": "Console",
"Args": {
"restrictedToMinimumLevel": "Debug",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}"
}
},
{
"Name": "Elasticsearch",
"Args": {
"nodeUris": "http://127.0.0.1:9200",
"indexFormat": "abp.dev.logging-{0:yyyy.MM.dd}",
"autoRegisterTemplate": true,
"autoRegisterTemplateVersion": "ESv7"
}
}
]
}
}

80
aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/appsettings.json

@ -0,0 +1,80 @@
{
"StringEncryption": {
"DefaultPassPhrase": "s46c5q55nxpeS8Ra",
"InitVectorBytes": "s83ng0abvd02js84",
"DefaultSalt": "sf&5)s3#"
},
"AllowedHosts": "*",
"Serilog": {
"MinimumLevel": {
"Default": "Debug",
"Override": {
"Microsoft.EntityFrameworkCore": "Debug",
"System": "Information",
"Microsoft": "Information"
}
},
"Enrich": [ "FromLogContext", "WithProcessId", "WithThreadId", "WithEnvironmentName", "WithMachineName", "WithApplicationName" ],
"WriteTo": [
{
"Name": "Console",
"Args": {
"initialMinimumLevel": "Verbose",
"standardErrorFromLevel": "Verbose",
"restrictedToMinimumLevel": "Verbose",
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}"
}
},
{
"Name": "File",
"Args": {
"path": "Logs/Debug-.log",
"restrictedToMinimumLevel": "Debug",
"rollingInterval": "Day",
"fileSizeLimitBytes": 5242880,
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}"
}
},
{
"Name": "File",
"Args": {
"path": "Logs/Info-.log",
"restrictedToMinimumLevel": "Information",
"rollingInterval": "Day",
"fileSizeLimitBytes": 5242880,
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}"
}
},
{
"Name": "File",
"Args": {
"path": "Logs/Warn-.log",
"restrictedToMinimumLevel": "Warning",
"rollingInterval": "Day",
"fileSizeLimitBytes": 5242880,
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}"
}
},
{
"Name": "File",
"Args": {
"path": "Logs/Error-.log",
"restrictedToMinimumLevel": "Error",
"rollingInterval": "Day",
"fileSizeLimitBytes": 5242880,
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}"
}
},
{
"Name": "File",
"Args": {
"path": "Logs/Fatal-.log",
"restrictedToMinimumLevel": "Fatal",
"rollingInterval": "Day",
"fileSizeLimitBytes": 5242880,
"outputTemplate": "{Timestamp:yyyy-MM-dd HH:mm:ss} [{Level:u3}] [{SourceContext}] [{ProcessId}] [{ThreadId}] - {Message:lj}{NewLine}{Exception}"
}
}
]
}
}

1
aspnet-core/services/LY.MicroService.WorkflowManagement.HttpApi.Host/dapr.sh

@ -0,0 +1 @@
dapr run --app-id workflow --app-port 30035 -H 36550 -- dotnet run --no-build
Loading…
Cancel
Save