fglaeser / Quartz.Extensions.DependencyInjection

Helper to register Quartz Scheduler and Jobs into the .NET Core dependency injection container.
MIT License
10 stars 1 forks source link

Jobs should usually not be singletons #3

Closed dfyx closed 4 years ago

dfyx commented 4 years ago

When creating jobs as singletons, there are (at least) two problems:

Instead, jobs should be registered as scoped or transient with each job execution opening a new scope. Here's my implementation for a job factory:

    public class ScopedJobFactory : IJobFactory
    {
        private readonly IServiceProvider _serviceProvider;

        private readonly ConcurrentDictionary<IJob, IServiceScope> _serviceScopes = new ConcurrentDictionary<IJob, IServiceScope>();

        public DependencyInjectionJobFactory(IServiceProvider serviceProvider)
        {
            _serviceProvider = serviceProvider;
        }

        public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
        {
            var jobType = bundle.JobDetail.JobType;
            var scope = _serviceProvider.CreateScope();

            var job = (IJob)(scope.ServiceProvider.GetService(jobType)
                             ?? ActivatorUtilities.CreateInstance(scope.ServiceProvider, jobType));

            _serviceScopes.TryAdd(job, scope);
            return job;
        }

        public void ReturnJob(IJob job)
        {
            if (job is IDisposable disposable)
            {
                disposable.Dispose();
            }

            if (_serviceScopes.TryRemove(job, out var scope))
            {
                scope.Dispose();
            }
        }
    }

There might be some edge cases with disposing jobs which I haven't tested yet but the general idea should work. As an added bonus, you can schedule jobs without registering them in the service collection, as long as all their dependencies are registered.

fglaeser commented 4 years ago

Hi, I will test the factory, thank you very match for your contribution.

fglaeser commented 4 years ago

Hi @dfyx, The factory will be available in the release 0.3.0 also with other features.

Thanks again.