73 changed files with 4074 additions and 46 deletions
@ -1,32 +1,13 @@ |
|||||
using Microsoft.Extensions.DependencyInjection; |
using Volo.Abp.Modularity; |
||||
using Volo.Abp; |
|
||||
using Volo.Abp.Modularity; |
|
||||
using Volo.Abp.RabbitMQ; |
using Volo.Abp.RabbitMQ; |
||||
using WorkflowCore.Interface; |
using Volo.Abp.Uow; |
||||
using WorkflowCore.Models; |
|
||||
|
|
||||
namespace LINGYUN.Abp.WorkflowCore.RabbitMQ |
namespace LINGYUN.Abp.WorkflowCore.RabbitMQ |
||||
{ |
{ |
||||
|
[DependsOn(typeof(AbpUnitOfWorkModule))] |
||||
[DependsOn(typeof(AbpRabbitMqModule))] |
[DependsOn(typeof(AbpRabbitMqModule))] |
||||
[DependsOn(typeof(AbpWorkflowCoreModule))] |
[DependsOn(typeof(AbpWorkflowCoreModule))] |
||||
public class AbpWorkflowCoreRabbitMQModule : AbpModule |
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(); |
|
||||
} |
|
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -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(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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(); |
||||
|
} |
||||
|
} |
||||
@ -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() |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,7 @@ |
|||||
|
namespace LINGYUN.Abp.WorkflowManagement.Activitys |
||||
|
{ |
||||
|
public class ActivityReleaseInput |
||||
|
{ |
||||
|
public string Token { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -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; } |
||||
|
} |
||||
|
} |
||||
@ -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; } |
||||
|
} |
||||
|
} |
||||
@ -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; } |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
@ -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; } |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
@ -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(); |
||||
|
} |
||||
|
} |
||||
@ -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>(); |
||||
|
} |
||||
|
} |
||||
@ -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>(); |
||||
|
} |
||||
|
} |
||||
@ -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; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WorkflowManagement.Workflows |
||||
|
{ |
||||
|
public class WorkflowStartInput |
||||
|
{ |
||||
|
public Dictionary<string, object> Data { get; set; } |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
@ -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) |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
@ -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; } |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
@ -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) |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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"] |
||||
@ -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(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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> |
||||
@ -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
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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
|
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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(); |
||||
|
} |
||||
|
} |
||||
@ -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" |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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 |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -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" |
||||
|
} |
||||
|
} |
||||
|
] |
||||
|
} |
||||
|
} |
||||
@ -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}" |
||||
|
} |
||||
|
} |
||||
|
] |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1 @@ |
|||||
|
dapr run --app-id workflow --app-port 30035 -H 36550 -- dotnet run --no-build |
||||
Loading…
Reference in new issue