Skip to content

Commit 103afa0

Browse files
committed
Using scoped services with QuartzJobRunner
1 parent 322843f commit 103afa0

File tree

13 files changed

+348
-0
lines changed

13 files changed

+348
-0
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
# Visual Studio Version 16
4+
VisualStudioVersion = 16.0.28803.352
5+
MinimumVisualStudioVersion = 10.0.40219.1
6+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuartzWithScopedServices", "QuartzWithScopedServices\QuartzWithScopedServices.csproj", "{9949A250-8B59-49FF-9258-4279280977DD}"
7+
EndProject
8+
Global
9+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
10+
Debug|Any CPU = Debug|Any CPU
11+
Release|Any CPU = Release|Any CPU
12+
EndGlobalSection
13+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
14+
{9949A250-8B59-49FF-9258-4279280977DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15+
{9949A250-8B59-49FF-9258-4279280977DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
16+
{9949A250-8B59-49FF-9258-4279280977DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
17+
{9949A250-8B59-49FF-9258-4279280977DD}.Release|Any CPU.Build.0 = Release|Any CPU
18+
EndGlobalSection
19+
GlobalSection(SolutionProperties) = preSolution
20+
HideSolutionNode = FALSE
21+
EndGlobalSection
22+
GlobalSection(ExtensibilityGlobals) = postSolution
23+
SolutionGuid = {765EAF8C-DC2A-4137-A0BA-3720AD03DFD5}
24+
EndGlobalSection
25+
EndGlobal
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using Microsoft.Extensions.DependencyInjection;
2+
using Microsoft.Extensions.Logging;
3+
using Quartz;
4+
using System;
5+
using System.Threading.Tasks;
6+
7+
namespace QuartzWithScopedServices
8+
{
9+
10+
public class HelloWorldJob : IJob
11+
{
12+
private readonly ILogger<HelloWorldJob> _logger;
13+
14+
public HelloWorldJob(ILogger<HelloWorldJob> logger)
15+
{
16+
_logger = logger;
17+
}
18+
19+
public Task Execute(IJobExecutionContext context)
20+
{
21+
_logger.LogInformation("Hello world!");
22+
return Task.CompletedTask;
23+
}
24+
}
25+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using Microsoft.Extensions.DependencyInjection;
2+
using Quartz;
3+
using Quartz.Spi;
4+
using System;
5+
6+
namespace QuartzWithScopedServices
7+
{
8+
public class JobFactory : IJobFactory
9+
{
10+
private readonly IServiceProvider _serviceProvider;
11+
12+
public JobFactory(IServiceProvider serviceProvider)
13+
{
14+
_serviceProvider = serviceProvider;
15+
}
16+
17+
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
18+
{
19+
return _serviceProvider.GetRequiredService<QuartzJobRunner>();
20+
}
21+
22+
public void ReturnJob(IJob job)
23+
{
24+
// we let the DI container handler this
25+
}
26+
}
27+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using System;
2+
3+
namespace QuartzWithScopedServices
4+
{
5+
public class JobSchedule
6+
{
7+
public JobSchedule(Type jobType, string cronExpression)
8+
{
9+
JobType = jobType;
10+
CronExpression = cronExpression;
11+
}
12+
13+
public Type JobType { get; }
14+
public string CronExpression { get; }
15+
}
16+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using Microsoft.Extensions.DependencyInjection;
2+
using Microsoft.Extensions.Logging;
3+
using Quartz;
4+
using System;
5+
using System.Threading.Tasks;
6+
7+
namespace QuartzWithScopedServices
8+
{
9+
public class PrintGuidJob : IJob
10+
{
11+
private readonly ILogger<PrintGuidJob> _logger;
12+
private readonly Guid _guid;
13+
14+
public PrintGuidJob(ILogger<PrintGuidJob> logger)
15+
{
16+
_logger = logger;
17+
_guid = Guid.NewGuid();
18+
}
19+
20+
public Task Execute(IJobExecutionContext context)
21+
{
22+
_logger.LogInformation("The job GUID is: " + _guid);
23+
return Task.CompletedTask;
24+
}
25+
}
26+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.IO;
4+
using System.Linq;
5+
using System.Threading.Tasks;
6+
using Microsoft.AspNetCore;
7+
using Microsoft.AspNetCore.Hosting;
8+
using Microsoft.Extensions.Configuration;
9+
using Microsoft.Extensions.Logging;
10+
11+
namespace QuartzWithScopedServices
12+
{
13+
public class Program
14+
{
15+
public static void Main(string[] args)
16+
{
17+
CreateWebHostBuilder(args).Build().Run();
18+
}
19+
20+
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
21+
WebHost.CreateDefaultBuilder(args)
22+
.UseStartup<Startup>();
23+
}
24+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"$schema": "http://json.schemastore.org/launchsettings.json",
3+
"iisSettings": {
4+
"windowsAuthentication": false,
5+
"anonymousAuthentication": true,
6+
"iisExpress": {
7+
"applicationUrl": "http://localhost:55846",
8+
"sslPort": 0
9+
}
10+
},
11+
"profiles": {
12+
"QuartzWithScopedServices": {
13+
"commandName": "Project",
14+
"launchBrowser": false,
15+
"launchUrl": "api/values",
16+
"applicationUrl": "http://localhost:5000",
17+
"environmentVariables": {
18+
"ASPNETCORE_ENVIRONMENT": "Development"
19+
}
20+
}
21+
}
22+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Threading;
4+
using System.Threading.Tasks;
5+
using Microsoft.Extensions.Hosting;
6+
using Quartz;
7+
using Quartz.Spi;
8+
9+
namespace QuartzWithScopedServices
10+
{
11+
public class QuartzHostedService : IHostedService
12+
{
13+
private readonly ISchedulerFactory _schedulerFactory;
14+
private readonly IJobFactory _jobFactory;
15+
private readonly IEnumerable<JobSchedule> _jobSchedules;
16+
private IScheduler _scheduler;
17+
18+
public QuartzHostedService(
19+
ISchedulerFactory schedulerFactory,
20+
IEnumerable<JobSchedule> jobSchedules,
21+
IJobFactory jobFactory)
22+
{
23+
_schedulerFactory = schedulerFactory;
24+
_jobSchedules = jobSchedules;
25+
_jobFactory = jobFactory;
26+
}
27+
28+
public async Task StartAsync(CancellationToken cancellationToken)
29+
{
30+
_scheduler = await _schedulerFactory.GetScheduler(cancellationToken);
31+
_scheduler.JobFactory = _jobFactory;
32+
33+
foreach (var jobSchedule in _jobSchedules)
34+
{
35+
var job = CreateJob(jobSchedule);
36+
var trigger = CreateTrigger(jobSchedule);
37+
38+
await _scheduler.ScheduleJob(job, trigger, cancellationToken);
39+
}
40+
41+
await _scheduler.Start(cancellationToken);
42+
}
43+
44+
public async Task StopAsync(CancellationToken cancellationToken)
45+
{
46+
await _scheduler.Shutdown(cancellationToken);
47+
}
48+
49+
private static ITrigger CreateTrigger(JobSchedule schedule)
50+
{
51+
return TriggerBuilder
52+
.Create()
53+
.WithIdentity($"{schedule.JobType.FullName}.trigger")
54+
.WithCronSchedule(schedule.CronExpression)
55+
.WithDescription(schedule.CronExpression)
56+
.Build();
57+
}
58+
59+
private static IJobDetail CreateJob(JobSchedule schedule)
60+
{
61+
var jobType = schedule.JobType;
62+
return JobBuilder
63+
.Create(jobType)
64+
.WithIdentity(jobType.FullName)
65+
.WithDescription(jobType.Name)
66+
.Build();
67+
}
68+
}
69+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using Microsoft.Extensions.DependencyInjection;
2+
using Microsoft.Extensions.Logging;
3+
using Quartz;
4+
using System;
5+
using System.Threading.Tasks;
6+
7+
namespace QuartzWithScopedServices
8+
{
9+
[DisallowConcurrentExecution]
10+
public class QuartzJobRunner : IJob
11+
{
12+
private readonly IServiceProvider _serviceProvider;
13+
14+
public QuartzJobRunner(IServiceProvider serviceProvider)
15+
{
16+
_serviceProvider = serviceProvider;
17+
}
18+
19+
public async Task Execute(IJobExecutionContext context)
20+
{
21+
using (var scope = _serviceProvider.CreateScope())
22+
{
23+
var job = scope.ServiceProvider.GetRequiredService(context.JobDetail.JobType) as IJob;
24+
25+
await job.Execute(context);
26+
}
27+
}
28+
}
29+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<Project Sdk="Microsoft.NET.Sdk.Web">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netcoreapp2.2</TargetFramework>
5+
<AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
6+
</PropertyGroup>
7+
8+
<ItemGroup>
9+
<PackageReference Include="Microsoft.AspNetCore.App" />
10+
<PackageReference Include="Quartz" Version="3.0.7" />
11+
</ItemGroup>
12+
13+
</Project>

0 commit comments

Comments
 (0)