-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Added dependency injection extensions
- Loading branch information
1 parent
af4bfbc
commit 98eb6f4
Showing
8 changed files
with
254 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
37 changes: 37 additions & 0 deletions
37
src/WorkflowEngine.Hangfire/DependencyInjectionExtensions.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
using Microsoft.Extensions.DependencyInjection; | ||
using WorkflowEngine; | ||
using WorkflowEngine.Core; | ||
using WorkflowEngine.Core.Actions; | ||
using WorkflowEngine.Core.Expressions; | ||
|
||
namespace Microsoft.Extensions.DependencyInjection | ||
{ | ||
|
||
public static class DependencyInjectionExtensions | ||
{ | ||
public static IServiceCollection AddWorkflowEngine<TOutputsRepository>(this IServiceCollection services) | ||
where TOutputsRepository: class, IOutputsRepository | ||
{ | ||
services.AddTransient<IWorkflowExecutor, WorkflowExecutor>(); | ||
services.AddTransient<IActionExecutor, ActionExecutor>(); | ||
services.AddTransient<IHangfireWorkflowExecutor, HangfireWorkflowExecutor>(); | ||
services.AddTransient<IHangfireActionExecutor, HangfireWorkflowExecutor>(); | ||
services.AddTransient(typeof(ScheduledWorkflowTrigger<>)); | ||
|
||
services.AddScoped<IArrayContext, ArrayContext>(); | ||
services.AddScoped<IScopeContext, ScopeContext>(); | ||
services.AddScoped<IRunContextAccessor, RunContextFactory>(); | ||
services.AddAction<ForeachAction>("Foreach"); | ||
|
||
services.AddFunctions(); | ||
services.AddScoped<IOutputsRepository, TOutputsRepository>(); | ||
services.AddSingleton<IWorkflowRepository, DefaultWorkflowRepository>(); | ||
|
||
services.AddHostedService<WorkflowStarterBackgroundJob>(); | ||
|
||
return services; | ||
} | ||
|
||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
using Hangfire.Storage; | ||
using System.Collections.Generic; | ||
|
||
namespace WorkflowEngine | ||
{ | ||
public static class HangfireExtensions | ||
{ | ||
|
||
|
||
public static void SetJobExternalKey(this IStorageConnection connection, string externalId, string jobId) | ||
{ | ||
// This method can be implemented in 1.1.0 | ||
connection.SetRangeInHash($"x-backgroundjob-keys:{externalId}", new[] { new KeyValuePair<string, string>("JobId", jobId) }); | ||
} | ||
|
||
public static string GetJobIdByKey(this IStorageConnection connection, string externalId) | ||
{ | ||
// This method can be implemented in 1.1.0 | ||
var entries = connection.GetAllEntriesFromHash($"x-backgroundjob-keys:{externalId}"); | ||
if (entries == null || !entries.ContainsKey("JobId")) | ||
return null; | ||
|
||
return entries["JobId"]; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
using Hangfire.Client; | ||
using Hangfire.Common; | ||
using System; | ||
using System.Linq; | ||
|
||
namespace WorkflowEngine | ||
{ | ||
|
||
public class JobNaturalKeyAttribute : JobFilterAttribute, IClientFilter | ||
{ | ||
public JobNaturalKeyAttribute(string keyFormat) | ||
{ | ||
KeyFormat = keyFormat; | ||
} | ||
|
||
public string KeyFormat { get; private set; } | ||
|
||
public void OnCreated(CreatedContext filterContext) | ||
{ | ||
var key = String.Format(KeyFormat, args: filterContext.Job.Args.ToArray()); | ||
filterContext.Connection.SetJobExternalKey(key, filterContext.BackgroundJob.Id); | ||
|
||
} | ||
|
||
public void OnCreating(CreatingContext filterContext) | ||
{ | ||
|
||
|
||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
using Hangfire; | ||
using Hangfire.Client; | ||
using Hangfire.Common; | ||
using Hangfire.Storage; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Microsoft.Extensions.Logging; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using WorkflowEngine.Core; | ||
|
||
namespace WorkflowEngine | ||
{ | ||
|
||
public class ScheduledWorkflowTrigger<TWorkflow> where TWorkflow : IWorkflow, new() | ||
{ | ||
private readonly ILogger _logger; | ||
private readonly IBackgroundJobClient _backgroundJobClient; | ||
private readonly IStorageConnection _storageConnection; | ||
|
||
public ScheduledWorkflowTrigger(ILogger<ScheduledWorkflowTrigger<TWorkflow>> logger, IBackgroundJobClient backgroundJobClient, JobStorage storageConnection) | ||
{ | ||
_logger = logger; | ||
_backgroundJobClient = backgroundJobClient; | ||
_storageConnection = storageConnection.GetConnection(); | ||
} | ||
|
||
[JobNaturalKey("{0}")] | ||
public Task<string> Trigger(string externalid, bool create, DateTimeOffset time, Dictionary<string, object> inputs) | ||
{ | ||
var existingJob = _storageConnection.GetJobIdByKey(externalid); | ||
if (!string.IsNullOrEmpty(existingJob)) | ||
{ | ||
_logger.LogInformation("Cleaning up existing Hangfire Job {JobID}", existingJob); | ||
_backgroundJobClient.Delete(existingJob); | ||
} | ||
|
||
if (create) | ||
{ | ||
var workflow = new TWorkflow(); | ||
workflow.Manifest.Triggers.First().Value.Inputs = inputs; | ||
|
||
var job = _backgroundJobClient.Schedule<IHangfireWorkflowExecutor>((executor) => executor.TriggerAsync( | ||
new TriggerContext { Workflow = workflow, }), time); | ||
|
||
_logger.LogInformation("Created scheduled workflow job {JobID}", job); | ||
|
||
return Task.FromResult(job); | ||
} | ||
|
||
return Task.FromResult<string>(null); | ||
} | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
70 changes: 70 additions & 0 deletions
70
src/WorkflowEngine.Hangfire/WorkflowStarterBackgroundJob.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
using Hangfire; | ||
using Microsoft.Extensions.Hosting; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using WorkflowEngine; | ||
using WorkflowEngine.Core; | ||
|
||
namespace Microsoft.Extensions.DependencyInjection | ||
{ | ||
public class WorkflowStarterBackgroundJob : BackgroundService | ||
{ | ||
private readonly IServiceScopeFactory _serviceScopeFactory; | ||
|
||
public WorkflowStarterBackgroundJob(IServiceScopeFactory serviceScopeFactory) | ||
{ | ||
_serviceScopeFactory = serviceScopeFactory; | ||
} | ||
|
||
protected override async Task ExecuteAsync(CancellationToken stoppingToken) | ||
{ | ||
var first = true; | ||
while (!stoppingToken.IsCancellationRequested) | ||
{ | ||
using var scope = _serviceScopeFactory.CreateScope(); | ||
var sp = scope.ServiceProvider; | ||
|
||
var workflows = sp.GetRequiredService<IWorkflowRepository>(); | ||
var jobs = sp.GetRequiredService<IRecurringJobManager>(); | ||
|
||
foreach (var workflow in await workflows.GetAllWorkflows()) | ||
{ | ||
var trigger = workflow.Manifest.Triggers.FirstOrDefault(t => t.Value.Type == "TimerTrigger"); | ||
|
||
if (!trigger.Equals(default(KeyValuePair<string, TriggerMetadata>))) | ||
{ | ||
|
||
jobs.AddOrUpdate<IHangfireWorkflowExecutor>(workflow.Id.ToString(), | ||
(executor) => executor.TriggerAsync(new TriggerContext | ||
{ | ||
Workflow = workflow, | ||
Trigger = new Trigger | ||
{ | ||
Inputs = trigger.Value.Inputs, | ||
ScheduledTime = DateTimeOffset.UtcNow, | ||
Type = workflow.Manifest.Triggers.FirstOrDefault().Value.Type, | ||
Key = trigger.Key | ||
}, | ||
}), trigger.Value.Inputs["cronExpression"] as string); | ||
|
||
if (first && trigger.Value.Inputs.ContainsKey("runAtStartup") && (bool)trigger.Value.Inputs["runAtStartup"]) | ||
jobs.Trigger(workflow.Id.ToString()); | ||
} | ||
} | ||
|
||
|
||
|
||
first = false; | ||
await Task.Delay(TimeSpan.FromMinutes(5), stoppingToken); | ||
|
||
|
||
|
||
} | ||
|
||
|
||
} | ||
} | ||
} |