-
-
Save Antaris/9c3c097d31a90da279e3e6d78497a369 to your computer and use it in GitHub Desktop.
using System; | |
using System.Collections.Generic; | |
using Microsoft.Extensions.DependencyInjection; | |
using Quartz; | |
using Quartz.Spi; | |
public class ServiceProviderJobFactory : IJobFactory | |
{ | |
private readonly IServiceProvider _rootServiceProvider; | |
private ConcurrentDictionary<Type, IServiceScope> _scopes = new ConcurrentDictionary<Type, IServiceScope>(); | |
public ServiceProviderJobFactory(IServiceProvider rootServiceProvider) | |
{ | |
_rootServiceProvider = rootServiceProvider ?? throw new ArgumentNullException(rootServiceProvider); | |
} | |
public IJob NewJob(TriggerFireBundle bundle, IScheduler scheduler) | |
{ | |
var jobType = bundle.JobDetail.JobType; | |
// MA - Generate a scope for the job, this allows the job to be registered | |
// using .AddScoped<T>() which means we can use scoped dependencies | |
// e.g. database contexts | |
var scope = _scopes.GetOrAdd(jobType, t => _rootServiceProvider.CreateScope()); | |
return (IJob)scope.ServiceProvider.GetRequiredService(jobType); | |
} | |
public void ReturnJob(IJob job) | |
{ | |
var jobType = job?.GetType(); | |
if (job != null && _scopes.TryGetValue(jobType, out var scope) | |
{ | |
// MA - Dispose of the scope, which disposes of the job's dependencies | |
scope.Dispose(); | |
// MA - Remove the scope so the next time the job is resolved, | |
// we can get a new job instance | |
_scopes.TryRemove(jobType, out _); | |
} | |
} | |
} |
Why the factory pattern must be used? Are there other ways to achieve the same result in a much cleaner way?
Quartz now has a baked in solution using their new Quartz.Extensions.Hosting
package
https://andrewlock.net/using-quartz-net-with-asp-net-core-and-worker-services/
Quartz now has a baked in solution using their new
Quartz.Extensions.Hosting
packagehttps://andrewlock.net/using-quartz-net-with-asp-net-core-and-worker-services/
Thank you, I literally have found that blog at the same time you wrote me :)
I checked the provided link about Quartz.Extensions.Hosting but what happens If I need to create jobs based on some information received after the worker service is started.
Let's say I have a BackgroundService hosted in a windows service and this windows service is responsible for creating new jobs based on some information received from other applications, let's say, a desktop application; unfortunately the above link about Quartz.Extensions.Hosting, does not help at all. Please correct me if I'm wrong.
Thanks, AndyPook for the provided sample.
How about https://github.com/AndyPook/QuartzHostedService/blob/master/QuartzHostedService/ScopedJobFactory.cs as another alternative?
Tightly associates the scope with the job, avoids the dictionary...