50 changed files with 1527 additions and 15 deletions
@ -0,0 +1,81 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Globalization; |
|||
using System.Linq; |
|||
using System.Reflection; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Localization; |
|||
using Volo.Abp.MultiTenancy; |
|||
using WorkflowCore.Interface; |
|||
using WorkflowCore.Models; |
|||
|
|||
namespace LINGYUN.Abp.WorkflowCore.Components.Primitives |
|||
{ |
|||
public class RemoteService : StepBodyAsyncBase |
|||
{ |
|||
private readonly ICurrentTenant _currentTenant; |
|||
private readonly IServiceProvider _serviceProvider; |
|||
public RemoteService( |
|||
ICurrentTenant currentTenant, |
|||
IServiceProvider serviceProvider) |
|||
{ |
|||
_currentTenant = currentTenant; |
|||
_serviceProvider = serviceProvider; |
|||
|
|||
Data = new Dictionary<string, object>(); |
|||
} |
|||
/// <summary>
|
|||
/// 远程服务接口类型
|
|||
/// </summary>
|
|||
public string Interface { get; set; } |
|||
/// <summary>
|
|||
/// 远程服务方法名称
|
|||
/// </summary>
|
|||
public string Method { get; set; } |
|||
/// <summary>
|
|||
/// 请求参数
|
|||
/// </summary>
|
|||
public Dictionary<string, object> Data { get; set; } |
|||
/// <summary>
|
|||
/// 调用结果
|
|||
/// </summary>
|
|||
public object Result { get; set; } |
|||
|
|||
public Guid? TenantId { get; set; } |
|||
public string CurrentCulture { get; set; } |
|||
|
|||
public override async Task<ExecutionResult> RunAsync(IStepExecutionContext context) |
|||
{ |
|||
var serviceType = Type.GetType(Interface, true, true); |
|||
var method = serviceType.GetMethod(Method); |
|||
|
|||
var serviceFactory = _serviceProvider.GetRequiredService(serviceType); |
|||
|
|||
using (_currentTenant.Change(TenantId)) |
|||
{ |
|||
using (CultureHelper.Use(CurrentCulture ?? CultureInfo.CurrentCulture.Name)) |
|||
{ |
|||
// TODO: 身份令牌?
|
|||
// 工作流中是否需要调用API, 还是用户调用API之后传递事件激活下一个步骤
|
|||
|
|||
// Abp Api动态代理
|
|||
var result = (Task)method.Invoke(serviceFactory, Data.Select(x => x.Value).ToArray()); |
|||
await result; |
|||
|
|||
if (!method.ReturnType.GenericTypeArguments.IsNullOrEmpty()) |
|||
{ |
|||
var resultType = method.ReturnType.GenericTypeArguments[0]; |
|||
var resultProperty = typeof(Task<>) |
|||
.MakeGenericType(resultType) |
|||
.GetProperty(nameof(Task<object>.Result), BindingFlags.Instance | BindingFlags.Public); |
|||
|
|||
Result = resultProperty.GetValue(result); |
|||
} |
|||
|
|||
return ExecutionResult.Next(); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -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.Guids" Version="$(VoloAbpPackageVersion)" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\..\elasticsearch\LINGYUN.Abp.Elasticsearch\LINGYUN.Abp.Elasticsearch.csproj" /> |
|||
<ProjectReference Include="..\LINGYUN.Abp.WorkflowCore\LINGYUN.Abp.WorkflowCore.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,22 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.Modularity; |
|||
using WorkflowCore.Interface; |
|||
using WorkflowCore.Models; |
|||
|
|||
namespace LINGYUN.Abp.WorkflowCore.Persistence.Elasticsearch |
|||
{ |
|||
[DependsOn(typeof(AbpWorkflowCoreModule))] |
|||
public class AbpWorkflowCorePersistenceElasticsearchModule : AbpModule |
|||
{ |
|||
public override void PreConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.AddTransient<IPersistenceProvider, ElasticsearchPersistenceProvider>(); |
|||
context.Services.AddTransient<ElasticsearchPersistenceProvider>(); |
|||
|
|||
PreConfigure<WorkflowOptions>(options => |
|||
{ |
|||
options.UsePersistence(provider => provider.GetRequiredService<ElasticsearchPersistenceProvider>()); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
namespace LINGYUN.Abp.WorkflowCore.Persistence.Elasticsearch |
|||
{ |
|||
public class AbpWorkflowCorePersistenceElasticsearchOptions |
|||
{ |
|||
/// <summary>
|
|||
/// Default Value: abp.workflows.persistence
|
|||
/// </summary>
|
|||
public string IndexFormat { get; set; } |
|||
public AbpWorkflowCorePersistenceElasticsearchOptions() |
|||
{ |
|||
IndexFormat = "abp.workflows.persistence"; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,555 @@ |
|||
using LINGYUN.Abp.Elasticsearch; |
|||
using LINGYUN.Abp.WorkflowCore.Persistence.Elasticsearch.Models; |
|||
using Microsoft.Extensions.Logging; |
|||
using Microsoft.Extensions.Options; |
|||
using Nest; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Threading; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Guids; |
|||
using WorkflowCore.Interface; |
|||
using WorkflowCore.Models; |
|||
|
|||
namespace LINGYUN.Abp.WorkflowCore.Persistence.Elasticsearch |
|||
{ |
|||
public class ElasticsearchPersistenceProvider : IPersistenceProvider, ITransientDependency |
|||
{ |
|||
private readonly ILogger<ElasticsearchPersistenceProvider> _logger; |
|||
|
|||
private readonly IGuidGenerator _guidGenerator; |
|||
private readonly IElasticsearchClientFactory _elasticsearchClientFactory; |
|||
private readonly AbpWorkflowCorePersistenceElasticsearchOptions _options; |
|||
|
|||
public ElasticsearchPersistenceProvider( |
|||
IGuidGenerator guidGenerator, |
|||
IElasticsearchClientFactory elasticsearchClientFactory, |
|||
IOptions<AbpWorkflowCorePersistenceElasticsearchOptions> options, |
|||
ILogger<ElasticsearchPersistenceProvider> logger) |
|||
{ |
|||
_guidGenerator = guidGenerator; |
|||
_elasticsearchClientFactory = elasticsearchClientFactory; |
|||
_options = options.Value; |
|||
_logger = logger; |
|||
} |
|||
|
|||
public bool SupportsScheduledCommands => true; |
|||
|
|||
public virtual async Task ClearSubscriptionToken(string eventSubscriptionId, string token, CancellationToken cancellationToken = default) |
|||
{ |
|||
var id = Guid.Parse(eventSubscriptionId); |
|||
|
|||
var client = CreateClient(); |
|||
|
|||
var response = await client.GetAsync<EventSubscription>( |
|||
id, |
|||
dsl => dsl.Index(CreateIndex()), |
|||
ct: cancellationToken); |
|||
|
|||
CheckResponse(response); |
|||
|
|||
if (response.Found) |
|||
{ |
|||
if (response.Source.ExternalToken != token) |
|||
{ |
|||
throw new InvalidOperationException(); |
|||
} |
|||
response.Source.ExternalToken = null; |
|||
response.Source.ExternalWorkerId = null; |
|||
response.Source.ExternalTokenExpiry = null; |
|||
|
|||
await client.UpdateAsync<EventSubscription>( |
|||
id, |
|||
dsl => dsl.Index(CreateIndex()) |
|||
.Doc(response.Source), |
|||
ct: cancellationToken); |
|||
} |
|||
} |
|||
|
|||
public virtual async Task<string> CreateEvent(Event newEvent, CancellationToken cancellationToken = default) |
|||
{ |
|||
var client = CreateClient(); |
|||
|
|||
var newEventId = _guidGenerator.Create(); |
|||
|
|||
newEvent.Id = newEventId.ToString(); |
|||
|
|||
var response = await client.IndexAsync( |
|||
newEvent, |
|||
dsl => dsl.Index(CreateIndex()) |
|||
.Id(newEventId), |
|||
ct: cancellationToken); |
|||
|
|||
CheckResponse(response); |
|||
|
|||
return newEvent.Id; |
|||
} |
|||
|
|||
public virtual async Task<string> CreateEventSubscription(EventSubscription subscription, CancellationToken cancellationToken = default) |
|||
{ |
|||
var client = CreateClient(); |
|||
|
|||
var newSubscriptionId = _guidGenerator.Create(); |
|||
|
|||
subscription.Id = newSubscriptionId.ToString(); |
|||
|
|||
var response = await client.IndexAsync( |
|||
subscription, |
|||
dsl => dsl.Index(CreateIndex()) |
|||
.Id(newSubscriptionId), |
|||
ct: cancellationToken); |
|||
|
|||
CheckResponse(response); |
|||
|
|||
return subscription.Id; |
|||
} |
|||
|
|||
public virtual async Task<string> CreateNewWorkflow(WorkflowInstance workflow, CancellationToken cancellationToken = default) |
|||
{ |
|||
var client = CreateClient(); |
|||
|
|||
var newWorkflowId = _guidGenerator.Create(); |
|||
|
|||
workflow.Id = newWorkflowId.ToString(); |
|||
|
|||
var response = await client.IndexAsync( |
|||
workflow, |
|||
dsl => dsl.Index(CreateIndex()) |
|||
.Id(newWorkflowId), |
|||
ct: cancellationToken); |
|||
|
|||
CheckResponse(response); |
|||
|
|||
return workflow.Id; |
|||
} |
|||
|
|||
public void EnsureStoreExists() |
|||
{ |
|||
// TODO: 为什么是同步API...
|
|||
var client = CreateClient(); |
|||
|
|||
var response = client.Indices.Exists(CreateIndex()); |
|||
if (!response.Exists) |
|||
{ |
|||
client.Indices.Create(CreateIndex()); |
|||
} |
|||
} |
|||
|
|||
public virtual async Task<Event> GetEvent(string id, CancellationToken cancellationToken = default) |
|||
{ |
|||
var eventId = Guid.Parse(id); |
|||
|
|||
var client = CreateClient(); |
|||
|
|||
var response = await client.GetAsync<Event>( |
|||
eventId, |
|||
dsl => dsl.Index(CreateIndex()), |
|||
ct: cancellationToken); |
|||
|
|||
CheckResponse(response); |
|||
|
|||
return response.Source; |
|||
} |
|||
|
|||
public virtual async Task<IEnumerable<string>> GetEvents(string eventName, string eventKey, DateTime asOf, CancellationToken cancellationToken = default) |
|||
{ |
|||
var client = CreateClient(); |
|||
|
|||
var terms = new List<Func<QueryContainerDescriptor<Event>, QueryContainer>>(); |
|||
|
|||
terms.Add(x => x.Term(t => t.Field(f => f.EventName.Suffix("keyword")).Value(eventName))); |
|||
terms.Add(x => x.Term(t => t.Field(f => f.EventKey.Suffix("keyword")).Value(eventKey))); |
|||
terms.Add(x => x.DateRange(t => t.Field(f => f.EventTime).GreaterThanOrEquals(asOf))); |
|||
|
|||
var response = await client.SearchAsync<Event>( |
|||
dsl => dsl.Index(CreateIndex()) |
|||
.Query(q => q.Bool(b => b.Filter(terms))) |
|||
.Source(s => s.Includes(e => e.Field(f => f.Id.Suffix("keyword")))), |
|||
ct: cancellationToken); |
|||
|
|||
CheckResponse(response); |
|||
|
|||
return response.Documents.Select(x => x.Id); |
|||
} |
|||
|
|||
public virtual async Task<EventSubscription> GetFirstOpenSubscription(string eventName, string eventKey, DateTime asOf, CancellationToken cancellationToken = default) |
|||
{ |
|||
var client = CreateClient(); |
|||
|
|||
var terms = new List<Func<QueryContainerDescriptor<EventSubscription>, QueryContainer>>(); |
|||
|
|||
terms.Add(x => x.Term(t => t.Field(f => f.EventName.Suffix("keyword")).Value(eventName))); |
|||
terms.Add(x => x.Term(t => t.Field(f => f.EventKey.Suffix("keyword")).Value(eventKey))); |
|||
terms.Add(x => x.Term(t => t.Field(f => f.ExternalToken.Suffix("keyword")).Value(null))); |
|||
terms.Add(x => x.DateRange(t => t.Field(f => f.SubscribeAsOf).LessThanOrEquals(asOf))); |
|||
|
|||
var response = await client.SearchAsync<EventSubscription>( |
|||
dsl => dsl.Index(CreateIndex()) |
|||
.Query(q => q.Bool(b => b.Filter(terms))) |
|||
.Source(s => s.Includes(e => e.Field(f => f.Id.Suffix("keyword")))) |
|||
.Sort(s => s.Field(f => f.SubscribeAsOf, SortOrder.Ascending)) |
|||
.Take(1), |
|||
ct: cancellationToken); |
|||
|
|||
CheckResponse(response); |
|||
|
|||
return response.Documents.FirstOrDefault(); |
|||
} |
|||
|
|||
public virtual async Task<IEnumerable<string>> GetRunnableEvents(DateTime asAt, CancellationToken cancellationToken = default) |
|||
{ |
|||
var client = CreateClient(); |
|||
var now = asAt.ToUniversalTime(); |
|||
|
|||
var terms = new List<Func<QueryContainerDescriptor<Event>, QueryContainer>>(); |
|||
|
|||
terms.Add(x => x.Term(t => t.Field(f => f.IsProcessed).Value(false))); |
|||
terms.Add(x => x.DateRange(t => t.Field(f => f.EventTime).LessThanOrEquals(now))); |
|||
|
|||
var response = await client.SearchAsync<Event>( |
|||
dsl => dsl.Index(CreateIndex()) |
|||
.Query(q => q.Bool(b => b.Filter(terms))) |
|||
.Source(s => s.Includes(e => e.Field(f => f.Id.Suffix("keyword")))), |
|||
ct: cancellationToken); |
|||
|
|||
CheckResponse(response); |
|||
|
|||
return response.Documents.Select(x => x.Id); |
|||
} |
|||
|
|||
public virtual async Task<IEnumerable<string>> GetRunnableInstances(DateTime asAt, CancellationToken cancellationToken = default) |
|||
{ |
|||
var client = CreateClient(); |
|||
var now = asAt.ToUniversalTime().Ticks; |
|||
|
|||
var terms = new List<Func<QueryContainerDescriptor<WorkflowInstance>, QueryContainer>>(); |
|||
|
|||
terms.Add(x => x.LongRange(t => t.Field(f => f.NextExecution).LessThanOrEquals(now))); |
|||
terms.Add(x => x.Term(t => t.Field(f => f.Status).Value(WorkflowStatus.Runnable))); |
|||
|
|||
var response = await client.SearchAsync<WorkflowInstance>( |
|||
dsl => dsl.Index(CreateIndex()) |
|||
.Query(q => q.Bool(b => b.Filter(terms))) |
|||
.Source(s => s.Includes(e => e.Field(f => f.Id.Suffix("keyword")))), |
|||
ct: cancellationToken); |
|||
|
|||
CheckResponse(response); |
|||
|
|||
return response.Documents.Select(x => x.Id); |
|||
} |
|||
|
|||
public virtual async Task<EventSubscription> GetSubscription(string eventSubscriptionId, CancellationToken cancellationToken = default) |
|||
{ |
|||
var client = CreateClient(); |
|||
|
|||
var id = Guid.Parse(eventSubscriptionId); |
|||
|
|||
var response = await client.GetAsync<EventSubscription>( |
|||
id, |
|||
dsl => dsl.Index(CreateIndex()), |
|||
ct: cancellationToken); |
|||
|
|||
CheckResponse(response); |
|||
|
|||
return response.Source; |
|||
} |
|||
|
|||
public virtual async Task<IEnumerable<EventSubscription>> GetSubscriptions(string eventName, string eventKey, DateTime asOf, CancellationToken cancellationToken = default) |
|||
{ |
|||
var client = CreateClient(); |
|||
var now = asOf.ToUniversalTime(); |
|||
|
|||
var terms = new List<Func<QueryContainerDescriptor<EventSubscription>, QueryContainer>>(); |
|||
|
|||
terms.Add(x => x.Term(t => t.Field(f => f.EventName.Suffix("keyword")).Value(eventName))); |
|||
terms.Add(x => x.Term(t => t.Field(f => f.EventKey.Suffix("keyword")).Value(eventKey))); |
|||
terms.Add(x => x.DateRange(t => t.Field(f => f.SubscribeAsOf).LessThanOrEquals(now))); |
|||
|
|||
var response = await client.SearchAsync<EventSubscription>( |
|||
dsl => dsl.Index(CreateIndex()) |
|||
.Query(q => q.Bool(b => b.Filter(terms))) |
|||
.Source(s => s.IncludeAll()), |
|||
ct: cancellationToken); |
|||
|
|||
CheckResponse(response); |
|||
|
|||
return response.Documents; |
|||
} |
|||
|
|||
public virtual async Task<WorkflowInstance> GetWorkflowInstance(string Id, CancellationToken cancellationToken = default) |
|||
{ |
|||
var workflowId = Guid.Parse(Id); |
|||
var client = CreateClient(); |
|||
|
|||
var response = await client.GetAsync<WorkflowInstance>( |
|||
workflowId, |
|||
dsl => dsl.Index(CreateIndex()), |
|||
ct: cancellationToken); |
|||
|
|||
CheckResponse(response); |
|||
|
|||
return response.Source; |
|||
} |
|||
|
|||
public virtual async Task<IEnumerable<WorkflowInstance>> GetWorkflowInstances(WorkflowStatus? status, string type, DateTime? createdFrom, DateTime? createdTo, int skip, int take) |
|||
{ |
|||
var client = CreateClient(); |
|||
|
|||
var terms = new List<Func<QueryContainerDescriptor<WorkflowInstance>, QueryContainer>>(); |
|||
|
|||
if (status.HasValue) |
|||
{ |
|||
terms.Add(x => x.Term(t => t.Field(f => f.Status).Value(status.Value))); |
|||
} |
|||
if (!type.IsNullOrWhiteSpace()) |
|||
{ |
|||
terms.Add(x => x.Term(t => t.Field(f => f.WorkflowDefinitionId.Suffix("keyword")).Value(type))); |
|||
} |
|||
if (createdFrom.HasValue) |
|||
{ |
|||
terms.Add(x => x.DateRange(t => t.Field(f => f.CreateTime).GreaterThanOrEquals(createdFrom.Value))); |
|||
} |
|||
if (createdTo.HasValue) |
|||
{ |
|||
terms.Add(x => x.DateRange(t => t.Field(f => f.CreateTime).LessThanOrEquals(createdTo.Value))); |
|||
} |
|||
|
|||
var response = await client.SearchAsync<WorkflowInstance>( |
|||
dsl => dsl.Index(CreateIndex()) |
|||
.Query(q => q.Bool(b => b.Filter(terms))) |
|||
.Source(s => s.IncludeAll()) |
|||
.Skip(skip) |
|||
.Take(take)); |
|||
|
|||
CheckResponse(response); |
|||
|
|||
return response.Documents; |
|||
} |
|||
|
|||
public virtual async Task<IEnumerable<WorkflowInstance>> GetWorkflowInstances(IEnumerable<string> ids, CancellationToken cancellationToken = default) |
|||
{ |
|||
var client = CreateClient(); |
|||
|
|||
var response = await client.SearchAsync<WorkflowInstance>( |
|||
dsl => dsl.Index(CreateIndex()) |
|||
.Query(q => |
|||
q.Bool(b => |
|||
b.Should(s => |
|||
s.Terms(t => t.Field(f => f.Id.Suffix("keyword")).Terms(ids))))) |
|||
.Source(s => s.IncludeAll()), |
|||
ct: cancellationToken); |
|||
|
|||
CheckResponse(response); |
|||
|
|||
return response.Documents; |
|||
} |
|||
|
|||
public virtual async Task MarkEventProcessed(string id, CancellationToken cancellationToken = default) |
|||
{ |
|||
var eventId = Guid.Parse(id); |
|||
|
|||
var client = CreateClient(); |
|||
|
|||
var response = await client.GetAsync<Event>( |
|||
eventId, |
|||
dsl => dsl.Index(CreateIndex()), |
|||
ct: cancellationToken); |
|||
|
|||
CheckResponse(response); |
|||
|
|||
if (response.Found) |
|||
{ |
|||
response.Source.IsProcessed = true; |
|||
|
|||
await client.UpdateAsync<Event>( |
|||
id, |
|||
dsl => dsl.Index(CreateIndex()) |
|||
.Doc(response.Source), |
|||
ct: cancellationToken); |
|||
} |
|||
} |
|||
|
|||
public virtual async Task MarkEventUnprocessed(string id, CancellationToken cancellationToken = default) |
|||
{ |
|||
var eventId = Guid.Parse(id); |
|||
|
|||
var client = CreateClient(); |
|||
|
|||
var response = await client.GetAsync<Event>( |
|||
eventId, |
|||
dsl => dsl.Index(CreateIndex()), |
|||
ct: cancellationToken); |
|||
|
|||
CheckResponse(response); |
|||
|
|||
if (response.Found) |
|||
{ |
|||
response.Source.IsProcessed = false; |
|||
|
|||
await client.UpdateAsync<Event>( |
|||
id, |
|||
dsl => dsl.Index(CreateIndex()) |
|||
.Doc(response.Source), |
|||
ct: cancellationToken); |
|||
} |
|||
} |
|||
|
|||
public virtual async Task PersistErrors(IEnumerable<ExecutionError> errors, CancellationToken cancellationToken = default) |
|||
{ |
|||
var executionErrors = errors as ExecutionError[] ?? errors.ToArray(); |
|||
if (executionErrors.Any()) |
|||
{ |
|||
var client = CreateClient(); |
|||
|
|||
var response = await client.IndexManyAsync( |
|||
errors, |
|||
CreateIndex(), |
|||
cancellationToken: cancellationToken); |
|||
|
|||
CheckResponse(response); |
|||
} |
|||
} |
|||
|
|||
public virtual async Task PersistWorkflow(WorkflowInstance workflow, CancellationToken cancellationToken = default) |
|||
{ |
|||
var workflowId = Guid.Parse(workflow.Id); |
|||
|
|||
var client = CreateClient(); |
|||
|
|||
var response = await client.GetAsync<WorkflowInstance>( |
|||
workflowId, |
|||
dsl => dsl.Index(CreateIndex()), |
|||
ct: cancellationToken); |
|||
|
|||
CheckResponse(response); |
|||
|
|||
await client.UpdateAsync<WorkflowInstance>( |
|||
workflowId, |
|||
dsl => dsl.Index(CreateIndex()) |
|||
.Doc(workflow), |
|||
ct: cancellationToken); |
|||
} |
|||
|
|||
public virtual async Task ProcessCommands(DateTimeOffset asOf, Func<ScheduledCommand, Task> action, CancellationToken cancellationToken = default) |
|||
{ |
|||
var client = CreateClient(); |
|||
|
|||
var terms = new List<Func<QueryContainerDescriptor<PersistedScheduledCommand>, QueryContainer>>(); |
|||
|
|||
terms.Add(x => x.LongRange(t => t.Field(f => f.ExecuteTime).LessThan(asOf.Ticks))); |
|||
|
|||
var response = await client.SearchAsync<PersistedScheduledCommand>( |
|||
dsl => dsl.Index(CreateIndex()) |
|||
.Query(q => q.Bool(b => b.Filter(terms))) |
|||
.Source(s => s.IncludeAll()), |
|||
ct: cancellationToken); |
|||
|
|||
CheckResponse(response); |
|||
|
|||
foreach (var command in response.Documents) |
|||
{ |
|||
try |
|||
{ |
|||
await action(command.ToScheduledCommand()); |
|||
|
|||
await client.DeleteAsync<PersistedScheduledCommand>( |
|||
command.Id, |
|||
dsl => dsl.Index(CreateIndex()), |
|||
ct: cancellationToken); |
|||
} |
|||
catch (Exception) |
|||
{ |
|||
//TODO: add logger
|
|||
} |
|||
} |
|||
} |
|||
|
|||
public virtual async Task ScheduleCommand(ScheduledCommand command) |
|||
{ |
|||
var persistedCommand = new PersistedScheduledCommand( |
|||
_guidGenerator.Create(), |
|||
command); |
|||
|
|||
var client = CreateClient(); |
|||
|
|||
var response = await client.IndexAsync( |
|||
persistedCommand, |
|||
dsl => dsl.Index(CreateIndex()).Id(persistedCommand.Id)); |
|||
|
|||
CheckResponse(response); |
|||
} |
|||
|
|||
public virtual async Task<bool> SetSubscriptionToken(string eventSubscriptionId, string token, string workerId, DateTime expiry, CancellationToken cancellationToken = default) |
|||
{ |
|||
var id = Guid.Parse(eventSubscriptionId); |
|||
|
|||
var client = CreateClient(); |
|||
|
|||
var response = await client.GetAsync<EventSubscription>( |
|||
id, |
|||
dsl => dsl.Index(CreateIndex()), |
|||
ct: cancellationToken); |
|||
|
|||
CheckResponse(response); |
|||
|
|||
if (response.Found) |
|||
{ |
|||
response.Source.ExternalToken = token; |
|||
response.Source.ExternalWorkerId = workerId; |
|||
response.Source.ExternalTokenExpiry = expiry; |
|||
|
|||
var uptResponse = await client.UpdateAsync<EventSubscription>( |
|||
id, |
|||
dsl => dsl.Index(CreateIndex()) |
|||
.Doc(response.Source), |
|||
ct: cancellationToken); |
|||
|
|||
return uptResponse.Result == Result.Updated; |
|||
} |
|||
|
|||
return false; |
|||
} |
|||
|
|||
public virtual async Task TerminateSubscription(string eventSubscriptionId, CancellationToken cancellationToken = default) |
|||
{ |
|||
var id = Guid.Parse(eventSubscriptionId); |
|||
|
|||
var client = CreateClient(); |
|||
|
|||
var response = await client.DeleteAsync<EventSubscription>( |
|||
id, |
|||
dsl => dsl.Index(CreateIndex()), |
|||
ct: cancellationToken); |
|||
|
|||
CheckResponse(response); |
|||
} |
|||
|
|||
private IElasticClient CreateClient() |
|||
{ |
|||
return _elasticsearchClientFactory.Create(); |
|||
} |
|||
|
|||
private string CreateIndex() |
|||
{ |
|||
return _options.IndexFormat; |
|||
} |
|||
|
|||
private void CheckResponse(IResponse response) |
|||
{ |
|||
if (!response.ApiCall.Success) |
|||
{ |
|||
_logger.LogError(default(EventId), response.ApiCall.OriginalException, $"ES Operation Failed"); |
|||
throw new AbpException($"ES Operation Failed", response.ApiCall.OriginalException); |
|||
} |
|||
|
|||
if (!response.IsValid) |
|||
{ |
|||
_logger.LogWarning("ES Request Valid Error: {0}", response.DebugInformation); |
|||
throw new InvalidOperationException(response.DebugInformation, response.OriginalException); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,32 @@ |
|||
using System; |
|||
using WorkflowCore.Models; |
|||
|
|||
namespace LINGYUN.Abp.WorkflowCore.Persistence.Elasticsearch.Models |
|||
{ |
|||
public class PersistedScheduledCommand |
|||
{ |
|||
public Guid Id { get; set; } |
|||
public string CommandName { get; set; } |
|||
public string Data { get; set; } |
|||
public long ExecuteTime { get; set; } |
|||
|
|||
public PersistedScheduledCommand() { } |
|||
|
|||
public PersistedScheduledCommand(Guid id, ScheduledCommand command) |
|||
{ |
|||
Id = id; |
|||
CommandName = command.CommandName; |
|||
Data = command.Data; |
|||
ExecuteTime = command.ExecuteTime; |
|||
} |
|||
public ScheduledCommand ToScheduledCommand() |
|||
{ |
|||
return new ScheduledCommand |
|||
{ |
|||
CommandName = CommandName, |
|||
Data = Data, |
|||
ExecuteTime = ExecuteTime |
|||
}; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
using System; |
|||
using Volo.Abp.DependencyInjection; |
|||
using Volo.Abp.Timing; |
|||
using WorkflowCore.Interface; |
|||
|
|||
namespace LINGYUN.Abp.WorkflowCore |
|||
{ |
|||
[Dependency(ReplaceServices = true)] |
|||
public class AbpDateTimeProvider : IDateTimeProvider |
|||
{ |
|||
private readonly IClock _clock; |
|||
|
|||
public AbpDateTimeProvider(IClock clock) |
|||
{ |
|||
_clock = clock; |
|||
} |
|||
|
|||
public DateTime Now => _clock.Now; |
|||
|
|||
public DateTime UtcNow => _clock.Now.ToUtcDateTime(); |
|||
} |
|||
} |
|||
@ -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.Ddd.Application.Contracts" Version="$(VoloAbpPackageVersion)" /> |
|||
<PackageReference Include="Volo.Abp.Authorization" Version="$(VoloAbpPackageVersion)" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\LINGYUN.Abp.WorkflowManagement.Domain.Shared\LINGYUN.Abp.WorkflowManagement.Domain.Shared.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,23 @@ |
|||
using LINGYUN.Abp.WorkflowManagement.Localization; |
|||
using Volo.Abp.Authorization.Permissions; |
|||
using Volo.Abp.Localization; |
|||
|
|||
namespace LINGYUN.Abp.WorkflowManagement.Authorization |
|||
{ |
|||
public class WorkflowManagementPermissionDefinitionProvider : PermissionDefinitionProvider |
|||
{ |
|||
public override void Define(IPermissionDefinitionContext context) |
|||
{ |
|||
var group = context.AddGroup(WorkflowManagementPermissions.GroupName, L("Permission:WorkflowManagement")); |
|||
|
|||
group.AddPermission( |
|||
WorkflowManagementPermissions.ManageSettings, |
|||
L("Permission:ManageSettings")); |
|||
} |
|||
|
|||
private static LocalizableString L(string name) |
|||
{ |
|||
return LocalizableString.Create<WorkflowManagementResource>(name); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
namespace LINGYUN.Abp.WorkflowManagement.Authorization |
|||
{ |
|||
public static class WorkflowManagementPermissions |
|||
{ |
|||
public const string GroupName = "WorkflowManagement"; |
|||
|
|||
public const string ManageSettings = GroupName + ".ManageSettings"; |
|||
} |
|||
} |
|||
@ -0,0 +1,14 @@ |
|||
using Volo.Abp.Application; |
|||
using Volo.Abp.Authorization; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace LINGYUN.Abp.WorkflowManagement |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpAuthorizationModule), |
|||
typeof(AbpDddApplicationContractsModule), |
|||
typeof(WorkflowManagementDomainSharedModule))] |
|||
public class WorkflowManagementApplicationContractsModule : AbpModule |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
namespace LINGYUN.Abp.WorkflowManagement |
|||
{ |
|||
public static class WorkflowManagementRemoteServiceConsts |
|||
{ |
|||
public const string RemoteServiceName = "WorkflowManagement"; |
|||
} |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net6.0</TargetFramework> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Volo.Abp.Ddd.Application" Version="$(VoloAbpPackageVersion)" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\LINGYUN.Abp.WorkflowManagement.Application.Contracts\LINGYUN.Abp.WorkflowManagement.Application.Contracts.csproj" /> |
|||
<ProjectReference Include="..\LINGYUN.Abp.WorkflowManagement.Domain\LINGYUN.Abp.WorkflowManagement.Domain.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,14 @@ |
|||
using LINGYUN.Abp.WorkflowManagement.Localization; |
|||
using Volo.Abp.Application.Services; |
|||
|
|||
namespace LINGYUN.Abp.WorkflowManagement |
|||
{ |
|||
public abstract class WorkflowManagementAppServiceBase : ApplicationService |
|||
{ |
|||
protected WorkflowManagementAppServiceBase() |
|||
{ |
|||
LocalizationResource = typeof(WorkflowManagementResource); |
|||
ObjectMapperContext = typeof(WorkflowManagementApplicationModule); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
using AutoMapper; |
|||
|
|||
namespace LINGYUN.Abp.WorkflowManagement |
|||
{ |
|||
public class WorkflowManagementApplicationMapperProfile : Profile |
|||
{ |
|||
public WorkflowManagementApplicationMapperProfile() |
|||
{ |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,25 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.Application; |
|||
using Volo.Abp.Authorization; |
|||
using Volo.Abp.AutoMapper; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace LINGYUN.Abp.WorkflowManagement |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpAuthorizationModule), |
|||
typeof(AbpDddApplicationContractsModule), |
|||
typeof(WorkflowManagementDomainSharedModule))] |
|||
public class WorkflowManagementApplicationModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.AddAutoMapperObjectMapper<WorkflowManagementApplicationModule>(); |
|||
|
|||
Configure<AbpAutoMapperOptions>(options => |
|||
{ |
|||
options.AddProfile<WorkflowManagementApplicationMapperProfile>(validate: true); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>netstandard2.0</TargetFramework> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<None Remove="LINGYUN\Abp\WorkflowManagement\Localization\Resources\en.json" /> |
|||
<None Remove="LINGYUN\Abp\WorkflowManagement\Localization\Resources\zh-Hans.json" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<EmbeddedResource Include="LINGYUN\Abp\WorkflowManagement\Localization\Resources\en.json" /> |
|||
<EmbeddedResource Include="LINGYUN\Abp\WorkflowManagement\Localization\Resources\zh-Hans.json" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Volo.Abp.Auditing" Version="$(VoloAbpPackageVersion)" /> |
|||
<PackageReference Include="Volo.Abp.EventBus" Version="$(VoloAbpPackageVersion)" /> |
|||
<PackageReference Include="Volo.Abp.Localization" Version="$(VoloAbpPackageVersion)" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,7 @@ |
|||
{ |
|||
"culture": "en", |
|||
"texts": { |
|||
"Permission:WorkflowManagement": "WorkflowManagement", |
|||
"Permission:ManageSettings": "Manage Settings" |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
{ |
|||
"culture": "zh-Hans", |
|||
"texts": { |
|||
"Permission:WorkflowManagement": "WorkflowManagement", |
|||
"Permission:ManageSettings": "管理设置" |
|||
} |
|||
} |
|||
@ -0,0 +1,9 @@ |
|||
using Volo.Abp.Localization; |
|||
|
|||
namespace LINGYUN.Abp.WorkflowManagement.Localization |
|||
{ |
|||
[LocalizationResourceName("WorkflowManagement")] |
|||
public class WorkflowManagementResource |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,33 @@ |
|||
using LINGYUN.Abp.WorkflowManagement.Localization; |
|||
using Volo.Abp.Localization; |
|||
using Volo.Abp.Localization.ExceptionHandling; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.VirtualFileSystem; |
|||
|
|||
namespace LINGYUN.Abp.WorkflowManagement |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpLocalizationModule))] |
|||
public class WorkflowManagementDomainSharedModule: AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
Configure<AbpVirtualFileSystemOptions>(options => |
|||
{ |
|||
options.FileSets.AddEmbedded<WorkflowManagementDomainSharedModule>(); |
|||
}); |
|||
|
|||
Configure<AbpLocalizationOptions>(options => |
|||
{ |
|||
options.Resources |
|||
.Add<WorkflowManagementResource>() |
|||
.AddVirtualJson("/Abp/WorkflowManagement/Localization/Resources"); |
|||
}); |
|||
|
|||
Configure<AbpExceptionLocalizationOptions>(options => |
|||
{ |
|||
options.MapCodeNamespace(WorkflowManagementErrorCodes.Namespace, typeof(WorkflowManagementResource)); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
namespace LINGYUN.Abp.WorkflowManagement |
|||
{ |
|||
public static class WorkflowManagementErrorCodes |
|||
{ |
|||
public const string Namespace = "WorkflowManagement"; |
|||
} |
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
<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.AutoMapper" Version="$(VoloAbpPackageVersion)" /> |
|||
<PackageReference Include="Volo.Abp.Caching" Version="$(VoloAbpPackageVersion)" /> |
|||
<PackageReference Include="Volo.Abp.Ddd.Domain" Version="$(VoloAbpPackageVersion)" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\LINGYUN.Abp.WorkflowCore\LINGYUN.Abp.WorkflowCore.csproj" /> |
|||
<ProjectReference Include="..\LINGYUN.Abp.WorkflowManagement.Domain.Shared\LINGYUN.Abp.WorkflowManagement.Domain.Shared.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,11 @@ |
|||
using Volo.Abp.Settings; |
|||
|
|||
namespace LINGYUN.Abp.WorkflowManagement.Settings |
|||
{ |
|||
public class WorkflowManagementSettingDefinitionProvider : SettingDefinitionProvider |
|||
{ |
|||
public override void Define(ISettingDefinitionContext context) |
|||
{ |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
namespace LINGYUN.Abp.WorkflowManagement.Settings |
|||
{ |
|||
public static class WorkflowManagementSettings |
|||
{ |
|||
public const string GroupName = "WorkflowManagement"; |
|||
} |
|||
} |
|||
@ -0,0 +1,57 @@ |
|||
using System; |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.Domain.Entities; |
|||
using Volo.Abp.MultiTenancy; |
|||
using WorkflowCore.Models; |
|||
|
|||
namespace LINGYUN.Abp.WorkflowManagement |
|||
{ |
|||
public class Step : Entity<Guid>, IMultiTenant |
|||
{ |
|||
public virtual Guid? TenantId { get; protected set; } |
|||
public virtual Guid WorkflowId { get; protected set; } |
|||
public virtual string Name { get; protected set;} |
|||
public virtual string StepType { get; protected set; } |
|||
public virtual string CancelCondition { get; set; } |
|||
public virtual WorkflowErrorHandling? ErrorBehavior { get; protected set; } |
|||
public virtual int? RetryInterval { get; set; } |
|||
public virtual bool Saga { get; set; } |
|||
public virtual Guid? NextStep { get; protected set; } |
|||
public virtual ExtraPropertyDictionary Inputs { get; set; } |
|||
public virtual ExtraPropertyDictionary Outputs { get; set; } |
|||
public virtual ExtraPropertyDictionary SelectNextStep { get; set; } |
|||
protected Step() |
|||
{ |
|||
Inputs = new ExtraPropertyDictionary(); |
|||
Outputs = new ExtraPropertyDictionary(); |
|||
SelectNextStep = new ExtraPropertyDictionary(); |
|||
} |
|||
|
|||
public Step( |
|||
Guid id, |
|||
Guid workflowId, |
|||
string name, |
|||
string stepType, |
|||
string cancelCondition, |
|||
WorkflowErrorHandling? errorBehavior = null, |
|||
int? retryInterval = null, |
|||
bool saga = false, |
|||
Guid? nextStep = null, |
|||
Guid? tenantId = null) : base(id) |
|||
{ |
|||
Name = name; |
|||
WorkflowId = workflowId; |
|||
StepType = stepType; |
|||
CancelCondition = cancelCondition; |
|||
ErrorBehavior = errorBehavior; |
|||
RetryInterval = retryInterval; |
|||
Saga = saga; |
|||
NextStep = nextStep; |
|||
TenantId = tenantId; |
|||
|
|||
Inputs = new ExtraPropertyDictionary(); |
|||
Outputs = new ExtraPropertyDictionary(); |
|||
SelectNextStep = new ExtraPropertyDictionary(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,45 @@ |
|||
using System; |
|||
using Volo.Abp.Domain.Entities.Auditing; |
|||
using Volo.Abp.MultiTenancy; |
|||
|
|||
namespace LINGYUN.Abp.WorkflowManagement |
|||
{ |
|||
/// <summary>
|
|||
/// 流程定义
|
|||
/// </summary>
|
|||
public class Workflow : AuditedAggregateRoot<Guid>, IMultiTenant |
|||
{ |
|||
/// <summary>
|
|||
/// 租户标识
|
|||
/// </summary>
|
|||
public virtual Guid? TenantId { get; protected set; } |
|||
/// <summary>
|
|||
/// 是否启用
|
|||
/// </summary>
|
|||
public virtual bool IsEnabled { get; protected set; } |
|||
/// <summary>
|
|||
/// 显示名称
|
|||
/// </summary>
|
|||
public virtual string DisplayName { get; set; } |
|||
/// <summary>
|
|||
/// 描述
|
|||
/// </summary>
|
|||
public virtual string Description { get; set; } |
|||
/// <summary>
|
|||
/// 版本号
|
|||
/// </summary>
|
|||
public virtual int Version { get; protected set; } |
|||
|
|||
protected Workflow() |
|||
{ |
|||
} |
|||
|
|||
public Workflow( |
|||
Guid id, |
|||
string displayName, |
|||
string description = "", |
|||
int version = 1) : base(id) |
|||
{ |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
namespace LINGYUN.Abp.WorkflowManagement |
|||
{ |
|||
public static class WorkflowManagementDbProperties |
|||
{ |
|||
public static string DbTablePrefix { get; set; } = "WorkflowManagement_"; |
|||
|
|||
public static string DbSchema { get; set; } = null; |
|||
|
|||
|
|||
public const string ConnectionStringName = "WorkflowManagement"; |
|||
} |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
using AutoMapper; |
|||
|
|||
namespace LINGYUN.Abp.WorkflowManagement |
|||
{ |
|||
public class WorkflowManagementDomainMapperProfile: Profile |
|||
{ |
|||
public WorkflowManagementDomainMapperProfile() |
|||
{ |
|||
|
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,27 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.AutoMapper; |
|||
using Volo.Abp.Domain.Entities.Events.Distributed; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace LINGYUN.Abp.WorkflowManagement |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpAutoMapperModule), |
|||
typeof(WorkflowManagementDomainSharedModule))] |
|||
public class WorkflowManagementDomainModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.AddAutoMapperObjectMapper<WorkflowManagementDomainModule>(); |
|||
|
|||
Configure<AbpAutoMapperOptions>(options => |
|||
{ |
|||
options.AddProfile<WorkflowManagementDomainMapperProfile>(validate: true); |
|||
}); |
|||
|
|||
Configure<AbpDistributedEntityEventOptions>(options => |
|||
{ |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net6.0</TargetFramework> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Volo.Abp.EntityFrameworkCore" Version="$(VoloAbpPackageVersion)" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\LINGYUN.Abp.WorkflowManagement.Domain\LINGYUN.Abp.WorkflowManagement.Domain.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,10 @@ |
|||
using Volo.Abp.Data; |
|||
using Volo.Abp.EntityFrameworkCore; |
|||
|
|||
namespace LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore |
|||
{ |
|||
[ConnectionStringName(WorkflowManagementDbProperties.ConnectionStringName)] |
|||
public interface IWorkflowManagementDbContext : IEfCoreDbContext |
|||
{ |
|||
} |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
using Microsoft.EntityFrameworkCore; |
|||
using Volo.Abp.EntityFrameworkCore; |
|||
|
|||
namespace LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore |
|||
{ |
|||
public class WorkflowManagementDbContext : AbpDbContext<WorkflowManagementDbContext>, IWorkflowManagementDbContext |
|||
{ |
|||
public WorkflowManagementDbContext( |
|||
DbContextOptions<WorkflowManagementDbContext> options) : base(options) |
|||
{ |
|||
} |
|||
|
|||
protected override void OnModelCreating(ModelBuilder modelBuilder) |
|||
{ |
|||
base.OnModelCreating(modelBuilder); |
|||
|
|||
modelBuilder.ConfigureWorkflowManagement(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,22 @@ |
|||
using Microsoft.EntityFrameworkCore; |
|||
using System; |
|||
using Volo.Abp; |
|||
|
|||
namespace LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore |
|||
{ |
|||
public static class WorkflowManagementDbContextModelCreatingExtensions |
|||
{ |
|||
public static void ConfigureWorkflowManagement( |
|||
this ModelBuilder builder, |
|||
Action<WorkflowManagementModelBuilderConfigurationOptions> optionsAction = null) |
|||
{ |
|||
Check.NotNull(builder, nameof(builder)); |
|||
|
|||
var options = new WorkflowManagementModelBuilderConfigurationOptions( |
|||
WorkflowManagementDbProperties.DbTablePrefix, |
|||
WorkflowManagementDbProperties.DbSchema |
|||
); |
|||
optionsAction?.Invoke(options); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.EntityFrameworkCore; |
|||
using Volo.Abp.Modularity; |
|||
|
|||
namespace LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore |
|||
{ |
|||
[DependsOn( |
|||
typeof(WorkflowManagementDomainModule), |
|||
typeof(AbpEntityFrameworkCoreModule))] |
|||
public class WorkflowManagementEntityFrameworkCoreModule : AbpModule |
|||
{ |
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
context.Services.AddAbpDbContext<WorkflowManagementDbContext>(options => |
|||
{ |
|||
options.AddDefaultRepositories(includeAllEntities: true); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,18 @@ |
|||
using JetBrains.Annotations; |
|||
using Volo.Abp.EntityFrameworkCore.Modeling; |
|||
|
|||
namespace LINGYUN.Abp.WorkflowManagement.EntityFrameworkCore |
|||
{ |
|||
public class WorkflowManagementModelBuilderConfigurationOptions : AbpModelBuilderConfigurationOptions |
|||
{ |
|||
public WorkflowManagementModelBuilderConfigurationOptions( |
|||
[NotNull] string tablePrefix = "", |
|||
[CanBeNull] string schema = null) |
|||
: base( |
|||
tablePrefix, |
|||
schema) |
|||
{ |
|||
|
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,19 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="..\..\..\configureawait.props" /> |
|||
<Import Project="..\..\..\common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net6.0</TargetFramework> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Volo.Abp.AspNetCore.Mvc" Version="$(VoloAbpPackageVersion)" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\LINGYUN.Abp.WorkflowManagement.Application.Contracts\LINGYUN.Abp.WorkflowManagement.Application.Contracts.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,41 @@ |
|||
using LINGYUN.Abp.WorkflowManagement.Localization; |
|||
using Microsoft.Extensions.DependencyInjection; |
|||
using Volo.Abp.AspNetCore.Mvc; |
|||
using Volo.Abp.AspNetCore.Mvc.Localization; |
|||
using Volo.Abp.Localization; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.Validation.Localization; |
|||
|
|||
namespace LINGYUN.Abp.WorkflowManagement |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpAspNetCoreMvcModule), |
|||
typeof(WorkflowManagementApplicationContractsModule))] |
|||
public class WorkflowManagementHttpApiModule : AbpModule |
|||
{ |
|||
public override void PreConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
PreConfigure<IMvcBuilder>(mvcBuilder => |
|||
{ |
|||
mvcBuilder.AddApplicationPartIfNotExists(typeof(WorkflowManagementHttpApiModule).Assembly); |
|||
}); |
|||
|
|||
PreConfigure<AbpMvcDataAnnotationsLocalizationOptions>(options => |
|||
{ |
|||
options.AddAssemblyResource( |
|||
typeof(WorkflowManagementResource), |
|||
typeof(WorkflowManagementApplicationContractsModule).Assembly); |
|||
}); |
|||
} |
|||
|
|||
public override void ConfigureServices(ServiceConfigurationContext context) |
|||
{ |
|||
Configure<AbpLocalizationOptions>(options => |
|||
{ |
|||
options.Resources |
|||
.Get<WorkflowManagementResource>() |
|||
.AddBaseTypes(typeof(AbpValidationResource)); |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
<Project Sdk="Microsoft.NET.Sdk"> |
|||
|
|||
<Import Project="../../common.props" /> |
|||
|
|||
<PropertyGroup> |
|||
<TargetFramework>net5.0</TargetFramework> |
|||
<RootNamespace /> |
|||
</PropertyGroup> |
|||
|
|||
<ItemGroup> |
|||
<PackageReference Include="Volo.Abp.AspNetCore.Mvc" Version="$(VoloAbpPackageVersion)" /> |
|||
<PackageReference Include="Volo.Abp.SettingManagement.Domain" Version="$(VoloAbpPackageVersion)" /> |
|||
<PackageReference Include="LINGYUN.Abp.SettingManagement.Application.Contracts" Version="$(LINGYUNAbpPackageVersion)" /> |
|||
</ItemGroup> |
|||
|
|||
<ItemGroup> |
|||
<ProjectReference Include="..\LINGYUN.Abp.WorkflowManagement.Application.Contracts\LINGYUN.Abp.WorkflowManagement.Application.Contracts.csproj" /> |
|||
</ItemGroup> |
|||
|
|||
</Project> |
|||
@ -0,0 +1,77 @@ |
|||
using LINGYUN.Abp.WorkflowManagement.Authorization; |
|||
using LINGYUN.Abp.WorkflowManagement.Localization; |
|||
using LINGYUN.Abp.SettingManagement; |
|||
using Microsoft.AspNetCore.Authorization; |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.Application.Services; |
|||
using Volo.Abp.Features; |
|||
using Volo.Abp.MultiTenancy; |
|||
using Volo.Abp.SettingManagement; |
|||
using Volo.Abp.Settings; |
|||
|
|||
namespace LINGYUN.Abp.WorkflowManagement.SettingManagement |
|||
{ |
|||
[Authorize(WorkflowManagementPermissions.ManageSettings)] |
|||
public class SettingAppService : ApplicationService, ISettingAppService |
|||
{ |
|||
protected ISettingManager SettingManager { get; } |
|||
protected ISettingDefinitionManager SettingDefinitionManager { get; } |
|||
|
|||
public SettingAppService( |
|||
ISettingManager settingManager, |
|||
ISettingDefinitionManager settingDefinitionManager) |
|||
{ |
|||
SettingManager = settingManager; |
|||
SettingDefinitionManager = settingDefinitionManager; |
|||
LocalizationResource = typeof(WorkflowManagementResource); |
|||
} |
|||
|
|||
public virtual async Task<ListResultDto<SettingGroupDto>> GetAllForCurrentTenantAsync() |
|||
{ |
|||
return await GetAllForProviderAsync(TenantSettingValueProvider.ProviderName, CurrentTenant.GetId().ToString()); |
|||
} |
|||
|
|||
public virtual async Task SetCurrentTenantAsync(UpdateSettingsDto input) |
|||
{ |
|||
// 增加特性检查
|
|||
await CheckFeatureAsync(); |
|||
|
|||
if (CurrentTenant.IsAvailable) |
|||
{ |
|||
foreach (var setting in input.Settings) |
|||
{ |
|||
await SettingManager.SetForTenantAsync(CurrentTenant.GetId(), setting.Name, setting.Value); |
|||
} |
|||
|
|||
await CurrentUnitOfWork.SaveChangesAsync(); |
|||
} |
|||
} |
|||
|
|||
protected virtual async Task CheckFeatureAsync() |
|||
{ |
|||
await FeatureChecker.CheckEnabledAsync(SettingManagementFeatures.Enable); |
|||
} |
|||
|
|||
protected virtual async Task<ListResultDto<SettingGroupDto>> GetAllForProviderAsync(string providerName, string providerKey) |
|||
{ |
|||
var settingGroups = new List<SettingGroupDto>(); |
|||
|
|||
await Task.CompletedTask; |
|||
|
|||
return new ListResultDto<SettingGroupDto>(settingGroups); |
|||
} |
|||
|
|||
public Task SetGlobalAsync(UpdateSettingsDto input) |
|||
{ |
|||
throw new NotSupportedException(); |
|||
} |
|||
|
|||
public Task<ListResultDto<SettingGroupDto>> GetAllForGlobalAsync() |
|||
{ |
|||
throw new NotSupportedException(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,48 @@ |
|||
using LINGYUN.Abp.SettingManagement; |
|||
using Microsoft.AspNetCore.Mvc; |
|||
using System.Threading.Tasks; |
|||
using Volo.Abp; |
|||
using Volo.Abp.Application.Dtos; |
|||
using Volo.Abp.AspNetCore.Mvc; |
|||
|
|||
namespace LINGYUN.Abp.WorkflowManagement.SettingManagement |
|||
{ |
|||
[RemoteService(Name = WorkflowManagementRemoteServiceConsts.RemoteServiceName)] |
|||
[ApiVersion("2.0")] |
|||
[Area("WorkflowManagement")] |
|||
[Route("api/WorkflowManagement/settings")] |
|||
public class SettingController : AbpController, ISettingAppService |
|||
{ |
|||
private readonly ISettingAppService _settingAppService; |
|||
public SettingController(ISettingAppService settingAppService) |
|||
{ |
|||
_settingAppService = settingAppService; |
|||
} |
|||
|
|||
[HttpPut] |
|||
public virtual async Task SetCurrentTenantAsync(UpdateSettingsDto input) |
|||
{ |
|||
await _settingAppService.SetCurrentTenantAsync(input); |
|||
} |
|||
|
|||
[HttpGet] |
|||
public virtual async Task<ListResultDto<SettingGroupDto>> GetAllForCurrentTenantAsync() |
|||
{ |
|||
return await _settingAppService.GetAllForCurrentTenantAsync(); |
|||
} |
|||
|
|||
[HttpPost] |
|||
[Route("by-global")] |
|||
public virtual async Task SetGlobalAsync(UpdateSettingsDto input) |
|||
{ |
|||
await _settingAppService.SetGlobalAsync(input); |
|||
} |
|||
|
|||
[HttpGet] |
|||
[Route("by-global")] |
|||
public virtual async Task<ListResultDto<SettingGroupDto>> GetAllForGlobalAsync() |
|||
{ |
|||
return await _settingAppService.GetAllForGlobalAsync(); |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,15 @@ |
|||
using LINGYUN.Abp.SettingManagement; |
|||
using Volo.Abp.AspNetCore.Mvc; |
|||
using Volo.Abp.Modularity; |
|||
using Volo.Abp.SettingManagement; |
|||
|
|||
namespace LINGYUN.Abp.WorkflowManagement.SettingManagement |
|||
{ |
|||
[DependsOn( |
|||
typeof(AbpSettingManagementApplicationContractsModule), |
|||
typeof(AbpAspNetCoreMvcModule), |
|||
typeof(AbpSettingManagementDomainModule))] |
|||
public class WorkflowManagementSettingManagementModule : AbpModule |
|||
{ |
|||
} |
|||
} |
|||
Loading…
Reference in new issue