diff --git a/apps/vue/src/views/account/center/index.vue b/apps/vue/src/views/account/center/index.vue
index 1f700b577..38d73c451 100644
--- a/apps/vue/src/views/account/center/index.vue
+++ b/apps/vue/src/views/account/center/index.vue
@@ -59,7 +59,7 @@
},
{
key: 'setting',
- name: L('User'),
+ name: L('DisplayName:UserSetting'),
component: 'setting',
},
];
diff --git a/aspnet-core/Directory.Build.props b/aspnet-core/Directory.Build.props
index 50aa64a65..0cdfddd29 100644
--- a/aspnet-core/Directory.Build.props
+++ b/aspnet-core/Directory.Build.props
@@ -3,6 +3,7 @@
5.0.0-rc.2
5.0.0-rc.2
1.5.0
+ 1.0.1
5.2.0
1.5.10
2.13.0
diff --git a/aspnet-core/LINGYUN.MicroService.Workflow.sln b/aspnet-core/LINGYUN.MicroService.Workflow.sln
index 8d629f7bf..18d1a7cf1 100644
--- a/aspnet-core/LINGYUN.MicroService.Workflow.sln
+++ b/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}
diff --git a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IndexInitializer.cs b/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IndexInitializer.cs
index 079394ed1..f49259704 100644
--- a/aspnet-core/modules/auditing/LINGYUN.Abp.AuditLogging.Elasticsearch/LINGYUN/Abp/AuditLogging/Elasticsearch/IndexInitializer.cs
+++ b/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(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(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());
diff --git a/aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application.Contracts/LINGYUN/Abp/SettingManagement/Localization/ApplicationContracts/en.json b/aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application.Contracts/LINGYUN/Abp/SettingManagement/Localization/ApplicationContracts/en.json
index c7d960e1c..30efeb7e6 100644
--- a/aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application.Contracts/LINGYUN/Abp/SettingManagement/Localization/ApplicationContracts/en.json
+++ b/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",
diff --git a/aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application.Contracts/LINGYUN/Abp/SettingManagement/Localization/ApplicationContracts/zh-Hans.json b/aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application.Contracts/LINGYUN/Abp/SettingManagement/Localization/ApplicationContracts/zh-Hans.json
index eab5dec9d..34fbdafc2 100644
--- a/aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application.Contracts/LINGYUN/Abp/SettingManagement/Localization/ApplicationContracts/zh-Hans.json
+++ b/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": "语言",
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.DistributedLock/LINGYUN.Abp.WorkflowCore.DistributedLock.csproj b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.DistributedLock/LINGYUN.Abp.WorkflowCore.DistributedLock.csproj
index 4d1174192..bf77fa720 100644
--- a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.DistributedLock/LINGYUN.Abp.WorkflowCore.DistributedLock.csproj
+++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.DistributedLock/LINGYUN.Abp.WorkflowCore.DistributedLock.csproj
@@ -9,7 +9,7 @@
-
+
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.DistributedLock/LINGYUN/Abp/WorkflowCore/DistributedLock/AbpWorkflowCoreDistributedLockModule.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.DistributedLock/LINGYUN/Abp/WorkflowCore/DistributedLock/AbpWorkflowCoreDistributedLockModule.cs
index 908258912..578713b8d 100644
--- a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.DistributedLock/LINGYUN/Abp/WorkflowCore/DistributedLock/AbpWorkflowCoreDistributedLockModule.cs
+++ b/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();
context.Services.AddSingleton();
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Persistence/AbpWorkflowPersistenceProvider.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Persistence/AbpWorkflowPersistenceProvider.cs
index d9d89b885..7e2be5df5 100644
--- a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.Persistence/LINGYUN/Abp/WorkflowCore/Persistence/AbpWorkflowPersistenceProvider.cs
+++ b/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 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 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> 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 GetFirstOpenSubscription(
string eventName,
string eventKey,
@@ -153,6 +175,7 @@ namespace LINGYUN.Abp.WorkflowCore.Persistence
return workflowEventSubscription?.ToEventSubscription();
}
+ //[UnitOfWork]
public virtual async Task> 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> 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 GetSubscription(
string eventSubscriptionId,
CancellationToken cancellationToken = default)
@@ -195,6 +220,7 @@ namespace LINGYUN.Abp.WorkflowCore.Persistence
return subscription?.ToEventSubscription();
}
+ //[UnitOfWork]
public virtual async Task> 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 GetWorkflowInstance(
string Id,
CancellationToken cancellationToken = default)
@@ -223,6 +250,7 @@ namespace LINGYUN.Abp.WorkflowCore.Persistence
return workflow?.ToWorkflowInstance();
}
+ //[UnitOfWork]
public virtual async Task> 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> GetWorkflowInstances(
IEnumerable 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 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);
}
}
}
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.RabbitMQ/LINGYUN/Abp/WorkflowCore/RabbitMQ/AbpRabbitMqQueueProvider.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.RabbitMQ/LINGYUN/Abp/WorkflowCore/RabbitMQ/AbpRabbitMqQueueProvider.cs
index c6580fb61..a604fcf94 100644
--- a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.RabbitMQ/LINGYUN/Abp/WorkflowCore/RabbitMQ/AbpRabbitMqQueueProvider.cs
+++ b/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();
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.RabbitMQ/LINGYUN/Abp/WorkflowCore/RabbitMQ/AbpWorkflowCoreRabbitMQModule.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.RabbitMQ/LINGYUN/Abp/WorkflowCore/RabbitMQ/AbpWorkflowCoreRabbitMQModule.cs
index adda074f2..5d2d62f84 100644
--- a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore.RabbitMQ/LINGYUN/Abp/WorkflowCore/RabbitMQ/AbpWorkflowCoreRabbitMQModule.cs
+++ b/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();
- context.Services.AddSingleton();
-
- PreConfigure(options =>
- {
- options.UseQueueProvider(provider => provider.GetRequiredService());
- });
- }
-
- public override void OnApplicationShutdown(ApplicationShutdownContext context)
- {
- context.ServiceProvider
- .GetRequiredService()
- .Dispose();
- }
}
}
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/AbpUnitOfWorkQueueProvider.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/AbpUnitOfWorkQueueProvider.cs
new file mode 100644
index 000000000..a70b64cb4
--- /dev/null
+++ b/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
+{
+ ///
+ /// 当触发新的工作流时,如果持久层在事务中会导致默认队列获取工作流实例失败
+ /// 建立一个事务适配队列在工作单元结束时再将消息入队
+ ///
+ 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 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();
+ }
+ }
+}
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/AbpWorkflowCoreModule.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/AbpWorkflowCoreModule.cs
index 842085fb4..7ed821f8a 100644
--- a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/AbpWorkflowCoreModule.cs
+++ b/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();
+ context.Services.AddSingleton();
+
+ PreConfigure(options =>
+ {
+ options.UseQueueProvider(provider => provider.GetRequiredService());
+ });
+
AutoAddDefinitionWorkflows(context.Services);
}
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/IQueueAdapterProvider.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/IQueueAdapterProvider.cs
new file mode 100644
index 000000000..443119d54
--- /dev/null
+++ b/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 DequeueWork(QueueType queue, CancellationToken cancellationToken);
+
+ Task Start();
+
+ Task Stop();
+ }
+}
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/SingleNodeQueueAdapterProvider.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowCore/LINGYUN/Abp/WorkflowCore/SingleNodeQueueAdapterProvider.cs
new file mode 100644
index 000000000..836765990
--- /dev/null
+++ b/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> _queues = new Dictionary>
+ {
+ [QueueType.Workflow] = new BlockingCollection(),
+ [QueueType.Event] = new BlockingCollection(),
+ [QueueType.Index] = new BlockingCollection()
+ };
+
+ public bool IsDequeueBlocking => true;
+
+ public Task QueueWork(string id, QueueType queue)
+ {
+ _queues[queue].Add(id);
+ return Task.CompletedTask;
+ }
+
+ public Task DequeueWork(QueueType queue, CancellationToken cancellationToken)
+ {
+ if (_queues[queue].TryTake(out string id, 100, cancellationToken))
+ return Task.FromResult(id);
+
+ return Task.FromResult(null);
+ }
+
+ public Task Start()
+ {
+ return Task.CompletedTask;
+ }
+
+ public Task Stop()
+ {
+ return Task.CompletedTask;
+ }
+
+ public void Dispose()
+ {
+ }
+ }
+}
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Activitys/Dto/ActivityFailureInput.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Activitys/Dto/ActivityFailureInput.cs
new file mode 100644
index 000000000..1b7093101
--- /dev/null
+++ b/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; }
+ }
+}
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Activitys/Dto/ActivityReleaseInput.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Activitys/Dto/ActivityReleaseInput.cs
new file mode 100644
index 000000000..f58b3287e
--- /dev/null
+++ b/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; }
+ }
+}
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Activitys/Dto/ActivitySuccessInput.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Activitys/Dto/ActivitySuccessInput.cs
new file mode 100644
index 000000000..a32d959fb
--- /dev/null
+++ b/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; }
+ }
+}
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Activitys/Dto/GetPendingActivityInput.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Activitys/Dto/GetPendingActivityInput.cs
new file mode 100644
index 000000000..b7d8ed790
--- /dev/null
+++ b/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; }
+ }
+}
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Activitys/Dto/PendingActivityDto.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Activitys/Dto/PendingActivityDto.cs
new file mode 100644
index 000000000..cc44e87be
--- /dev/null
+++ b/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; }
+ }
+}
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Activitys/IActivityAppService.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Activitys/IActivityAppService.cs
new file mode 100644
index 000000000..c859ab989
--- /dev/null
+++ b/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 GetAsync(GetPendingActivityInput input);
+
+ Task DeleteAsync(ActivityReleaseInput input);
+
+ Task SuccessAsync(ActivitySuccessInput input);
+
+ Task FailureAsync(ActivityFailureInput input);
+ }
+}
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Events/Dto/EventPublishInput.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Events/Dto/EventPublishInput.cs
new file mode 100644
index 000000000..14f5c791d
--- /dev/null
+++ b/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; }
+ }
+}
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Events/IEventAppService.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Events/IEventAppService.cs
new file mode 100644
index 000000000..0f7181323
--- /dev/null
+++ b/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);
+ }
+}
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Workflows/Dto/StepDto.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Workflows/Dto/StepDto.cs
new file mode 100644
index 000000000..a79cab6c6
--- /dev/null
+++ b/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 CompensateWith { get; set; } = new List();
+ public ExtraPropertyDictionary Inputs { get; set; } = new ExtraPropertyDictionary();
+ public ExtraPropertyDictionary Outputs { get; set; } = new ExtraPropertyDictionary();
+ public ExtraPropertyDictionary SelectNextStep { get; set; } = new ExtraPropertyDictionary();
+ }
+}
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Workflows/Dto/WorkflowCreateDto.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Workflows/Dto/WorkflowCreateDto.cs
new file mode 100644
index 000000000..97e93e3b7
--- /dev/null
+++ b/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
+ {
+ ///
+ /// 是否启用
+ ///
+ public bool IsEnabled { get; set; }
+ ///
+ /// 名称
+ ///
+ public string Name { get; set; }
+ ///
+ /// 显示名称
+ ///
+ public string DisplayName { get; set; }
+ ///
+ /// 描述
+ ///
+ public string Description { get; set; }
+ ///
+ /// 版本号
+ ///
+ public int Version { get; set; }
+
+ public List Steps { get; set; } = new List();
+ }
+}
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Workflows/Dto/WorkflowDefinitionDto.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Workflows/Dto/WorkflowDefinitionDto.cs
new file mode 100644
index 000000000..1f24f85f3
--- /dev/null
+++ b/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
+ {
+ ///
+ /// 描述
+ ///
+ public string Description { get; set; }
+ ///
+ /// 版本号
+ ///
+ public int Version { get; set; }
+
+ public List Steps { get; set; } = new List();
+ }
+}
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Workflows/Dto/WorkflowDto.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Workflows/Dto/WorkflowDto.cs
new file mode 100644
index 000000000..180bf462a
--- /dev/null
+++ b/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; }
+ }
+}
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Workflows/Dto/WorkflowStartInput.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Workflows/Dto/WorkflowStartInput.cs
new file mode 100644
index 000000000..d8f5b40e5
--- /dev/null
+++ b/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 Data { get; set; }
+ }
+}
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Workflows/IWorkflowAppService.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application.Contracts/LINGYUN/Abp/WorkflowManagement/Workflows/IWorkflowAppService.cs
new file mode 100644
index 000000000..0d878cfe0
--- /dev/null
+++ b/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 GetAsync(string id);
+
+ Task CreateAsync(WorkflowCreateDto input);
+
+ Task StartAsync(string id, WorkflowStartInput input);
+
+ Task SuspendAsync(string id);
+
+ Task ResumeAsync(string id);
+
+ Task TerminateAsync(string id);
+ }
+}
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application/LINGYUN/Abp/WorkflowManagement/Activitys/ActivityAppService.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application/LINGYUN/Abp/WorkflowManagement/Activitys/ActivityAppService.cs
new file mode 100644
index 000000000..d8c921907
--- /dev/null
+++ b/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 GetAsync(GetPendingActivityInput input)
+ {
+ var activity = await _controller.GetPendingActivity(
+ input.ActivityName, input.WorkflowId, input.Timeout);
+
+ return ObjectMapper.Map(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);
+ }
+ }
+}
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application/LINGYUN/Abp/WorkflowManagement/Events/EventAppService.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application/LINGYUN/Abp/WorkflowManagement/Events/EventAppService.cs
new file mode 100644
index 000000000..dd3931881
--- /dev/null
+++ b/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);
+ }
+ }
+}
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application/LINGYUN/Abp/WorkflowManagement/WorkflowManagementApplicationMapperProfile.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application/LINGYUN/Abp/WorkflowManagement/WorkflowManagementApplicationMapperProfile.cs
index 2bb35efe9..6312d2f5a 100644
--- a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application/LINGYUN/Abp/WorkflowManagement/WorkflowManagementApplicationMapperProfile.cs
+++ b/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()
+ .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();
}
}
}
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application/LINGYUN/Abp/WorkflowManagement/Workflows/WorkflowAppService.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Application/LINGYUN/Abp/WorkflowManagement/Workflows/WorkflowAppService.cs
new file mode 100644
index 000000000..fc34c6c64
--- /dev/null
+++ b/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 GetAsync(string id)
+ {
+ var workflow = await _persistence.GetWorkflowInstance(id);
+
+ return ObjectMapper.Map(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();
+ var stepCompensateNodes = new List();
+
+ ICollection CreateCompensateNodes(StepNode node, ICollection steps)
+ {
+ var stepNodes = new List();
+ 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 StartAsync(string id, WorkflowStartInput input)
+ {
+ var workflowData = new Dictionary();
+ foreach (var data in input.Data)
+ {
+ if (data.Value is JsonElement element)
+ {
+ //var dataDic = new Dictionary();
+ //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(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();
+ }
+ }
+ }
+}
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain.Shared/LINGYUN/Abp/WorkflowManagement/WorkflowConsts.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain.Shared/LINGYUN/Abp/WorkflowManagement/WorkflowConsts.cs
new file mode 100644
index 000000000..d1055cfcd
--- /dev/null
+++ b/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;
+ }
+}
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/CompensateNode.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/CompensateNode.cs
new file mode 100644
index 000000000..c1e79a13c
--- /dev/null
+++ b/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)
+ {
+ }
+ }
+}
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/ICompensateNodeRepository.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/ICompensateNodeRepository.cs
new file mode 100644
index 000000000..d9c7d1f7f
--- /dev/null
+++ b/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
+ {
+ Task> GetAllChildrenWithWorkflowAsync(
+ Guid workflowId,
+ CancellationToken cancellationToken = default);
+ }
+}
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/IStep.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/IStep.cs
new file mode 100644
index 000000000..a0e35a309
--- /dev/null
+++ b/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; }
+ }
+}
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/IStepNodeRepository.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/IStepNodeRepository.cs
new file mode 100644
index 000000000..f800795c1
--- /dev/null
+++ b/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
+ {
+ Task> GetAllChildrenWithWorkflowAsync(
+ Guid workflowId,
+ CancellationToken cancellationToken = default);
+ }
+}
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/IWorkflowRepository.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/IWorkflowRepository.cs
new file mode 100644
index 000000000..348804633
--- /dev/null
+++ b/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
+ {
+ Task CheckVersionAsync(
+ string name,
+ int version,
+ CancellationToken cancellationToken = default);
+ }
+}
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/Step.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/Step.cs
index 3fc65ef3a..c310257f2 100644
--- a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/Step.cs
+++ b/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, IMultiTenant
+ public abstract class Step : Entity, 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();
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/StepNode.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/StepNode.cs
new file mode 100644
index 000000000..0862881d4
--- /dev/null
+++ b/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)
+ {
+ }
+ }
+}
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/Workflow.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/Workflow.cs
index abebeb49b..098c42a82 100644
--- a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/Workflow.cs
+++ b/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
///
public virtual bool IsEnabled { get; protected set; }
///
+ /// 名称
+ ///
+ public virtual string Name { get; set; }
+ ///
/// 显示名称
///
public virtual string DisplayName { get; set; }
@@ -30,16 +35,31 @@ namespace LINGYUN.Abp.WorkflowManagement
///
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;
}
}
}
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/WorkflowManagementDbProperties.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/WorkflowManagementDbProperties.cs
index 2f85c3451..4775e8a57 100644
--- a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/WorkflowManagementDbProperties.cs
+++ b/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;
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/WorkflowManagementDomainModule.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/WorkflowManagementDomainModule.cs
index 9e3dede8e..2bb687818 100644
--- a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/WorkflowManagementDomainModule.cs
+++ b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/WorkflowManagementDomainModule.cs
@@ -21,7 +21,10 @@ namespace LINGYUN.Abp.WorkflowManagement
Configure(options =>
{
+
});
+
+ context.Services.AddHostedService();
}
}
}
diff --git a/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/WorkflowManager.cs b/aspnet-core/modules/workflow/LINGYUN.Abp.WorkflowManagement.Domain/LINGYUN/Abp/WorkflowManagement/WorkflowManager.cs
new file mode 100644
index 000000000..953bd52cc
--- /dev/null
+++ b/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 steps,
+ ICollection compensates)
+ {
+ var dataType = typeof(Dictionary);
+ 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 ConvertSteps(
+ ICollection steps,
+ ICollection compensates)
+ {
+ var nodes = new List();
+
+ 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 ConvertCompensateSteps(
+ ICollection compensates)
+ {
+ var nodes = new List();
+
+ 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 source, Type dataType)
+ {
+ var result = new WorkflowStepCollection();
+ int i = 0;
+ var stack = new Stack(source.Reverse());
+ var parents = new List();
+ var compensatables = new List();
+
+ 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())
+ stack.Push(child);
+ }
+
+ if (nextStep.Do.Count > 0)
+ parents.Add(nextStep);
+ }
+
+ if (nextStep.CompensateWith != null)
+ {
+ foreach (var compChild in nextStep.CompensateWith.Reverse())
+ 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(acn));
+ continue;
+ }
+
+ if ((input.Value is IDictionary) || (input.Value is IDictionary