97 changed files with 1482 additions and 9578 deletions
@ -0,0 +1,32 @@ |
|||||
|
using Microsoft.Extensions.Options; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using Volo.Abp.Cli; |
||||
|
using Volo.Abp.Cli.Args; |
||||
|
using Volo.Abp.Cli.Commands; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Cli.Commands |
||||
|
{ |
||||
|
[Dependency(ReplaceServices = true)] |
||||
|
public class CommandSelector : ICommandSelector, ITransientDependency |
||||
|
{ |
||||
|
protected AbpCliOptions Options { get; } |
||||
|
|
||||
|
public CommandSelector(IOptions<AbpCliOptions> options) |
||||
|
{ |
||||
|
Options = options.Value; |
||||
|
} |
||||
|
|
||||
|
public Type Select(CommandLineArgs commandLineArgs) |
||||
|
{ |
||||
|
if (commandLineArgs.Command.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
return typeof(HelpCommand); |
||||
|
} |
||||
|
|
||||
|
return Options.Commands.GetOrDefault(commandLineArgs.Command) |
||||
|
?? typeof(HelpCommand); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,98 @@ |
|||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Microsoft.Extensions.Logging; |
||||
|
using Microsoft.Extensions.Logging.Abstractions; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using System.Linq; |
||||
|
using System.Text; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Cli; |
||||
|
using Volo.Abp.Cli.Args; |
||||
|
using Volo.Abp.Cli.Commands; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace LINGYUN.Abp.Cli.Commands |
||||
|
{ |
||||
|
public class HelpCommand : IConsoleCommand, ITransientDependency |
||||
|
{ |
||||
|
public ILogger<HelpCommand> Logger { get; set; } |
||||
|
protected AbpCliOptions AbpCliOptions { get; } |
||||
|
protected IServiceScopeFactory ServiceScopeFactory { get; } |
||||
|
|
||||
|
public HelpCommand(IOptions<AbpCliOptions> cliOptions, |
||||
|
IServiceScopeFactory serviceScopeFactory) |
||||
|
{ |
||||
|
ServiceScopeFactory = serviceScopeFactory; |
||||
|
Logger = NullLogger<HelpCommand>.Instance; |
||||
|
AbpCliOptions = cliOptions.Value; |
||||
|
} |
||||
|
|
||||
|
public Task ExecuteAsync(CommandLineArgs commandLineArgs) |
||||
|
{ |
||||
|
if (string.IsNullOrWhiteSpace(commandLineArgs.Target)) |
||||
|
{ |
||||
|
Logger.LogInformation(GetUsageInfo()); |
||||
|
return Task.CompletedTask; |
||||
|
} |
||||
|
|
||||
|
if (!AbpCliOptions.Commands.ContainsKey(commandLineArgs.Target)) |
||||
|
{ |
||||
|
Logger.LogWarning($"There is no command named {commandLineArgs.Target}."); |
||||
|
Logger.LogInformation(GetUsageInfo()); |
||||
|
return Task.CompletedTask; |
||||
|
} |
||||
|
|
||||
|
var commandType = AbpCliOptions.Commands[commandLineArgs.Target]; |
||||
|
|
||||
|
using (var scope = ServiceScopeFactory.CreateScope()) |
||||
|
{ |
||||
|
var command = (IConsoleCommand)scope.ServiceProvider.GetRequiredService(commandType); |
||||
|
Logger.LogInformation(command.GetUsageInfo()); |
||||
|
} |
||||
|
|
||||
|
return Task.CompletedTask; |
||||
|
} |
||||
|
|
||||
|
public string GetUsageInfo() |
||||
|
{ |
||||
|
var sb = new StringBuilder(); |
||||
|
|
||||
|
sb.AppendLine(""); |
||||
|
sb.AppendLine("Usage:"); |
||||
|
sb.AppendLine(""); |
||||
|
sb.AppendLine(" labp <command> <target> [options]"); |
||||
|
sb.AppendLine(""); |
||||
|
sb.AppendLine("Command List:"); |
||||
|
sb.AppendLine(""); |
||||
|
|
||||
|
foreach (var command in AbpCliOptions.Commands.ToArray()) |
||||
|
{ |
||||
|
string shortDescription; |
||||
|
|
||||
|
using (var scope = ServiceScopeFactory.CreateScope()) |
||||
|
{ |
||||
|
shortDescription = ((IConsoleCommand)scope.ServiceProvider |
||||
|
.GetRequiredService(command.Value)).GetShortDescription(); |
||||
|
} |
||||
|
|
||||
|
sb.Append(" > "); |
||||
|
sb.Append(command.Key); |
||||
|
sb.Append(string.IsNullOrWhiteSpace(shortDescription) ? "" : ":"); |
||||
|
sb.Append(" "); |
||||
|
sb.AppendLine(shortDescription); |
||||
|
} |
||||
|
|
||||
|
sb.AppendLine(""); |
||||
|
sb.AppendLine("To get a detailed help for a command:"); |
||||
|
sb.AppendLine(""); |
||||
|
sb.AppendLine(" labp help <command>"); |
||||
|
sb.AppendLine(""); |
||||
|
|
||||
|
return sb.ToString(); |
||||
|
} |
||||
|
|
||||
|
public string GetShortDescription() |
||||
|
{ |
||||
|
return "Show command line help. Write ` labp help <command> `"; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,20 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\configureawait.props" /> |
||||
|
<Import Project="..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netstandard2.0</TargetFramework> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Volo.Abp.Emailing" Version="$(VoloAbpPackageVersion)" /> |
||||
|
<PackageReference Include="Volo.Abp.Sms" Version="$(VoloAbpPackageVersion)" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\LINGYUN.Abp.WorkflowCore\LINGYUN.Abp.WorkflowCore.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,14 @@ |
|||||
|
using Volo.Abp.Emailing; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Volo.Abp.Sms; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WorkflowCore.Components |
||||
|
{ |
||||
|
[DependsOn( |
||||
|
typeof(AbpSmsModule), |
||||
|
typeof(AbpEmailingModule), |
||||
|
typeof(AbpWorkflowCoreModule))] |
||||
|
public class AbpWorkflowCoreComponentsModule : AbpModule |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,60 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Microsoft.Extensions.Logging; |
||||
|
using Microsoft.Extensions.Logging.Abstractions; |
||||
|
using System; |
||||
|
using System.Globalization; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Emailing; |
||||
|
using Volo.Abp.Emailing.Templates; |
||||
|
using Volo.Abp.TextTemplating; |
||||
|
using WorkflowCore.Interface; |
||||
|
using WorkflowCore.Models; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WorkflowCore.Components.Primitives |
||||
|
{ |
||||
|
public class EmailStepBody : StepBodyAsyncBase |
||||
|
{ |
||||
|
public ILogger<EmailStepBody> Logger { protected get; set; } |
||||
|
|
||||
|
private readonly IEmailSender _emailSender; |
||||
|
private readonly ITemplateRenderer _templateRenderer; |
||||
|
|
||||
|
public EmailStepBody( |
||||
|
IEmailSender emailSender, |
||||
|
ITemplateRenderer templateRenderer) |
||||
|
{ |
||||
|
_emailSender = emailSender; |
||||
|
_templateRenderer = templateRenderer; |
||||
|
|
||||
|
Logger = NullLogger<EmailStepBody>.Instance; |
||||
|
} |
||||
|
|
||||
|
[NotNull] |
||||
|
public string Title { get; set; } |
||||
|
|
||||
|
[NotNull] |
||||
|
public string Receivers { get; set; } |
||||
|
|
||||
|
[CanBeNull] |
||||
|
public object Data { get; set; } |
||||
|
|
||||
|
[CanBeNull] |
||||
|
public string Template { get; set; } |
||||
|
|
||||
|
public override async Task<ExecutionResult> RunAsync(IStepExecutionContext context) |
||||
|
{ |
||||
|
Logger.LogInformation("Working on sending email step."); |
||||
|
|
||||
|
var templateContent = await _templateRenderer.RenderAsync( |
||||
|
Template.IsNullOrWhiteSpace() ? StandardEmailTemplates.Message : Template, |
||||
|
Data, |
||||
|
CultureInfo.CurrentCulture.Name); |
||||
|
|
||||
|
await _emailSender.SendAsync(Receivers, Title, templateContent); |
||||
|
|
||||
|
Logger.LogInformation("Email sent, forward to next step."); |
||||
|
|
||||
|
return ExecutionResult.Next(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,51 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using Microsoft.Extensions.Logging; |
||||
|
using Microsoft.Extensions.Logging.Abstractions; |
||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Sms; |
||||
|
using WorkflowCore.Interface; |
||||
|
using WorkflowCore.Models; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WorkflowCore.Components.Primitives |
||||
|
{ |
||||
|
public class SmsStepBody : StepBodyAsyncBase |
||||
|
{ |
||||
|
public ILogger<SmsStepBody> Logger { protected get; set; } |
||||
|
|
||||
|
|
||||
|
private readonly ISmsSender _smsSender; |
||||
|
|
||||
|
public SmsStepBody(ISmsSender smsSender) |
||||
|
{ |
||||
|
_smsSender = smsSender; |
||||
|
|
||||
|
Logger = NullLogger<SmsStepBody>.Instance; |
||||
|
} |
||||
|
|
||||
|
[NotNull] |
||||
|
public string Message { get; set; } |
||||
|
|
||||
|
[NotNull] |
||||
|
public string PhoneNumber { get; set; } |
||||
|
|
||||
|
[CanBeNull] |
||||
|
public string Template { get; set; } |
||||
|
|
||||
|
public override async Task<ExecutionResult> RunAsync(IStepExecutionContext context) |
||||
|
{ |
||||
|
Logger.LogInformation("Working on sending sms message step."); |
||||
|
|
||||
|
var smsMessage = new SmsMessage(PhoneNumber, Message); |
||||
|
if (!Template.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
smsMessage.Properties.Add("TemplateCode", Template); |
||||
|
} |
||||
|
await _smsSender.SendAsync(smsMessage); |
||||
|
|
||||
|
Logger.LogInformation("Sms message sent, forward to next step."); |
||||
|
|
||||
|
return ExecutionResult.Next(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
# LINGYUN.Abp.WorkflowCore.Components |
||||
|
|
||||
|
预设的工作流组件 |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,20 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\configureawait.props" /> |
||||
|
<Import Project="..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netstandard2.0</TargetFramework> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Microsoft.Extensions.Caching.Abstractions" Version="$(MicrosoftPackageVersion)" /> |
||||
|
<PackageReference Include="Volo.Abp.DistributedLocking" Version="$(VoloAbpPackageVersion)" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\LINGYUN.Abp.WorkflowCore\LINGYUN.Abp.WorkflowCore.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,73 @@ |
|||||
|
using Microsoft.Extensions.Caching.Memory; |
||||
|
using System; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.DistributedLocking; |
||||
|
using WorkflowCore.Interface; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WorkflowCore.DistributedLock |
||||
|
{ |
||||
|
public class AbpDistributedLockProvider : IDistributedLockProvider |
||||
|
{ |
||||
|
private readonly IMemoryCache _lockCache; |
||||
|
private readonly IAbpDistributedLock _distributedLock; |
||||
|
|
||||
|
private readonly TimeSpan _lockTimeout = TimeSpan.FromMinutes(1); |
||||
|
|
||||
|
public AbpDistributedLockProvider( |
||||
|
IMemoryCache memoryCache, |
||||
|
IAbpDistributedLock abpDistributedLock) |
||||
|
{ |
||||
|
_lockCache = memoryCache; |
||||
|
_distributedLock = abpDistributedLock; |
||||
|
} |
||||
|
|
||||
|
public virtual async Task<bool> AcquireLock(string Id, CancellationToken cancellationToken) |
||||
|
{ |
||||
|
var handle = await _distributedLock.TryAcquireAsync(Id, _lockTimeout, cancellationToken); |
||||
|
if (handle == null) |
||||
|
{ |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
var cacheItem = new LockCacheItem(Id, handle); |
||||
|
// 预留一点时间
|
||||
|
_lockCache.Set(Id, cacheItem, TimeSpan.FromMinutes(1.5d)); |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
public virtual async Task ReleaseLock(string Id) |
||||
|
{ |
||||
|
var cacheItem = _lockCache.Get<LockCacheItem>(Id); |
||||
|
if (cacheItem == null) |
||||
|
{ |
||||
|
await cacheItem.Handle.DisposeAsync(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public Task Start() |
||||
|
{ |
||||
|
return Task.CompletedTask; |
||||
|
} |
||||
|
|
||||
|
public Task Stop() |
||||
|
{ |
||||
|
return Task.CompletedTask; |
||||
|
} |
||||
|
|
||||
|
private class LockCacheItem |
||||
|
{ |
||||
|
public string Id { get; set; } |
||||
|
public IAbpDistributedLockHandle Handle { get; set; } |
||||
|
public LockCacheItem() { } |
||||
|
public LockCacheItem( |
||||
|
string id, |
||||
|
IAbpDistributedLockHandle handle) |
||||
|
{ |
||||
|
Id = id; |
||||
|
Handle = handle; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Volo.Abp.DistributedLocking; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using WorkflowCore.Interface; |
||||
|
using WorkflowCore.Models; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WorkflowCore.DistributedLock |
||||
|
{ |
||||
|
[DependsOn(typeof(AbpWorkflowCoreModule))] |
||||
|
[DependsOn(typeof(AbpDistributedLockingModule))] |
||||
|
public class AbpWorkflowCoreDistributedLockModule : AbpModule |
||||
|
{ |
||||
|
public override void PreConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
context.Services.AddSingleton<IDistributedLockProvider, AbpDistributedLockProvider>(); |
||||
|
context.Services.AddSingleton<AbpDistributedLockProvider>(); |
||||
|
|
||||
|
PreConfigure<WorkflowOptions>(options => |
||||
|
{ |
||||
|
options.UseDistributedLockManager(provider => provider.GetRequiredService<AbpDistributedLockProvider>()); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,9 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WorkflowCore.Emailing |
||||
|
{ |
||||
|
public class Class1 |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,15 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\configureawait.props" /> |
||||
|
<Import Project="..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netstandard2.0</TargetFramework> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\LINGYUN.Abp.WorkflowCore\LINGYUN.Abp.WorkflowCore.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -1,16 +1,19 @@ |
|||||
<Project Sdk="Microsoft.NET.Sdk"> |
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
<PropertyGroup> |
<Import Project="..\..\..\configureawait.props" /> |
||||
<TargetFramework>netstandard2.1</TargetFramework> |
<Import Project="..\..\..\common.props" /> |
||||
<RootNamespace /> |
|
||||
</PropertyGroup> |
<PropertyGroup> |
||||
|
<TargetFramework>net6.0</TargetFramework> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
<ItemGroup> |
<ItemGroup> |
||||
<PackageReference Include="Volo.Abp.EntityFrameworkCore" Version="4.4.0" /> |
<PackageReference Include="Volo.Abp.EntityFrameworkCore" Version="$(VoloAbpPackageVersion)" /> |
||||
</ItemGroup> |
</ItemGroup> |
||||
|
|
||||
<ItemGroup> |
<ItemGroup> |
||||
<ProjectReference Include="..\LINGYUN.Abp.WorkflowCore.Persistence\LINGYUN.Abp.WorkflowCore.Persistence.csproj" /> |
<ProjectReference Include="..\LINGYUN.Abp.WorkflowCore.Persistence\LINGYUN.Abp.WorkflowCore.Persistence.csproj" /> |
||||
</ItemGroup> |
</ItemGroup> |
||||
|
|
||||
</Project> |
</Project> |
||||
|
|||||
@ -1,14 +1,27 @@ |
|||||
using LINGYUN.Abp.WorkflowCore.Persistence.EntityFrameworkCore; |
using LINGYUN.Abp.WorkflowCore.Persistence.EntityFrameworkCore; |
||||
|
using Microsoft.EntityFrameworkCore; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
using Volo.Abp.Domain.Repositories.EntityFrameworkCore; |
using Volo.Abp.Domain.Repositories.EntityFrameworkCore; |
||||
using Volo.Abp.EntityFrameworkCore; |
using Volo.Abp.EntityFrameworkCore; |
||||
|
|
||||
namespace LINGYUN.Abp.WorkflowCore.Persistence |
namespace LINGYUN.Abp.WorkflowCore.Persistence |
||||
{ |
{ |
||||
public class EfCoreWorkflowScheduledCommandRepository : EfCoreRepository<WorkflowDbContext, WorkflowScheduledCommand, long>, IWorkflowScheduledCommandRepository |
public class EfCoreWorkflowScheduledCommandRepository : EfCoreRepository<WorkflowDbContext, PersistedScheduledCommand, long>, IWorkflowScheduledCommandRepository |
||||
{ |
{ |
||||
public EfCoreWorkflowScheduledCommandRepository(IDbContextProvider<WorkflowDbContext> dbContextProvider) |
public EfCoreWorkflowScheduledCommandRepository(IDbContextProvider<WorkflowDbContext> dbContextProvider) |
||||
: base(dbContextProvider) |
: base(dbContextProvider) |
||||
{ |
{ |
||||
} |
} |
||||
|
|
||||
|
public virtual async Task<bool> CheckExistsAsync( |
||||
|
string name, |
||||
|
string data, |
||||
|
CancellationToken cancellationToken = default) |
||||
|
{ |
||||
|
return await (await GetDbSetAsync()) |
||||
|
.AnyAsync(x => x.CommandName.Equals(name) && x.Data.Equals(data), |
||||
|
GetCancellationToken(cancellationToken)); |
||||
|
} |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -1,16 +1,19 @@ |
|||||
<Project Sdk="Microsoft.NET.Sdk"> |
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
<PropertyGroup> |
<Import Project="..\..\..\configureawait.props" /> |
||||
<TargetFramework>netstandard2.0</TargetFramework> |
<Import Project="..\..\..\common.props" /> |
||||
<RootNamespace /> |
|
||||
</PropertyGroup> |
<PropertyGroup> |
||||
|
<TargetFramework>netstandard2.0</TargetFramework> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
<ItemGroup> |
<ItemGroup> |
||||
<PackageReference Include="Volo.Abp.Ddd.Domain" Version="4.4.0" /> |
<PackageReference Include="Volo.Abp.Ddd.Domain" Version="$(VoloAbpPackageVersion)" /> |
||||
</ItemGroup> |
</ItemGroup> |
||||
|
|
||||
<ItemGroup> |
<ItemGroup> |
||||
<ProjectReference Include="..\LINGYUN.Abp.WorkflowCore\LINGYUN.Abp.WorkflowCore.csproj" /> |
<ProjectReference Include="..\LINGYUN.Abp.WorkflowCore\LINGYUN.Abp.WorkflowCore.csproj" /> |
||||
</ItemGroup> |
</ItemGroup> |
||||
|
|
||||
</Project> |
</Project> |
||||
|
|||||
@ -0,0 +1,292 @@ |
|||||
|
using Newtonsoft.Json; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
using Volo.Abp.Guids; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
using WorkflowCore.Models; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WorkflowCore.Persistence |
||||
|
{ |
||||
|
internal static class ExtensionMethods |
||||
|
{ |
||||
|
private static JsonSerializerSettings SerializerSettings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.All }; |
||||
|
|
||||
|
internal static PersistedWorkflow ToPersistable( |
||||
|
this WorkflowInstance instance, |
||||
|
IGuidGenerator generator, |
||||
|
ICurrentTenant currentTenant, |
||||
|
PersistedWorkflow persistable = null) |
||||
|
{ |
||||
|
if (persistable == null) |
||||
|
{ |
||||
|
persistable = new PersistedWorkflow( |
||||
|
generator.Create(), |
||||
|
instance.CreateTime, |
||||
|
instance.WorkflowDefinitionId, |
||||
|
JsonConvert.SerializeObject(instance.Data, SerializerSettings), |
||||
|
instance.Version, |
||||
|
instance.Description, |
||||
|
instance.Reference, |
||||
|
instance.Status, |
||||
|
instance.NextExecution, |
||||
|
instance.CompleteTime, |
||||
|
currentTenant.Id); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
persistable.Data = JsonConvert.SerializeObject(instance.Data, SerializerSettings); |
||||
|
persistable.Description = instance.Description; |
||||
|
persistable.Reference = instance.Reference; |
||||
|
persistable.NextExecution = instance.NextExecution; |
||||
|
persistable.Version = instance.Version; |
||||
|
persistable.WorkflowDefinitionId = instance.WorkflowDefinitionId; |
||||
|
persistable.Status = instance.Status; |
||||
|
persistable.CreationTime = instance.CreateTime; |
||||
|
persistable.CompleteTime = instance.CompleteTime; |
||||
|
} |
||||
|
|
||||
|
foreach (var ep in instance.ExecutionPointers) |
||||
|
{ |
||||
|
var epId = ep.Id.IsNullOrWhiteSpace() ? Guid.Empty : Guid.Parse(ep.Id); |
||||
|
var persistedEP = persistable.FindPointer(epId); |
||||
|
|
||||
|
if (persistedEP == null) |
||||
|
{ |
||||
|
persistedEP = new PersistedExecutionPointer( |
||||
|
generator.Create(), |
||||
|
persistable.Id, |
||||
|
ep.StepId, |
||||
|
ep.StepName, |
||||
|
ep.Active, |
||||
|
JsonConvert.SerializeObject(ep.PersistenceData, SerializerSettings), |
||||
|
ep.EventName, |
||||
|
ep.EventKey, |
||||
|
ep.EventPublished, |
||||
|
JsonConvert.SerializeObject(ep.EventData, SerializerSettings), |
||||
|
ep.RetryCount, |
||||
|
ep.Children.JoinAsString(";"), |
||||
|
JsonConvert.SerializeObject(ep.ContextItem, SerializerSettings), |
||||
|
ep.PredecessorId, |
||||
|
JsonConvert.SerializeObject(ep.Outcome, SerializerSettings), |
||||
|
ep.Scope.JoinAsString(";"), |
||||
|
ep.Status, |
||||
|
ep.SleepUntil, |
||||
|
ep.StartTime, |
||||
|
ep.EndTime, |
||||
|
currentTenant.Id); |
||||
|
|
||||
|
persistable.AddPointer(persistedEP); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
persistedEP.StepId = ep.StepId; |
||||
|
persistedEP.Active = ep.Active; |
||||
|
persistedEP.SleepUntil = ep.SleepUntil; |
||||
|
persistedEP.PersistenceData = JsonConvert.SerializeObject(ep.PersistenceData, SerializerSettings); |
||||
|
persistedEP.StartTime = ep.StartTime; |
||||
|
persistedEP.EndTime = ep.EndTime; |
||||
|
persistedEP.StepName = ep.StepName; |
||||
|
persistedEP.RetryCount = ep.RetryCount; |
||||
|
persistedEP.PredecessorId = ep.PredecessorId; |
||||
|
persistedEP.ContextItem = JsonConvert.SerializeObject(ep.ContextItem, SerializerSettings); |
||||
|
persistedEP.Children = ep.Children.JoinAsString(";"); |
||||
|
persistedEP.EventName = ep.EventName; |
||||
|
persistedEP.EventKey = ep.EventKey; |
||||
|
persistedEP.EventPublished = ep.EventPublished; |
||||
|
persistedEP.EventData = JsonConvert.SerializeObject(ep.EventData, SerializerSettings); |
||||
|
persistedEP.Outcome = JsonConvert.SerializeObject(ep.Outcome, SerializerSettings); |
||||
|
persistedEP.Status = ep.Status; |
||||
|
persistedEP.Scope = ep.Scope.JoinAsString(";"); |
||||
|
} |
||||
|
|
||||
|
foreach (var attr in ep.ExtensionAttributes) |
||||
|
{ |
||||
|
var persistedAttr = persistedEP.FindAttribute(attr.Key); |
||||
|
if (persistedAttr == null) |
||||
|
{ |
||||
|
persistedEP.AddAttribute(attr.Key, JsonConvert.SerializeObject(attr.Value, SerializerSettings)); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
persistedAttr.Key = attr.Key; |
||||
|
persistedAttr.Value = JsonConvert.SerializeObject(attr.Value, SerializerSettings); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return persistable; |
||||
|
} |
||||
|
|
||||
|
internal static PersistedExecutionError ToPersistable( |
||||
|
this ExecutionError instance, |
||||
|
ICurrentTenant currentTenant) |
||||
|
{ |
||||
|
var result = new PersistedExecutionError( |
||||
|
Guid.Parse(instance.WorkflowId), |
||||
|
Guid.Parse(instance.ExecutionPointerId), |
||||
|
instance.ErrorTime, |
||||
|
instance.Message, |
||||
|
currentTenant.Id); |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
internal static PersistedSubscription ToPersistable( |
||||
|
this EventSubscription instance, |
||||
|
IGuidGenerator generator, |
||||
|
ICurrentTenant currentTenant) |
||||
|
{ |
||||
|
PersistedSubscription result = new PersistedSubscription( |
||||
|
generator.Create(), |
||||
|
Guid.Parse(instance.WorkflowId), |
||||
|
instance.StepId, |
||||
|
Guid.Parse(instance.ExecutionPointerId), |
||||
|
instance.EventName, |
||||
|
instance.EventKey, |
||||
|
DateTime.SpecifyKind(instance.SubscribeAsOf, DateTimeKind.Utc), |
||||
|
JsonConvert.SerializeObject(instance.SubscriptionData, SerializerSettings), |
||||
|
instance.ExternalToken, |
||||
|
instance.ExternalWorkerId, |
||||
|
instance.ExternalTokenExpiry, |
||||
|
currentTenant.Id); |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
internal static PersistedEvent ToPersistable( |
||||
|
this Event instance, |
||||
|
IGuidGenerator generator, |
||||
|
ICurrentTenant currentTenant) |
||||
|
{ |
||||
|
PersistedEvent result = new PersistedEvent( |
||||
|
generator.Create(), |
||||
|
instance.EventName, |
||||
|
instance.EventKey, |
||||
|
JsonConvert.SerializeObject(instance.EventData, SerializerSettings), |
||||
|
DateTime.SpecifyKind(instance.EventTime, DateTimeKind.Utc), |
||||
|
currentTenant.Id); |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
internal static PersistedScheduledCommand ToPersistable( |
||||
|
this ScheduledCommand instance, |
||||
|
ICurrentTenant currentTenant) |
||||
|
{ |
||||
|
var result = new PersistedScheduledCommand( |
||||
|
instance.CommandName, |
||||
|
instance.Data, |
||||
|
instance.ExecuteTime, |
||||
|
currentTenant.Id); |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
internal static WorkflowInstance ToWorkflowInstance(this PersistedWorkflow instance) |
||||
|
{ |
||||
|
WorkflowInstance result = new WorkflowInstance(); |
||||
|
result.Data = JsonConvert.DeserializeObject(instance.Data, SerializerSettings); |
||||
|
result.Description = instance.Description; |
||||
|
result.Reference = instance.Reference; |
||||
|
result.Id = instance.Id.ToString(); |
||||
|
result.NextExecution = instance.NextExecution; |
||||
|
result.Version = instance.Version; |
||||
|
result.WorkflowDefinitionId = instance.WorkflowDefinitionId; |
||||
|
result.Status = instance.Status; |
||||
|
result.CreateTime = DateTime.SpecifyKind(instance.CreationTime, DateTimeKind.Utc); |
||||
|
if (instance.CompleteTime.HasValue) |
||||
|
result.CompleteTime = DateTime.SpecifyKind(instance.CompleteTime.Value, DateTimeKind.Utc); |
||||
|
|
||||
|
result.ExecutionPointers = new ExecutionPointerCollection(instance.ExecutionPointers.Count + 8); |
||||
|
|
||||
|
foreach (var ep in instance.ExecutionPointers) |
||||
|
{ |
||||
|
var pointer = new ExecutionPointer(); |
||||
|
|
||||
|
pointer.Id = ep.Id.ToString(); |
||||
|
pointer.StepId = ep.StepId; |
||||
|
pointer.Active = ep.Active; |
||||
|
|
||||
|
if (ep.SleepUntil.HasValue) |
||||
|
pointer.SleepUntil = DateTime.SpecifyKind(ep.SleepUntil.Value, DateTimeKind.Utc); |
||||
|
|
||||
|
pointer.PersistenceData = JsonConvert.DeserializeObject(ep.PersistenceData ?? string.Empty, SerializerSettings); |
||||
|
|
||||
|
if (ep.StartTime.HasValue) |
||||
|
pointer.StartTime = DateTime.SpecifyKind(ep.StartTime.Value, DateTimeKind.Utc); |
||||
|
|
||||
|
if (ep.EndTime.HasValue) |
||||
|
pointer.EndTime = DateTime.SpecifyKind(ep.EndTime.Value, DateTimeKind.Utc); |
||||
|
|
||||
|
pointer.StepName = ep.StepName; |
||||
|
|
||||
|
pointer.RetryCount = ep.RetryCount; |
||||
|
pointer.PredecessorId = ep.PredecessorId; |
||||
|
pointer.ContextItem = JsonConvert.DeserializeObject(ep.ContextItem ?? string.Empty, SerializerSettings); |
||||
|
|
||||
|
if (!string.IsNullOrEmpty(ep.Children)) |
||||
|
pointer.Children = ep.Children.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries).ToList(); |
||||
|
|
||||
|
pointer.EventName = ep.EventName; |
||||
|
pointer.EventKey = ep.EventKey; |
||||
|
pointer.EventPublished = ep.EventPublished; |
||||
|
pointer.EventData = JsonConvert.DeserializeObject(ep.EventData ?? string.Empty, SerializerSettings); |
||||
|
pointer.Outcome = JsonConvert.DeserializeObject(ep.Outcome ?? string.Empty, SerializerSettings); |
||||
|
pointer.Status = ep.Status; |
||||
|
|
||||
|
if (!string.IsNullOrEmpty(ep.Scope)) |
||||
|
pointer.Scope = new List<string>(ep.Scope.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)); |
||||
|
|
||||
|
foreach (var attr in ep.ExtensionAttributes) |
||||
|
{ |
||||
|
pointer.ExtensionAttributes[attr.Key] = JsonConvert.DeserializeObject(attr.Value, SerializerSettings); |
||||
|
} |
||||
|
|
||||
|
result.ExecutionPointers.Add(pointer); |
||||
|
} |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
internal static EventSubscription ToEventSubscription(this PersistedSubscription instance) |
||||
|
{ |
||||
|
EventSubscription result = new EventSubscription(); |
||||
|
result.Id = instance.Id.ToString(); |
||||
|
result.EventKey = instance.EventKey; |
||||
|
result.EventName = instance.EventName; |
||||
|
result.StepId = instance.StepId; |
||||
|
result.ExecutionPointerId = instance.ExecutionPointerId.ToString(); |
||||
|
result.WorkflowId = instance.WorkflowId.ToString(); |
||||
|
result.SubscribeAsOf = DateTime.SpecifyKind(instance.SubscribeAsOf, DateTimeKind.Utc); |
||||
|
result.SubscriptionData = JsonConvert.DeserializeObject(instance.SubscriptionData, SerializerSettings); |
||||
|
result.ExternalToken = instance.ExternalToken; |
||||
|
result.ExternalTokenExpiry = instance.ExternalTokenExpiry; |
||||
|
result.ExternalWorkerId = instance.ExternalWorkerId; |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
internal static Event ToEvent(this PersistedEvent instance) |
||||
|
{ |
||||
|
Event result = new Event(); |
||||
|
result.Id = instance.Id.ToString(); |
||||
|
result.EventKey = instance.EventKey; |
||||
|
result.EventName = instance.EventName; |
||||
|
result.EventTime = DateTime.SpecifyKind(instance.CreationTime, DateTimeKind.Utc); |
||||
|
result.IsProcessed = instance.IsProcessed; |
||||
|
result.EventData = JsonConvert.DeserializeObject(instance.EventData, SerializerSettings); |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
internal static ScheduledCommand ToScheduledCommand(this PersistedScheduledCommand instance) |
||||
|
{ |
||||
|
var result = new ScheduledCommand(); |
||||
|
result.CommandName = instance.CommandName; |
||||
|
result.Data = instance.Data; |
||||
|
result.ExecuteTime = instance.ExecuteTime; |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,8 +1,14 @@ |
|||||
using Volo.Abp.Domain.Repositories; |
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Domain.Repositories; |
||||
|
|
||||
namespace LINGYUN.Abp.WorkflowCore.Persistence |
namespace LINGYUN.Abp.WorkflowCore.Persistence |
||||
{ |
{ |
||||
public interface IWorkflowScheduledCommandRepository : IRepository<WorkflowScheduledCommand, long> |
public interface IWorkflowScheduledCommandRepository : IRepository<PersistedScheduledCommand, long> |
||||
{ |
{ |
||||
|
Task<bool> CheckExistsAsync( |
||||
|
string name, |
||||
|
string data, |
||||
|
CancellationToken cancellationToken = default); |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -0,0 +1,123 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Collections.ObjectModel; |
||||
|
using System.Linq; |
||||
|
using Volo.Abp.Domain.Entities; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
using WorkflowCore.Models; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WorkflowCore.Persistence |
||||
|
{ |
||||
|
public class PersistedExecutionPointer : Entity<Guid>, IMultiTenant |
||||
|
{ |
||||
|
public virtual Guid? TenantId { get; protected set; } |
||||
|
|
||||
|
public virtual Guid WorkflowId { get; protected set; } |
||||
|
|
||||
|
public virtual PersistedWorkflow Workflow { get; protected set; } |
||||
|
|
||||
|
public virtual int StepId { get; set; } |
||||
|
|
||||
|
public virtual bool Active { get; set; } |
||||
|
|
||||
|
public virtual DateTime? SleepUntil { get; set; } |
||||
|
|
||||
|
public virtual string PersistenceData { get; set; } |
||||
|
|
||||
|
public virtual DateTime? StartTime { get; set; } |
||||
|
|
||||
|
public virtual DateTime? EndTime { get; set; } |
||||
|
|
||||
|
public virtual string EventName { get; set; } |
||||
|
|
||||
|
public virtual string EventKey { get; set; } |
||||
|
|
||||
|
public virtual bool EventPublished { get; set; } |
||||
|
|
||||
|
public virtual string EventData { get; set; } |
||||
|
|
||||
|
public virtual string StepName { get; set; } |
||||
|
|
||||
|
public virtual int RetryCount { get; set; } |
||||
|
|
||||
|
public virtual string Children { get; set; } |
||||
|
|
||||
|
public virtual string ContextItem { get; set; } |
||||
|
|
||||
|
public virtual string PredecessorId { get; set; } |
||||
|
|
||||
|
public virtual string Outcome { get; set; } |
||||
|
|
||||
|
public virtual PointerStatus Status { get; set; } |
||||
|
|
||||
|
public virtual string Scope { get; set; } |
||||
|
|
||||
|
public virtual ICollection<PersistedExtensionAttribute> ExtensionAttributes { get; protected set; } |
||||
|
|
||||
|
protected PersistedExecutionPointer() |
||||
|
{ |
||||
|
ExtensionAttributes = new Collection<PersistedExtensionAttribute>(); |
||||
|
} |
||||
|
|
||||
|
public PersistedExecutionPointer( |
||||
|
Guid id, |
||||
|
Guid workflowId, |
||||
|
int stepId, |
||||
|
string stepName, |
||||
|
bool active, |
||||
|
string persistenceData, |
||||
|
string eventName, |
||||
|
string eventKey, |
||||
|
bool eventPublished, |
||||
|
string eventData, |
||||
|
int retryCount, |
||||
|
string children, |
||||
|
string contextItem, |
||||
|
string predecessorId, |
||||
|
string outcome, |
||||
|
string scope, |
||||
|
PointerStatus status = PointerStatus.Legacy, |
||||
|
DateTime? sleepUntil = null, |
||||
|
DateTime? startTime = null, |
||||
|
DateTime? endTime = null, |
||||
|
Guid? tenantId = null) : base(id) |
||||
|
{ |
||||
|
WorkflowId = workflowId; |
||||
|
StepId = stepId; |
||||
|
StepName = stepName; |
||||
|
Active = active; |
||||
|
PersistenceData = persistenceData; |
||||
|
EventName = eventName; |
||||
|
EventKey = eventKey; |
||||
|
EventPublished = eventPublished; |
||||
|
EventData = eventData; |
||||
|
RetryCount = retryCount; |
||||
|
Children = children; |
||||
|
ContextItem = contextItem; |
||||
|
PredecessorId = predecessorId; |
||||
|
Outcome = outcome; |
||||
|
Scope = scope; |
||||
|
Status = status; |
||||
|
SleepUntil = sleepUntil; |
||||
|
StartTime = startTime; |
||||
|
EndTime = endTime; |
||||
|
|
||||
|
TenantId = tenantId; |
||||
|
|
||||
|
ExtensionAttributes = new Collection<PersistedExtensionAttribute>(); |
||||
|
} |
||||
|
|
||||
|
public PersistedExtensionAttribute AddAttribute(string key, string value) |
||||
|
{ |
||||
|
var attr = new PersistedExtensionAttribute(Id, key, value); |
||||
|
ExtensionAttributes.Add(attr); |
||||
|
|
||||
|
return attr; |
||||
|
} |
||||
|
|
||||
|
public PersistedExtensionAttribute FindAttribute(string key) |
||||
|
{ |
||||
|
return ExtensionAttributes.FirstOrDefault(x => x.Key.Equals(key)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,66 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Collections.ObjectModel; |
||||
|
using System.Linq; |
||||
|
using Volo.Abp.Domain.Entities.Auditing; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
using WorkflowCore.Models; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WorkflowCore.Persistence |
||||
|
{ |
||||
|
public class PersistedWorkflow : AuditedAggregateRoot<Guid>, IMultiTenant |
||||
|
{ |
||||
|
public virtual Guid? TenantId { get; protected set; } |
||||
|
public virtual string WorkflowDefinitionId { get; set; } |
||||
|
public virtual int Version { get; set; } |
||||
|
public virtual string Description { get; set; } |
||||
|
public virtual string Reference { get; set; } |
||||
|
public virtual long? NextExecution { get; set; } |
||||
|
public virtual WorkflowStatus Status { get; set; } |
||||
|
public virtual string Data { get; set; } |
||||
|
public virtual DateTime? CompleteTime { get; set; } |
||||
|
public virtual ICollection<PersistedExecutionPointer> ExecutionPointers { get; protected set; } |
||||
|
|
||||
|
protected PersistedWorkflow() |
||||
|
{ |
||||
|
ExecutionPointers = new Collection<PersistedExecutionPointer>(); |
||||
|
} |
||||
|
|
||||
|
public PersistedWorkflow( |
||||
|
Guid id, |
||||
|
DateTime creationTime, |
||||
|
string defintionId, |
||||
|
string data, |
||||
|
int version, |
||||
|
string description, |
||||
|
string reference, |
||||
|
WorkflowStatus status, |
||||
|
long? nextExecution = null, |
||||
|
DateTime? completeTime = null, |
||||
|
Guid? tenantId = null) : base(id) |
||||
|
{ |
||||
|
Data = data; |
||||
|
CreationTime = creationTime; |
||||
|
WorkflowDefinitionId = defintionId; |
||||
|
Version = version; |
||||
|
Description = description; |
||||
|
Reference = reference; |
||||
|
NextExecution = nextExecution; |
||||
|
Status = status; |
||||
|
CompleteTime = completeTime; |
||||
|
TenantId = tenantId; |
||||
|
|
||||
|
ExecutionPointers = new Collection<PersistedExecutionPointer>(); |
||||
|
} |
||||
|
|
||||
|
public void AddPointer(PersistedExecutionPointer pointer) |
||||
|
{ |
||||
|
ExecutionPointers.Add(pointer); |
||||
|
} |
||||
|
|
||||
|
public PersistedExecutionPointer FindPointer(Guid id) |
||||
|
{ |
||||
|
return ExecutionPointers.FirstOrDefault(point => point.Id.Equals(id)); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,100 +0,0 @@ |
|||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Collections.ObjectModel; |
|
||||
using System.Linq; |
|
||||
using Volo.Abp.Domain.Entities.Auditing; |
|
||||
using Volo.Abp.Guids; |
|
||||
using Volo.Abp.MultiTenancy; |
|
||||
using WorkflowCore.Models; |
|
||||
|
|
||||
namespace LINGYUN.Abp.WorkflowCore.Persistence |
|
||||
{ |
|
||||
public class Workflow : AuditedAggregateRoot<Guid>, IMultiTenant |
|
||||
{ |
|
||||
public virtual Guid? TenantId { get; protected set; } |
|
||||
public virtual string WorkflowDefinitionId { get; protected set; } |
|
||||
public virtual int Version { get; protected set; } |
|
||||
public virtual string Description { get; protected set; } |
|
||||
public virtual string Reference { get; protected set; } |
|
||||
public virtual long? NextExecution { get; protected set; } |
|
||||
public virtual WorkflowStatus Status { get; protected set; } |
|
||||
public virtual string Data { get; protected set; } |
|
||||
public virtual DateTime? CompleteTime { get; protected set; } |
|
||||
public virtual ICollection<WorkflowExecutionPointer> ExecutionPointers { get; protected set; } |
|
||||
|
|
||||
protected Workflow() |
|
||||
{ |
|
||||
ExecutionPointers = new Collection<WorkflowExecutionPointer>(); |
|
||||
} |
|
||||
|
|
||||
public Workflow( |
|
||||
Guid id, |
|
||||
DateTime creationTime, |
|
||||
string defintionId, |
|
||||
string data, |
|
||||
int version, |
|
||||
string description, |
|
||||
string reference, |
|
||||
WorkflowStatus status, |
|
||||
long? nextExecution = null, |
|
||||
DateTime? completeTime = null, |
|
||||
Guid? tenantId = null) : base(id) |
|
||||
{ |
|
||||
Data = data; |
|
||||
CreationTime = creationTime; |
|
||||
WorkflowDefinitionId = defintionId; |
|
||||
Version = version; |
|
||||
Description = description; |
|
||||
Reference = reference; |
|
||||
NextExecution = nextExecution; |
|
||||
Status = status; |
|
||||
CompleteTime = completeTime; |
|
||||
TenantId = tenantId; |
|
||||
|
|
||||
ExecutionPointers = new Collection<WorkflowExecutionPointer>(); |
|
||||
} |
|
||||
|
|
||||
public void AddPointer(WorkflowExecutionPointer pointer) |
|
||||
{ |
|
||||
ExecutionPointers.Add(pointer); |
|
||||
} |
|
||||
|
|
||||
public WorkflowExecutionPointer FindPointer(Guid id) |
|
||||
{ |
|
||||
return ExecutionPointers.FirstOrDefault(point => point.Id.Equals(id)); |
|
||||
} |
|
||||
|
|
||||
public void Update( |
|
||||
WorkflowInstance instance, |
|
||||
IGuidGenerator guidGenerator, |
|
||||
ICurrentTenant currentTenant) |
|
||||
{ |
|
||||
Data = instance.Data.SerializeObject(); |
|
||||
CreationTime = instance.CreateTime; |
|
||||
WorkflowDefinitionId = instance.WorkflowDefinitionId; |
|
||||
Version = instance.Version; |
|
||||
Description = instance.Description; |
|
||||
Reference = instance.Reference; |
|
||||
NextExecution = instance.NextExecution; |
|
||||
Status = instance.Status; |
|
||||
CompleteTime = instance.CompleteTime; |
|
||||
|
|
||||
foreach (var pointer in instance.ExecutionPointers) |
|
||||
{ |
|
||||
if (!Guid.TryParse(pointer.Id, out Guid pointerId)) |
|
||||
{ |
|
||||
pointerId = guidGenerator.Create(); |
|
||||
} |
|
||||
|
|
||||
var currentPointer = FindPointer(pointerId); |
|
||||
if (currentPointer != null) |
|
||||
{ |
|
||||
currentPointer.Update(pointer); |
|
||||
continue; |
|
||||
} |
|
||||
|
|
||||
AddPointer(pointer.ToWorkflowExecutionPointer(this, guidGenerator, currentTenant)); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,159 +0,0 @@ |
|||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Collections.ObjectModel; |
|
||||
using System.Linq; |
|
||||
using Volo.Abp.Domain.Entities; |
|
||||
using Volo.Abp.MultiTenancy; |
|
||||
using WorkflowCore.Models; |
|
||||
|
|
||||
namespace LINGYUN.Abp.WorkflowCore.Persistence |
|
||||
{ |
|
||||
public class WorkflowExecutionPointer : Entity<Guid>, IMultiTenant |
|
||||
{ |
|
||||
public virtual Guid? TenantId { get; protected set; } |
|
||||
|
|
||||
public virtual Guid WorkflowId { get; protected set; } |
|
||||
|
|
||||
public virtual Workflow Workflow { get; protected set; } |
|
||||
|
|
||||
public virtual int StepId { get; protected set; } |
|
||||
|
|
||||
public virtual bool Active { get; protected set; } |
|
||||
|
|
||||
public virtual DateTime? SleepUntil { get; protected set; } |
|
||||
|
|
||||
public virtual string PersistenceData { get; protected set; } |
|
||||
|
|
||||
public virtual DateTime? StartTime { get; protected set; } |
|
||||
|
|
||||
public virtual DateTime? EndTime { get; protected set; } |
|
||||
|
|
||||
public virtual string EventName { get; protected set; } |
|
||||
|
|
||||
public virtual string EventKey { get; protected set; } |
|
||||
|
|
||||
public virtual bool EventPublished { get; protected set; } |
|
||||
|
|
||||
public virtual string EventData { get; protected set; } |
|
||||
|
|
||||
public virtual string StepName { get; protected set; } |
|
||||
|
|
||||
public virtual int RetryCount { get; protected set; } |
|
||||
|
|
||||
public virtual string Children { get; protected set; } |
|
||||
|
|
||||
public virtual string ContextItem { get; protected set; } |
|
||||
|
|
||||
public virtual string PredecessorId { get; protected set; } |
|
||||
|
|
||||
public virtual string Outcome { get; protected set; } |
|
||||
|
|
||||
public virtual PointerStatus Status { get; protected set; } |
|
||||
|
|
||||
public virtual string Scope { get; protected set; } |
|
||||
|
|
||||
public virtual ICollection<WorkflowExtensionAttribute> ExtensionAttributes { get; protected set; } |
|
||||
|
|
||||
protected WorkflowExecutionPointer() |
|
||||
{ |
|
||||
ExtensionAttributes = new Collection<WorkflowExtensionAttribute>(); |
|
||||
} |
|
||||
|
|
||||
public WorkflowExecutionPointer( |
|
||||
Guid id, |
|
||||
Guid workflowId, |
|
||||
int stepId, |
|
||||
string stepName, |
|
||||
bool active, |
|
||||
string persistenceData, |
|
||||
string eventName, |
|
||||
string eventKey, |
|
||||
bool eventPublished, |
|
||||
string eventData, |
|
||||
int retryCount, |
|
||||
string children, |
|
||||
string contextItem, |
|
||||
string predecessorId, |
|
||||
string outcome, |
|
||||
string scope, |
|
||||
PointerStatus status = PointerStatus.Legacy, |
|
||||
DateTime? sleepUntil = null, |
|
||||
DateTime? startTime = null, |
|
||||
DateTime? endTime = null, |
|
||||
Guid? tenantId = null) : base(id) |
|
||||
{ |
|
||||
WorkflowId = workflowId; |
|
||||
StepId = stepId; |
|
||||
StepName = stepName; |
|
||||
Active = active; |
|
||||
PersistenceData = persistenceData; |
|
||||
EventName = eventName; |
|
||||
EventKey = eventKey; |
|
||||
EventPublished = eventPublished; |
|
||||
EventData = eventData; |
|
||||
RetryCount = retryCount; |
|
||||
Children = children; |
|
||||
ContextItem = contextItem; |
|
||||
PredecessorId = predecessorId; |
|
||||
Outcome = outcome; |
|
||||
Scope = scope; |
|
||||
Status = status; |
|
||||
SleepUntil = sleepUntil; |
|
||||
StartTime = startTime; |
|
||||
EndTime = endTime; |
|
||||
|
|
||||
TenantId = tenantId; |
|
||||
|
|
||||
ExtensionAttributes = new Collection<WorkflowExtensionAttribute>(); |
|
||||
} |
|
||||
|
|
||||
public void Update(ExecutionPointer pointer) |
|
||||
{ |
|
||||
StepId = pointer.StepId; |
|
||||
StepName = pointer.StepName; |
|
||||
Active = pointer.Active; |
|
||||
PersistenceData = pointer.PersistenceData.SerializeObject(); |
|
||||
EventName = pointer.EventName; |
|
||||
EventKey = pointer.EventKey; |
|
||||
EventPublished = pointer.EventPublished; |
|
||||
EventData = pointer.EventData.SerializeObject(); |
|
||||
RetryCount = pointer.RetryCount; |
|
||||
Children = pointer.Children.JoinAsString(";"); |
|
||||
ContextItem = pointer.ContextItem.SerializeObject(); |
|
||||
PredecessorId = pointer.PredecessorId; |
|
||||
Outcome = pointer.Outcome.SerializeObject(); |
|
||||
Scope = pointer.Scope.JoinAsString(";"); |
|
||||
Status = pointer.Status; |
|
||||
SleepUntil = pointer.SleepUntil; |
|
||||
StartTime = pointer.StartTime; |
|
||||
EndTime = pointer.EndTime; |
|
||||
|
|
||||
foreach (var attribute in pointer.ExtensionAttributes) |
|
||||
{ |
|
||||
var findAttr = FindAttribute(attribute.Key); |
|
||||
if (findAttr == null) |
|
||||
{ |
|
||||
AddAttribute(attribute.Key, attribute.Value.SerializeObject()); |
|
||||
} |
|
||||
else |
|
||||
{ |
|
||||
findAttr.Key = attribute.Key; |
|
||||
findAttr.Value = attribute.Value.SerializeObject(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public WorkflowExtensionAttribute AddAttribute(string key, string value) |
|
||||
{ |
|
||||
var attr = new WorkflowExtensionAttribute(Id, key, value); |
|
||||
ExtensionAttributes.Add(attr); |
|
||||
|
|
||||
return attr; |
|
||||
} |
|
||||
|
|
||||
public WorkflowExtensionAttribute FindAttribute(string key) |
|
||||
{ |
|
||||
return ExtensionAttributes.FirstOrDefault(x => x.Key.Equals(key)); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,113 +0,0 @@ |
|||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Linq; |
|
||||
using WorkflowCore.Models; |
|
||||
|
|
||||
namespace LINGYUN.Abp.WorkflowCore.Persistence |
|
||||
{ |
|
||||
public static class WorkflowExtensions |
|
||||
{ |
|
||||
public static Event ToEvent(this WorkflowEvent workflowEvent) |
|
||||
{ |
|
||||
return new Event |
|
||||
{ |
|
||||
Id = workflowEvent.Id.ToString(), |
|
||||
EventName = workflowEvent.EventName, |
|
||||
EventKey = workflowEvent.EventKey, |
|
||||
EventTime = workflowEvent.CreationTime.ToUtcDateTime(), |
|
||||
IsProcessed = workflowEvent.IsProcessed, |
|
||||
EventData = workflowEvent.EventData.DeserializeObject() |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
public static EventSubscription ToEventSubscription(this WorkflowEventSubscription workflowEventSubscription) |
|
||||
{ |
|
||||
return new EventSubscription |
|
||||
{ |
|
||||
Id = workflowEventSubscription.Id.ToString(), |
|
||||
StepId = workflowEventSubscription.StepId, |
|
||||
SubscribeAsOf = workflowEventSubscription.SubscribeAsOf.ToUtcDateTime(), |
|
||||
SubscriptionData = workflowEventSubscription.SubscriptionData.DeserializeObject(), |
|
||||
EventKey = workflowEventSubscription.EventKey, |
|
||||
EventName = workflowEventSubscription.EventName, |
|
||||
ExecutionPointerId = workflowEventSubscription.ExecutionPointerId.ToString(), |
|
||||
ExternalWorkerId = workflowEventSubscription.ExternalWorkerId, |
|
||||
ExternalToken = workflowEventSubscription.ExternalToken, |
|
||||
ExternalTokenExpiry = workflowEventSubscription.ExternalTokenExpiry.ToNullableUtcDateTime(), |
|
||||
WorkflowId = workflowEventSubscription.WorkflowId.ToString() |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
public static WorkflowInstance ToWorkflowInstance(this Workflow workflow) |
|
||||
{ |
|
||||
return new WorkflowInstance |
|
||||
{ |
|
||||
Id = workflow.Id.ToString(), |
|
||||
WorkflowDefinitionId = workflow.WorkflowDefinitionId, |
|
||||
CompleteTime = workflow.CompleteTime.ToNullableUtcDateTime(), |
|
||||
CreateTime = workflow.CreationTime.ToUtcDateTime(), |
|
||||
Data = workflow.Data.DeserializeObject(), |
|
||||
Status = workflow.Status, |
|
||||
Description = workflow.Description, |
|
||||
NextExecution = workflow.NextExecution, |
|
||||
Reference = workflow.Reference, |
|
||||
Version = workflow.Version, |
|
||||
ExecutionPointers = new ExecutionPointerCollection( |
|
||||
workflow.ExecutionPointers |
|
||||
.Select(pointer => pointer.ToExecutionPointer()) |
|
||||
.ToList()) |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
public static ExecutionPointer ToExecutionPointer(this WorkflowExecutionPointer pointer) |
|
||||
{ |
|
||||
return new ExecutionPointer |
|
||||
{ |
|
||||
Id = pointer.Id.ToString(), |
|
||||
EventData = pointer.EventData.DeserializeObject(), |
|
||||
EventKey = pointer.StepName, |
|
||||
EventName = pointer.EventName, |
|
||||
EventPublished = pointer.EventPublished, |
|
||||
ExtensionAttributes = pointer.ExtensionAttributes.ToExtensionAttributes(), |
|
||||
Active = pointer.Active, |
|
||||
Children = pointer.Children.Split(';').ToList(), |
|
||||
ContextItem = pointer.ContextItem.DeserializeObject(), |
|
||||
Scope = pointer.Scope.Split(';').ToList(), |
|
||||
Outcome = pointer.Outcome.DeserializeObject(), |
|
||||
PersistenceData = pointer.PersistenceData.DeserializeObject(), |
|
||||
PredecessorId = pointer.PredecessorId, |
|
||||
RetryCount = pointer.RetryCount, |
|
||||
Status = pointer.Status, |
|
||||
StepId = pointer.StepId, |
|
||||
StepName = pointer.StepName, |
|
||||
EndTime = pointer.EndTime.ToNullableUtcDateTime(), |
|
||||
StartTime = pointer.StartTime.ToNullableUtcDateTime(), |
|
||||
SleepUntil = pointer.SleepUntil.ToNullableUtcDateTime(), |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
public static ScheduledCommand ToScheduledCommand( |
|
||||
this WorkflowScheduledCommand command) |
|
||||
{ |
|
||||
return new ScheduledCommand |
|
||||
{ |
|
||||
CommandName = command.CommandName, |
|
||||
Data = command.Data, |
|
||||
ExecuteTime = command.ExecuteTime |
|
||||
}; |
|
||||
} |
|
||||
|
|
||||
public static Dictionary<string, object> ToExtensionAttributes( |
|
||||
this ICollection<WorkflowExtensionAttribute> attributes) |
|
||||
{ |
|
||||
var attrDic = new Dictionary<string, object>(); |
|
||||
|
|
||||
foreach (var attr in attributes) |
|
||||
{ |
|
||||
attrDic.Add(attr.Key, attr.Value.DeserializeObject()); |
|
||||
} |
|
||||
|
|
||||
return attrDic; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,139 +0,0 @@ |
|||||
using LINGYUN.Abp.WorkflowCore.Persistence; |
|
||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using Volo.Abp.Guids; |
|
||||
using Volo.Abp.MultiTenancy; |
|
||||
|
|
||||
namespace WorkflowCore.Models |
|
||||
{ |
|
||||
public static class WorkflowExtensions |
|
||||
{ |
|
||||
public static Workflow ToWorkflow( |
|
||||
this WorkflowInstance instance, |
|
||||
IGuidGenerator generator, |
|
||||
ICurrentTenant currentTenant) |
|
||||
{ |
|
||||
var workflow = new Workflow( |
|
||||
generator.Create(), |
|
||||
instance.CreateTime, |
|
||||
instance.WorkflowDefinitionId, |
|
||||
instance.Data.SerializeObject(handlingString: true), |
|
||||
instance.Version, |
|
||||
instance.Description, |
|
||||
instance.Reference, |
|
||||
instance.Status, |
|
||||
instance.NextExecution, |
|
||||
instance.CompleteTime, |
|
||||
currentTenant.Id); |
|
||||
|
|
||||
foreach (var pointer in instance.ExecutionPointers) |
|
||||
{ |
|
||||
var toPointer = pointer.ToWorkflowExecutionPointer(workflow, generator, currentTenant); |
|
||||
workflow.AddPointer(toPointer); |
|
||||
} |
|
||||
|
|
||||
return workflow; |
|
||||
} |
|
||||
|
|
||||
public static WorkflowExecutionPointer ToWorkflowExecutionPointer( |
|
||||
this ExecutionPointer executionPointer, |
|
||||
Workflow workflow, |
|
||||
IGuidGenerator generator, |
|
||||
ICurrentTenant currentTenant) |
|
||||
{ |
|
||||
var pointer = new WorkflowExecutionPointer( |
|
||||
generator.Create(), |
|
||||
workflow.Id, |
|
||||
executionPointer.StepId, |
|
||||
executionPointer.StepName, |
|
||||
executionPointer.Active, |
|
||||
executionPointer.PersistenceData.SerializeObject(handlingString: true), |
|
||||
executionPointer.EventName, |
|
||||
executionPointer.EventKey, |
|
||||
executionPointer.EventPublished, |
|
||||
executionPointer.EventData.SerializeObject(handlingString: true), |
|
||||
executionPointer.RetryCount, |
|
||||
executionPointer.Children.JoinAsString(";"), |
|
||||
executionPointer.ContextItem.SerializeObject(handlingString: true), |
|
||||
executionPointer.PredecessorId, |
|
||||
executionPointer.Outcome.SerializeObject(handlingString: true), |
|
||||
executionPointer.Scope.JoinAsString(";"), |
|
||||
executionPointer.Status, |
|
||||
executionPointer.SleepUntil, |
|
||||
executionPointer.StartTime, |
|
||||
executionPointer.EndTime, |
|
||||
currentTenant.Id); |
|
||||
|
|
||||
foreach (var attribute in executionPointer.ExtensionAttributes) |
|
||||
{ |
|
||||
pointer.AddAttribute(attribute.Key, attribute.Value.SerializeObject(handlingString: true)); |
|
||||
} |
|
||||
|
|
||||
executionPointer.Id = pointer.Id.ToString(); |
|
||||
|
|
||||
return pointer; |
|
||||
} |
|
||||
|
|
||||
public static WorkflowEvent ToWorkflowEvent( |
|
||||
this Event @event, |
|
||||
IGuidGenerator generator, |
|
||||
ICurrentTenant currentTenant) |
|
||||
{ |
|
||||
var we = new WorkflowEvent( |
|
||||
generator.Create(), |
|
||||
@event.EventName, |
|
||||
@event.EventKey, |
|
||||
@event.EventData.SerializeObject(handlingString: true), |
|
||||
@event.EventTime, |
|
||||
currentTenant.Id) |
|
||||
{ |
|
||||
IsProcessed = @event.IsProcessed |
|
||||
}; |
|
||||
|
|
||||
return we; |
|
||||
} |
|
||||
|
|
||||
public static WorkflowEventSubscription ToWorkflowEventSubscription( |
|
||||
this EventSubscription subscription, |
|
||||
IGuidGenerator generator, |
|
||||
ICurrentTenant currentTenant) |
|
||||
{ |
|
||||
return new WorkflowEventSubscription( |
|
||||
generator.Create(), |
|
||||
Guid.Parse(subscription.WorkflowId), |
|
||||
subscription.StepId, |
|
||||
Guid.Parse(subscription.ExecutionPointerId), |
|
||||
subscription.EventName, |
|
||||
subscription.EventKey, |
|
||||
subscription.SubscribeAsOf, |
|
||||
subscription.SubscriptionData.SerializeObject(handlingString: true), |
|
||||
subscription.ExternalToken, |
|
||||
subscription.ExternalWorkerId, |
|
||||
subscription.ExternalTokenExpiry, |
|
||||
currentTenant.Id); |
|
||||
} |
|
||||
|
|
||||
public static WorkflowExecutionError ToWorkflowExecutionError( |
|
||||
this ExecutionError executionError, |
|
||||
ICurrentTenant currentTenant) |
|
||||
{ |
|
||||
return new WorkflowExecutionError( |
|
||||
Guid.Parse(executionError.WorkflowId), |
|
||||
Guid.Parse(executionError.ExecutionPointerId), |
|
||||
executionError.ErrorTime, |
|
||||
executionError.Message, |
|
||||
currentTenant.Id); |
|
||||
} |
|
||||
|
|
||||
public static WorkflowScheduledCommand ToWorkflowScheduledCommand( |
|
||||
this ScheduledCommand command, |
|
||||
ICurrentTenant currentTenant) |
|
||||
{ |
|
||||
return new WorkflowScheduledCommand( |
|
||||
command.CommandName, |
|
||||
command.Data, |
|
||||
command.ExecuteTime, |
|
||||
currentTenant.Id); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -1,11 +1,24 @@ |
|||||
using System; |
using Microsoft.Extensions.DependencyInjection; |
||||
using System.Collections.Generic; |
using System; |
||||
using System.Text; |
|
||||
using Volo.Abp.DependencyInjection; |
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
namespace LINGYUN.Abp.WorkflowCore |
namespace LINGYUN.Abp.WorkflowCore |
||||
{ |
{ |
||||
public class AbpWorkflowCoreConventionalRegistrar : DefaultConventionalRegistrar |
public class AbpWorkflowCoreConventionalRegistrar : DefaultConventionalRegistrar |
||||
{ |
{ |
||||
|
protected override bool IsConventionalRegistrationDisabled(Type type) |
||||
|
{ |
||||
|
return !IsWorkflowComponent(type) || base.IsConventionalRegistrationDisabled(type); |
||||
|
} |
||||
|
|
||||
|
private static bool IsWorkflowComponent(Type type) |
||||
|
{ |
||||
|
return type.IsWorkflow() || type.IsStepBody(); |
||||
|
} |
||||
|
|
||||
|
protected override ServiceLifetime? GetDefaultLifeTimeOrNull(Type type) |
||||
|
{ |
||||
|
return ServiceLifetime.Transient; |
||||
|
} |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -1,10 +1,11 @@ |
|||||
using Volo.Abp.Collections; |
namespace LINGYUN.Abp.WorkflowCore |
||||
using WorkflowCore.Interface; |
|
||||
|
|
||||
namespace LINGYUN.Abp.WorkflowCore |
|
||||
{ |
{ |
||||
public class AbpWorkflowCoreOptions |
public class AbpWorkflowCoreOptions |
||||
{ |
{ |
||||
public ITypeList<IWorkflow> DefinitionProviders { get; } |
public bool IsEnabled { get; set; } |
||||
|
public AbpWorkflowCoreOptions() |
||||
|
{ |
||||
|
IsEnabled = true; |
||||
|
} |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -1,10 +0,0 @@ |
|||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Text; |
|
||||
|
|
||||
namespace LINGYUN.Abp.WorkflowCore |
|
||||
{ |
|
||||
public interface IWorkflowManager |
|
||||
{ |
|
||||
} |
|
||||
} |
|
||||
@ -1,14 +0,0 @@ |
|||||
using Volo.Abp.DependencyInjection; |
|
||||
using WorkflowCore.Interface; |
|
||||
using WorkflowCore.Models; |
|
||||
|
|
||||
namespace LINGYUN.Abp.WorkflowCore |
|
||||
{ |
|
||||
public class NullStepBody : StepBody, ITransientDependency |
|
||||
{ |
|
||||
public override ExecutionResult Run(IStepExecutionContext context) |
|
||||
{ |
|
||||
return ExecutionResult.Next(); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,8 @@ |
|||||
|
using WorkflowCore.Models; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WorkflowCore |
||||
|
{ |
||||
|
public abstract class StepBodyAsyncBase : StepBodyAsync |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
using WorkflowCore.Models; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WorkflowCore |
||||
|
{ |
||||
|
public abstract class StepBodyBase : StepBody |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,33 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using System.Linq; |
||||
|
using System.Reflection; |
||||
|
using Volo.Abp; |
||||
|
using WorkflowCore.Interface; |
||||
|
|
||||
|
namespace LINGYUN.Abp.WorkflowCore |
||||
|
{ |
||||
|
public static class WorkflowRegisterHelper |
||||
|
{ |
||||
|
public readonly static MethodInfo RegisterGenericWorkflowMethod = |
||||
|
typeof(IWorkflowRegistry) |
||||
|
.GetMethods(BindingFlags.Public | BindingFlags.Instance) |
||||
|
.First(m => m.Name == nameof(IWorkflowRegistry.RegisterWorkflow) && m.IsGenericMethodDefinition); |
||||
|
|
||||
|
public static void RegisterWorkflow( |
||||
|
[NotNull] IWorkflowRegistry registry, |
||||
|
[NotNull] object workflow) |
||||
|
{ |
||||
|
Check.NotNull(registry, nameof(registry)); |
||||
|
Check.NotNull(workflow, nameof(workflow)); |
||||
|
|
||||
|
var workflowDataType = workflow.GetType() |
||||
|
.GetInterfaces() |
||||
|
.First(x => x.IsGenericType) |
||||
|
.GetGenericArguments()[0]; |
||||
|
|
||||
|
RegisterGenericWorkflowMethod |
||||
|
.MakeGenericMethod(workflowDataType) |
||||
|
.Invoke(registry, new object[] { workflow }); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,23 +0,0 @@ |
|||||
using Newtonsoft.Json; |
|
||||
|
|
||||
namespace System |
|
||||
{ |
|
||||
public static class ObjectSerializerExtensions |
|
||||
{ |
|
||||
private readonly static JsonSerializerSettings SerializerSettings = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All }; |
|
||||
|
|
||||
public static string SerializeObject(this object obj, bool handlingString = false, JsonSerializerSettings serializerSettings = null) |
|
||||
{ |
|
||||
if (obj is string objStr && !handlingString) |
|
||||
{ |
|
||||
return objStr; |
|
||||
} |
|
||||
return JsonConvert.SerializeObject(obj, serializerSettings ?? SerializerSettings); |
|
||||
} |
|
||||
|
|
||||
public static object DeserializeObject(this string str, JsonSerializerSettings serializerSettings = null) |
|
||||
{ |
|
||||
return JsonConvert.DeserializeObject(str ?? string.Empty, serializerSettings ?? SerializerSettings); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,18 @@ |
|||||
|
using System.Linq; |
||||
|
using WorkflowCore.Interface; |
||||
|
|
||||
|
namespace System |
||||
|
{ |
||||
|
public static class WorkflowTypeExtensions |
||||
|
{ |
||||
|
public static bool IsWorkflow(this Type type) |
||||
|
{ |
||||
|
return type.GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IWorkflow<>)); |
||||
|
} |
||||
|
|
||||
|
public static bool IsStepBody(this Type type) |
||||
|
{ |
||||
|
return typeof(IStepBody).IsAssignableFrom(type); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
File diff suppressed because it is too large
Binary file not shown.
File diff suppressed because it is too large
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Binary file not shown.
File diff suppressed because it is too large
Binary file not shown.
File diff suppressed because it is too large
Binary file not shown.
File diff suppressed because it is too large
Binary file not shown.
Loading…
Reference in new issue