├── .gitignore
├── ConsoleApp
├── ConsoleApp.csproj
├── Program.cs
└── TestJob.cs
├── ConsoleAppNET
├── App.config
├── ConsoleAppNET.csproj
├── Program.cs
├── Properties
│ └── AssemblyInfo.cs
└── packages.config
├── LICENSE
├── QuartzWebApi.Tests
├── Properties
│ └── AssemblyInfo.cs
├── QuartzWebApi.Tests.csproj
├── TestJob.cs
├── UnitTest1.cs
├── app.config
├── obj
│ └── Debug
│ │ ├── .NETFramework,Version=v4.8.AssemblyAttributes.cs
│ │ └── DesignTimeResolveAssemblyReferencesInput.cache
└── packages.config
├── QuartzWebApi.sln
├── QuartzWebApi.sln.DotSettings
├── QuartzWebApi
├── Controllers
│ └── SchedulerController.cs
├── Loggers
│ ├── Console.cs
│ ├── File.cs
│ └── Stream.cs
├── QuartzWebApi.csproj
├── SchedulerConnector.cs
├── SchedulerHost.cs
├── Startup.cs
└── Wrappers
│ ├── Calendars
│ ├── AbstractClassContractResolver.cs
│ ├── AnnualCalendar.cs
│ ├── BaseCalendar.cs
│ ├── BaseConverter.cs
│ ├── CalendarType.cs
│ ├── CronCalendar.cs
│ ├── DailyCalendar.cs
│ ├── HolidayCalendar.cs
│ ├── MonthlyCalendar.cs
│ └── WeeklyCalendar.cs
│ ├── GroupMatcher.cs
│ ├── GroupMatcherType.cs
│ ├── JobDetail.cs
│ ├── JobDetailWithTrigger.cs
│ ├── JobDetailWithTriggers.cs
│ ├── JobExecutionContext.cs
│ ├── JobExecutionContexts.cs
│ ├── JobKey.cs
│ ├── JobKeyWithDataMap.cs
│ ├── JobKeys.cs
│ ├── Key.cs
│ ├── RescheduleJob.cs
│ ├── RunningJobs.cs
│ ├── ScheduleJobs.cs
│ ├── SchedulerContext.cs
│ ├── SchedulerMetaData.cs
│ ├── Trigger.cs
│ ├── TriggerKey.cs
│ ├── TriggerKeys.cs
│ └── Triggers.cs
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.sln.docstates
8 |
9 | # Build results
10 |
11 | [Dd]ebug/
12 | [Rr]elease/
13 | x64/
14 | build/
15 | [Bb]in/
16 | [Oo]bj/
17 |
18 | # Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
19 | !packages/*/build/
20 |
21 | # MSTest test Results
22 | [Tt]est[Rr]esult*/
23 | [Bb]uild[Ll]og.*
24 |
25 | *_i.c
26 | *_p.c
27 | *.ilk
28 | *.meta
29 | *.obj
30 | *.pch
31 | *.pdb
32 | *.pgc
33 | *.pgd
34 | *.rsp
35 | *.sbr
36 | *.tlb
37 | *.tli
38 | *.tlh
39 | *.tmp
40 | *.tmp_proj
41 | *.log
42 | *.vspscc
43 | *.vssscc
44 | .builds
45 | *.pidb
46 | *.log
47 | *.scc
48 |
49 | # Visual C++ cache files
50 | ipch/
51 | *.aps
52 | *.ncb
53 | *.opensdf
54 | *.sdf
55 | *.cachefile
56 |
57 | # Visual Studio profiler
58 | *.psess
59 | *.vsp
60 | *.vspx
61 |
62 | # Guidance Automation Toolkit
63 | *.gpState
64 |
65 | # ReSharper is a .NET coding add-in
66 | _ReSharper*/
67 | *.[Rr]e[Ss]harper
68 |
69 | # TeamCity is a build add-in
70 | _TeamCity*
71 |
72 | # DotCover is a Code Coverage Tool
73 | *.dotCover
74 |
75 | # NCrunch
76 | *.ncrunch*
77 | .*crunch*.local.xml
78 |
79 | # Installshield output folder
80 | [Ee]xpress/
81 |
82 | # DocProject is a documentation generator add-in
83 | DocProject/buildhelp/
84 | DocProject/Help/*.HxT
85 | DocProject/Help/*.HxC
86 | DocProject/Help/*.hhc
87 | DocProject/Help/*.hhk
88 | DocProject/Help/*.hhp
89 | DocProject/Help/Html2
90 | DocProject/Help/html
91 |
92 | # Click-Once directory
93 | publish/
94 |
95 | # Publish Web Output
96 | *.Publish.xml
97 |
98 | # NuGet Packages Directory
99 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line
100 | #packages/
101 |
102 | # Windows Azure Build Output
103 | csx
104 | *.build.csdef
105 |
106 | # Windows Store app package directory
107 | AppPackages/
108 |
109 | # Others
110 | sql/
111 | *.Cache
112 | ClientBin/
113 | [Ss]tyle[Cc]op.*
114 | ~$*
115 | *~
116 | *.dbmdl
117 | *.[Pp]ublish.xml
118 | *.pfx
119 | *.publishsettings
120 |
121 | # RIA/Silverlight projects
122 | Generated_Code/
123 |
124 | # Backup & report files from converting an old project file to a newer
125 | # Visual Studio version. Backup files are not needed, because we have git ;-)
126 | _UpgradeReport_Files/
127 | Backup*/
128 | UpgradeLog*.XML
129 | UpgradeLog*.htm
130 |
131 | # SQL Server files
132 | App_Data/*.mdf
133 | App_Data/*.ldf
134 |
135 |
136 | #LightSwitch generated files
137 | GeneratedArtifacts/
138 | _Pvt_Extensions/
139 | ModelManifest.xml
140 |
141 | # =========================
142 | # Windows detritus
143 | # =========================
144 |
145 | # Windows image file caches
146 | Thumbs.db
147 | ehthumbs.db
148 |
149 | # Folder config file
150 | Desktop.ini
151 |
152 | # Recycle Bin used on file shares
153 | $RECYCLE.BIN/
154 |
155 | # Mac desktop service store files
156 | .DS_Store
157 | packages/
158 | .vs/
159 |
--------------------------------------------------------------------------------
/ConsoleApp/ConsoleApp.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 | enable
7 | enable
8 | latest
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/ConsoleApp/Program.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Specialized;
2 | using System.Net;
3 | using ConsoleApp;
4 | using Quartz;
5 | using Quartz.Impl;
6 | using Quartz.Impl.Calendar;
7 | using QuartzWebApi;
8 |
9 | var properties = new NameValueCollection
10 | {
11 | ["quartz.scheduler.exporter.bindName"] = "Scheduler",
12 | ["quartz.scheduler.exporter.channelName"] = "tcpQuartz",
13 | ["quartz.scheduler.exporter.channelType"] = "tcp",
14 | ["quartz.scheduler.exporter.port"] = "45000",
15 | ["quartz.scheduler.exporter.type"] = "Quartz.Simpl.RemotingSchedulerExporter, Quartz",
16 | ["quartz.scheduler.instanceName"] = Dns.GetHostEntry(Environment.MachineName).HostName.Replace(".", "_"),
17 | ["quartz.jobStore.type"] = "Quartz.Simpl.RAMJobStore, Quartz",
18 | ["quartz.threadPool.type"] = "Quartz.Simpl.SimpleThreadPool, Quartz"
19 | };
20 |
21 | var scheduler = new StdSchedulerFactory(properties).GetScheduler().Result;
22 |
23 | scheduler.Context.Add("key1", "value1");
24 | scheduler.Context.Add("key2", "value2");
25 | scheduler.Context.Add("key3", "value3");
26 |
27 | scheduler.Start();
28 |
29 | var job = new TestJob();
30 | var schedulerJob = JobBuilder.Create(job.GetType())
31 | .WithIdentity(new JobKey("JobKeyName", "JobKeyGroup"))
32 | .WithDescription("Test")
33 | .RequestRecovery()
34 | .Build();
35 |
36 | var schedulerTrigger = (ISimpleTrigger)TriggerBuilder.Create()
37 | .WithIdentity("triggerKey")
38 | .WithDescription("TestTrigger")
39 | .StartAt(DateTime.Now)
40 | .Build();
41 |
42 | var mc = new MonthlyCalendar();
43 | mc.SetDayExcluded(1, true);
44 | mc.SetDayExcluded(12, true);
45 | scheduler.AddCalendar("monthlyCalendar", mc, true, true);
46 | scheduler.ScheduleJob(schedulerJob, schedulerTrigger);
47 |
48 | var host = new SchedulerHost("http://localhost:44344", scheduler, null);
49 | host.Start();
50 |
51 | var connector = new SchedulerConnector("http://localhost:44344");
52 | var test = connector.GetMetaData().Result;
53 |
54 | Console.ReadKey();
--------------------------------------------------------------------------------
/ConsoleApp/TestJob.cs:
--------------------------------------------------------------------------------
1 | using Quartz;
2 |
3 | namespace ConsoleApp;
4 |
5 | public class TestJob : IJob
6 | {
7 | public Task Execute(IJobExecutionContext context)
8 | {
9 | while (true)
10 | {
11 | context.JobDetail.JobDataMap.PutAsString("Timer", DateTime.Now);
12 | Thread.Sleep(10000);
13 | }
14 | }
15 | }
--------------------------------------------------------------------------------
/ConsoleAppNET/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/ConsoleAppNET/ConsoleAppNET.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {5C27C0B4-2E28-46A5-BD4C-54F51D5041F0}
8 | Exe
9 | ConsoleAppNET
10 | ConsoleAppNET
11 | v4.8
12 | 512
13 | true
14 | true
15 |
16 |
17 |
18 | AnyCPU
19 | true
20 | full
21 | false
22 | bin\Debug\
23 | DEBUG;TRACE
24 | prompt
25 | 4
26 | 10
27 |
28 |
29 | AnyCPU
30 | pdbonly
31 | true
32 | bin\Release\
33 | TRACE
34 | prompt
35 | 4
36 | 10
37 |
38 |
39 |
40 | ..\packages\Microsoft.Bcl.AsyncInterfaces.8.0.0\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll
41 |
42 |
43 | ..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.8.0.0\lib\net462\Microsoft.Extensions.DependencyInjection.Abstractions.dll
44 |
45 |
46 | ..\packages\Microsoft.Extensions.Logging.Abstractions.8.0.0\lib\net462\Microsoft.Extensions.Logging.Abstractions.dll
47 |
48 |
49 | ..\packages\Microsoft.Owin.4.2.2\lib\net45\Microsoft.Owin.dll
50 |
51 |
52 | ..\packages\Microsoft.Owin.Host.HttpListener.4.2.2\lib\net45\Microsoft.Owin.Host.HttpListener.dll
53 |
54 |
55 | ..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll
56 |
57 |
58 | ..\packages\Owin.1.0\lib\net40\Owin.dll
59 |
60 |
61 | ..\packages\Quartz.3.8.1\lib\net472\Quartz.dll
62 |
63 |
64 | ..\packages\Quartz.Serialization.Json.3.8.1\lib\net472\Quartz.Serialization.Json.dll
65 |
66 |
67 |
68 | ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll
69 |
70 |
71 |
72 |
73 | ..\packages\System.Diagnostics.DiagnosticSource.8.0.0\lib\net462\System.Diagnostics.DiagnosticSource.dll
74 |
75 |
76 | ..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll
77 |
78 |
79 |
80 | ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
81 |
82 |
83 | ..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll
84 |
85 |
86 |
87 | ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | {d95e8519-ca6c-4e08-bf4c-2f2ee4fff728}
107 | QuartzWebApi
108 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/ConsoleAppNET/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Specialized;
3 | using System.Net;
4 | using System.Threading;
5 | using System.Threading.Tasks;
6 | using Quartz;
7 | using Quartz.Impl;
8 | using Quartz.Impl.Calendar;
9 | using QuartzWebApi;
10 |
11 | namespace ConsoleAppNET;
12 |
13 | internal class Program
14 | {
15 | static void Main(string[] args)
16 | {
17 | var properties = new NameValueCollection
18 | {
19 | ["quartz.scheduler.exporter.bindName"] = "Scheduler",
20 | ["quartz.scheduler.exporter.channelName"] = "tcpQuartz",
21 | ["quartz.scheduler.exporter.channelType"] = "tcp",
22 | ["quartz.scheduler.exporter.port"] = "45000",
23 | ["quartz.scheduler.exporter.type"] = "Quartz.Simpl.RemotingSchedulerExporter, Quartz",
24 | ["quartz.scheduler.instanceName"] = Dns.GetHostEntry(Environment.MachineName).HostName.Replace(".", "_"),
25 | ["quartz.jobStore.type"] = "Quartz.Simpl.RAMJobStore, Quartz",
26 | ["quartz.threadPool.type"] = "Quartz.Simpl.SimpleThreadPool, Quartz"
27 | };
28 |
29 | var scheduler = new StdSchedulerFactory(properties).GetScheduler().Result;
30 |
31 | scheduler.Context.Add("key1", "value1");
32 | scheduler.Context.Add("key2", "value2");
33 | scheduler.Context.Add("key3", "value3");
34 |
35 | scheduler.Start();
36 |
37 | var job = new TestJob();
38 | var schedulerJob = JobBuilder.Create(job.GetType())
39 | .WithIdentity(new JobKey("JobKeyName", "JobKeyGroup"))
40 | .WithDescription("Test")
41 | .RequestRecovery()
42 | .Build();
43 |
44 | var schedulerTrigger = (ISimpleTrigger)TriggerBuilder.Create()
45 | .WithIdentity("triggerKey")
46 | .WithDescription("TestTrigger")
47 | .StartAt(DateTime.Now)
48 | .Build();
49 |
50 | var mc = new MonthlyCalendar();
51 | mc.SetDayExcluded(1, true);
52 | mc.SetDayExcluded(12, true);
53 | scheduler.AddCalendar("monthlyCalendar", mc, true, true);
54 | scheduler.ScheduleJob(schedulerJob, schedulerTrigger);
55 |
56 | var host = new SchedulerHost("http://localhost:44344", scheduler, null);
57 | host.Start();
58 |
59 | var connector = new SchedulerConnector("http://localhost:44344");
60 | var paused = connector.IsJobGroupPaused("JobKeyGroup").Result;
61 |
62 |
63 | Console.ReadKey();
64 | }
65 | }
66 |
67 | public class TestJob : IJob
68 | {
69 | public Task Execute(IJobExecutionContext context)
70 | {
71 | while (true)
72 | {
73 | context.JobDetail.JobDataMap.PutAsString("Timer", DateTime.Now);
74 | Thread.Sleep(10000);
75 | }
76 | }
77 | }
--------------------------------------------------------------------------------
/ConsoleAppNET/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("ConsoleAppNET")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("ConsoleAppNET")]
13 | [assembly: AssemblyCopyright("Copyright © 2024")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("5c27c0b4-2e28-46a5-bd4c-54f51d5041f0")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/ConsoleAppNET/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Kees
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/QuartzWebApi.Tests/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("QuartzWebApi.Tests")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("QuartzWebApi.Tests")]
13 | [assembly: AssemblyCopyright("Copyright © 2022")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("e99aabc4-f815-487a-8efe-5625e7a07f64")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Build and Revision Numbers
33 | // by using the '*' as shown below:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/QuartzWebApi.Tests/QuartzWebApi.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Debug
8 | AnyCPU
9 | {E99AABC4-F815-487A-8EFE-5625E7A07F64}
10 | Library
11 | Properties
12 | QuartzWebApi.Tests
13 | QuartzWebApi.Tests
14 | v4.8
15 | 512
16 | {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
17 | False
18 | UnitTest
19 |
20 |
21 |
22 |
23 | true
24 | full
25 | false
26 | bin\Debug\
27 | DEBUG;TRACE
28 | prompt
29 | 4
30 | latest
31 |
32 |
33 | pdbonly
34 | true
35 | bin\Release\
36 | TRACE
37 | prompt
38 | 4
39 | latest
40 |
41 |
42 |
43 | ..\packages\Microsoft.ApplicationInsights.2.22.0\lib\net46\Microsoft.ApplicationInsights.dll
44 |
45 |
46 | ..\packages\Microsoft.Bcl.AsyncInterfaces.8.0.0\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll
47 |
48 |
49 |
50 | ..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.8.0.0\lib\net462\Microsoft.Extensions.DependencyInjection.Abstractions.dll
51 |
52 |
53 | ..\packages\Microsoft.Extensions.Logging.Abstractions.8.0.0\lib\net462\Microsoft.Extensions.Logging.Abstractions.dll
54 |
55 |
56 | ..\packages\Microsoft.Owin.4.2.2\lib\net45\Microsoft.Owin.dll
57 |
58 |
59 | ..\packages\Microsoft.Owin.Host.HttpListener.4.2.2\lib\net45\Microsoft.Owin.Host.HttpListener.dll
60 |
61 |
62 | ..\packages\Microsoft.Testing.Extensions.Telemetry.1.0.1\lib\netstandard2.0\Microsoft.Testing.Extensions.Telemetry.dll
63 |
64 |
65 | ..\packages\Microsoft.Testing.Extensions.TrxReport.Abstractions.1.0.1\lib\netstandard2.0\Microsoft.Testing.Extensions.TrxReport.Abstractions.dll
66 |
67 |
68 | ..\packages\Microsoft.Testing.Extensions.VSTestBridge.1.0.1\lib\netstandard2.0\Microsoft.Testing.Extensions.VSTestBridge.dll
69 |
70 |
71 | ..\packages\Microsoft.Testing.Platform.MSBuild.1.0.1\lib\netstandard2.0\Microsoft.Testing.Platform.dll
72 |
73 |
74 | ..\packages\Microsoft.Testing.Platform.MSBuild.1.0.1\lib\netstandard2.0\Microsoft.Testing.Platform.MSBuild.dll
75 |
76 |
77 | ..\packages\Microsoft.TestPlatform.ObjectModel.17.9.0\lib\net462\Microsoft.TestPlatform.CoreUtilities.dll
78 |
79 |
80 | ..\packages\Microsoft.TestPlatform.ObjectModel.17.9.0\lib\net462\Microsoft.TestPlatform.PlatformAbstractions.dll
81 |
82 |
83 | ..\packages\Microsoft.TestPlatform.ObjectModel.17.9.0\lib\net462\Microsoft.VisualStudio.TestPlatform.ObjectModel.dll
84 |
85 |
86 | ..\packages\MSTest.TestFramework.3.2.1\lib\net462\Microsoft.VisualStudio.TestPlatform.TestFramework.dll
87 |
88 |
89 | ..\packages\MSTest.TestFramework.3.2.1\lib\net462\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll
90 |
91 |
92 | ..\packages\NuGet.Frameworks.6.9.1\lib\net472\NuGet.Frameworks.dll
93 |
94 |
95 | ..\packages\Owin.1.0\lib\net40\Owin.dll
96 |
97 |
98 | ..\packages\Quartz.3.8.1\lib\net472\Quartz.dll
99 |
100 |
101 |
102 | ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll
103 |
104 |
105 | ..\packages\System.Collections.Immutable.8.0.0\lib\net462\System.Collections.Immutable.dll
106 |
107 |
108 |
109 |
110 |
111 |
112 | ..\packages\System.Diagnostics.DiagnosticSource.8.0.0\lib\net462\System.Diagnostics.DiagnosticSource.dll
113 |
114 |
115 | ..\packages\System.Memory.4.5.5\lib\net461\System.Memory.dll
116 |
117 |
118 |
119 |
120 | ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
121 |
122 |
123 | ..\packages\System.Reflection.Metadata.8.0.0\lib\net462\System.Reflection.Metadata.dll
124 |
125 |
126 |
127 | ..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll
128 |
129 |
130 |
131 |
132 | ..\packages\System.Threading.Tasks.Extensions.4.5.4\lib\net461\System.Threading.Tasks.Extensions.dll
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 | {d95e8519-ca6c-4e08-bf4c-2f2ee4fff728}
154 | QuartzWebApi
155 |
156 |
157 |
158 |
159 |
160 | This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
177 |
--------------------------------------------------------------------------------
/QuartzWebApi.Tests/TestJob.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 | using System.Threading.Tasks;
4 | using Quartz;
5 |
6 | namespace QuartzWebApi.Tests;
7 |
8 | public class TestJob : IJob
9 | {
10 | public Task Execute(IJobExecutionContext context)
11 | {
12 | while (true)
13 | {
14 | context.JobDetail.JobDataMap.PutAsString("Timer", DateTime.Now);
15 | Thread.Sleep(10000);
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/QuartzWebApi.Tests/UnitTest1.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.VisualStudio.TestTools.UnitTesting;
2 | using System;
3 | using System.Collections.Specialized;
4 | using Quartz;
5 | using Quartz.Impl;
6 | using Quartz.Impl.Calendar;
7 |
8 | namespace QuartzWebApi.Tests;
9 |
10 | [TestClass]
11 | public class UnitTest1
12 | {
13 | #region Fields
14 | private SchedulerHost _host;
15 | private SchedulerConnector _connector;
16 | #endregion
17 |
18 | #region Initialize
19 | ///
20 | /// Setup testing
21 | ///
22 | [TestInitialize]
23 | public void Initialize()
24 | {
25 | var properties = new NameValueCollection
26 | {
27 | ["quartz.scheduler.exporter.bindName"] = "Scheduler",
28 | ["quartz.scheduler.exporter.channelName"] = "tcpQuartz",
29 | ["quartz.scheduler.exporter.channelType"] = "tcp",
30 | ["quartz.scheduler.exporter.port"] = "45000",
31 | ["quartz.scheduler.exporter.type"] = "Quartz.Simpl.RemotingSchedulerExporter, Quartz",
32 | ["quartz.scheduler.instanceName"] = "SchedulerInstance",
33 | ["quartz.jobStore.type"] = "Quartz.Simpl.RAMJobStore, Quartz",
34 | ["quartz.threadPool.type"] = "Quartz.Simpl.SimpleThreadPool, Quartz"
35 | };
36 |
37 | var scheduler = new StdSchedulerFactory(properties).GetScheduler().Result;
38 |
39 | scheduler.Context.Add("key1", "value1");
40 | scheduler.Context.Add("key2", "value2");
41 | scheduler.Context.Add("key3", "value3");
42 |
43 | scheduler.Start();
44 |
45 | var job = new TestJob();
46 | var schedulerJob = JobBuilder.Create(job.GetType())
47 | .WithIdentity(new JobKey("JobKeyName", "JobKeyGroup"))
48 | .WithDescription("Test")
49 | .RequestRecovery()
50 | .Build();
51 |
52 | var schedulerTrigger = (ISimpleTrigger)TriggerBuilder.Create()
53 | .WithIdentity("triggerKey")
54 | .WithDescription("TestTrigger")
55 | .StartAt(DateTime.Now)
56 | .Build();
57 |
58 | var mc = new MonthlyCalendar();
59 | mc.SetDayExcluded(1, true);
60 | mc.SetDayExcluded(12, true);
61 | scheduler.AddCalendar("monthlyCalendar", mc, true, true);
62 | scheduler.ScheduleJob(schedulerJob, schedulerTrigger);
63 |
64 | _host = new SchedulerHost("http://localhost:44344", scheduler, null);
65 | _host.Start();
66 |
67 | _connector = new SchedulerConnector("http://localhost:44344");
68 | }
69 | #endregion
70 |
71 | #region Cleanup
72 | [TestCleanup]
73 | public void Cleanup()
74 | {
75 | _host.Stop();
76 | }
77 | #endregion
78 |
79 | [TestMethod]
80 | public void IsJobGroupPaused()
81 | {
82 | var paused = _connector.IsJobGroupPaused("JobKeyGroup").Result;
83 | Assert.IsFalse(paused);
84 | }
85 |
86 | [TestMethod]
87 | public void IsTriggerGroupPaused()
88 | {
89 | var paused = _connector.IsTriggerGroupPaused("JobKeyGroup").Result;
90 | Assert.IsFalse(paused);
91 | }
92 |
93 | [TestMethod]
94 | public void SchedulerName()
95 | {
96 | var name = _connector.SchedulerName().Result;
97 | Assert.AreEqual("SchedulerInstance", name);
98 | }
99 |
100 | [TestMethod]
101 | public void SchedulerInstanceId()
102 | {
103 | var id = _connector.SchedulerInstanceId().Result;
104 | Assert.AreEqual("NON_CLUSTERED", id);
105 | }
106 |
107 | [TestMethod]
108 | public void Context()
109 | {
110 | var result = _connector.Context().Result;
111 | Assert.AreEqual("value1", result["key1"]);
112 | Assert.AreEqual("value2", result["key2"]);
113 | Assert.AreEqual("value3", result["key3"]);
114 | }
115 |
116 | [TestMethod]
117 | public void GetMetaData()
118 | {
119 | var result = _connector.GetMetaData().Result;
120 | Assert.IsTrue(result.Summary.Contains("Quartz"));
121 | }
122 |
123 | [TestMethod]
124 | public void Start()
125 | {
126 | _connector.Start().GetAwaiter().GetResult();
127 | }
128 | }
--------------------------------------------------------------------------------
/QuartzWebApi.Tests/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/QuartzWebApi.Tests/obj/Debug/.NETFramework,Version=v4.8.AssemblyAttributes.cs:
--------------------------------------------------------------------------------
1 | //
2 | using System;
3 | using System.Reflection;
4 | [assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
5 |
--------------------------------------------------------------------------------
/QuartzWebApi.Tests/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sicos1977/QuartzWebApi/9b57a913d530824b96b6508394b37f454b2b6427/QuartzWebApi.Tests/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache
--------------------------------------------------------------------------------
/QuartzWebApi.Tests/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/QuartzWebApi.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.1.32421.90
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuartzWebApi.Tests", "QuartzWebApi.Tests\QuartzWebApi.Tests.csproj", "{E99AABC4-F815-487A-8EFE-5625E7A07F64}"
7 | EndProject
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QuartzWebApi", "QuartzWebApi\QuartzWebApi.csproj", "{D95E8519-CA6C-4E08-BF4C-2F2EE4FFF728}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {E99AABC4-F815-487A-8EFE-5625E7A07F64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {E99AABC4-F815-487A-8EFE-5625E7A07F64}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {E99AABC4-F815-487A-8EFE-5625E7A07F64}.Release|Any CPU.ActiveCfg = Release|Any CPU
19 | {E99AABC4-F815-487A-8EFE-5625E7A07F64}.Release|Any CPU.Build.0 = Release|Any CPU
20 | {D95E8519-CA6C-4E08-BF4C-2F2EE4FFF728}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {D95E8519-CA6C-4E08-BF4C-2F2EE4FFF728}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {D95E8519-CA6C-4E08-BF4C-2F2EE4FFF728}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {D95E8519-CA6C-4E08-BF4C-2F2EE4FFF728}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {AE16B40F-D3D7-4C75-A620-2874AF2D00F7}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/QuartzWebApi.sln.DotSettings:
--------------------------------------------------------------------------------
1 |
2 | True
3 | True
4 | True
5 | True
6 | True
7 | True
8 | True
9 | True
10 | True
11 | True
12 | True
13 | True
14 | True
15 | True
16 | True
17 | True
18 | True
19 | True
20 | True
21 | True
22 | True
23 | True
24 | True
25 | True
26 | True
27 | True
28 | True
29 | True
30 | True
31 | True
32 | True
33 | True
34 | True
35 | True
36 | True
37 | True
38 | True
39 | True
40 | True
41 | True
42 | True
43 | True
44 | True
45 | True
46 | True
47 | True
48 | True
49 | True
50 | True
51 | True
52 | True
53 | True
54 | True
55 | True
56 | True
57 | True
58 | True
59 | True
60 | True
61 | True
62 | True
63 | True
64 | True
65 | True
66 | True
67 | True
68 | True
69 | True
70 | True
71 | True
72 | True
73 | True
74 | True
75 | True
76 | True
77 | True
78 | True
79 | True
80 | True
81 | True
82 | True
83 | True
--------------------------------------------------------------------------------
/QuartzWebApi/Loggers/Console.cs:
--------------------------------------------------------------------------------
1 | namespace QuartzWebApi.Loggers;
2 |
3 | ///
4 | /// Writes log information to the console
5 | ///
6 | public class Console() : Stream(System.Console.OpenStandardOutput());
--------------------------------------------------------------------------------
/QuartzWebApi/Loggers/File.cs:
--------------------------------------------------------------------------------
1 | namespace QuartzWebApi.Loggers;
2 |
3 | ///
4 | /// Writes log information to a file
5 | ///
6 | public class File : Stream
7 | {
8 | ///
9 | /// Logs information to the given
10 | ///
11 | ///
12 | public File(string fileName) : base(System.IO.File.OpenWrite(fileName))
13 | {
14 | }
15 | }
--------------------------------------------------------------------------------
/QuartzWebApi/Loggers/Stream.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 | using Microsoft.Extensions.Logging;
4 |
5 | namespace QuartzWebApi.Loggers;
6 |
7 | ///
8 | /// Writes log information to a stream
9 | ///
10 | public class Stream : ILogger, IDisposable
11 | {
12 | #region Fields
13 | private System.IO.Stream _stream;
14 | private string _instanceId;
15 | #endregion
16 |
17 | #region Constructors
18 | ///
19 | /// Logs information to the given
20 | ///
21 | ///
22 | public Stream(System.IO.Stream stream)
23 | {
24 | _stream = stream;
25 | }
26 | #endregion
27 |
28 | #region BeginScope
29 | public IDisposable BeginScope(TState state)
30 | {
31 | _instanceId = state?.ToString();
32 | return null;
33 | }
34 | #endregion
35 |
36 | #region IsEnabled
37 | ///
38 | /// Will always return true
39 | ///
40 | ///
41 | ///
42 | public bool IsEnabled(LogLevel logLevel)
43 | {
44 | return true;
45 | }
46 | #endregion
47 |
48 | #region Log
49 | public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception,
50 | Func formatter)
51 | {
52 | var message = $"{formatter(state, exception)}";
53 |
54 | if (_stream == null || !_stream.CanWrite) return;
55 | var line =
56 | $"{DateTime.Now:yyyy-MM-ddTHH:mm:ss.fff}{(_instanceId != null ? $" - {_instanceId}" : string.Empty)} - {message}{Environment.NewLine}";
57 | var bytes = Encoding.UTF8.GetBytes(line);
58 | _stream.Write(bytes, 0, bytes.Length);
59 | _stream.Flush();
60 | }
61 | #endregion
62 |
63 | #region Dispose
64 | public void Dispose()
65 | {
66 | if (_stream == null)
67 | return;
68 |
69 | _stream.Dispose();
70 | _stream = null;
71 | }
72 | #endregion
73 | }
--------------------------------------------------------------------------------
/QuartzWebApi/QuartzWebApi.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net48;net6
5 | latest
6 | True
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/QuartzWebApi/SchedulerConnector.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Net.Http;
3 | using System.Threading.Tasks;
4 | using QuartzWebApi.Wrappers;
5 | // ReSharper disable UnusedMember.Global
6 |
7 | namespace QuartzWebApi;
8 |
9 | ///
10 | /// Connects to the
11 | ///
12 | public class SchedulerConnector
13 | {
14 | #region Fields
15 | private readonly HttpClient _httpClient;
16 | #endregion
17 |
18 | #region Constructor
19 | ///
20 | /// Create a new instance of the
21 | ///
22 | /// The host address of the scheduler
23 | public SchedulerConnector(string schedulerHostAddress)
24 | {
25 | _httpClient = new HttpClient();
26 | _httpClient.BaseAddress = new Uri(schedulerHostAddress);
27 | }
28 | #endregion
29 |
30 | #region IsJobGroupPaused
31 | ///
32 | /// Returns true if the given JobGroup is paused
33 | ///
34 | /// The group name
35 | ///
36 | public async Task IsJobGroupPaused(string groupName)
37 | {
38 | var response = await _httpClient.GetAsync($"Scheduler/IsJobGroupPaused/{groupName}").ConfigureAwait(false);
39 | return bool.Parse(await response.Content.ReadAsStringAsync());
40 | }
41 | #endregion
42 |
43 | #region IsTriggerGroupPaused
44 | ///
45 | /// Returns true if the given TriggerGroup is paused
46 | ///
47 | /// The group name
48 | ///
49 | public async Task IsTriggerGroupPaused(string groupName)
50 | {
51 | var response = await _httpClient.GetAsync($"Scheduler/IsTriggerGroupPaused/{groupName}").ConfigureAwait(false);
52 | return bool.Parse(await response.Content.ReadAsStringAsync());
53 | }
54 | #endregion
55 |
56 | #region SchedulerName
57 | ///
58 | /// Returns the name of the scheduler
59 | ///
60 | public async Task SchedulerName()
61 | {
62 | var response = await _httpClient.GetAsync("Scheduler/SchedulerName").ConfigureAwait(false);
63 | var result = await response.Content.ReadAsStringAsync();
64 | return result.Trim('\"');
65 | }
66 | #endregion
67 |
68 | #region SchedulerInstanceId
69 | ///
70 | /// Returns the instance id of the scheduler
71 | ///
72 | public async Task SchedulerInstanceId()
73 | {
74 | var response = await _httpClient.GetAsync("Scheduler/SchedulerInstanceId").ConfigureAwait(false);
75 | var result = await response.Content.ReadAsStringAsync();
76 | return result.Trim('\"');
77 | }
78 | #endregion
79 |
80 | #region Context
81 | ///
82 | /// Returns the of the .
83 | ///
84 | public async Task Context()
85 | {
86 | var response = await _httpClient.GetAsync("Scheduler/SchedulerContext").ConfigureAwait(false);
87 | var result = await response.Content.ReadAsStringAsync();
88 | return SchedulerContext.FromJsonString(result);
89 | }
90 | #endregion
91 |
92 | #region GetMetaData
93 | ///
94 | /// Get a object describing the settings
95 | /// and capabilities of the scheduler instance.
96 | ///
97 | ///
98 | /// Note that the data returned is an 'instantaneous' snapshot, and that as
99 | /// soon as it's returned, the meta-data values may be different.
100 | ///
101 | public async Task GetMetaData()
102 | {
103 | var response = await _httpClient.GetAsync("Scheduler/GetMetaData").ConfigureAwait(false);
104 | var json = await response.Content.ReadAsStringAsync();
105 | return SchedulerMetaData.FromJsonString(json);
106 | }
107 | #endregion
108 |
109 | public async Task Start()
110 | {
111 | await _httpClient.PostAsync("Scheduler/Start", null).ConfigureAwait(false);
112 | }
113 |
114 | public async Task StartDelayed(int delay)
115 | {
116 | var response = await _httpClient.PostAsync($"Scheduler/StartDelayed/{delay}", null);
117 | // Handle response if necessary
118 | }
119 | }
--------------------------------------------------------------------------------
/QuartzWebApi/SchedulerHost.cs:
--------------------------------------------------------------------------------
1 | #if NET48
2 | //using Microsoft.Owin;
3 | using System;
4 | using System.Collections.Generic;
5 | using System.Net.Http;
6 | using System.Net.Http.Headers;
7 | using System.Net.Http.Formatting;
8 | using Microsoft.Owin.Hosting;
9 | using System.Web.Http.Controllers;
10 | using System.Web.Http.Dispatcher;
11 | #endif
12 |
13 | #if NET6_0
14 | using Microsoft.AspNetCore.Hosting;
15 | using Microsoft.Extensions.DependencyInjection;
16 | using Microsoft.Extensions.Logging;
17 | #endif
18 |
19 | using Microsoft.Extensions.Logging;
20 | using Quartz;
21 |
22 | namespace QuartzWebApi;
23 |
24 | ///
25 | /// Acts as a host for the Web API
26 | ///
27 | ///
28 | /// Create a new instance of the class
29 | ///
30 | /// The base address, e.g. http://localhost:45000
31 | ///
32 | /// >
33 | public class SchedulerHost(string baseAddress, IScheduler scheduler, ILogger logger)
34 | {
35 | #region Fields
36 | #if NET48
37 | private IDisposable _webApp;
38 | #endif
39 | #if NET6_0
40 | private IWebHost _webHost;
41 | #endif
42 | #endregion
43 |
44 | #region Start
45 | ///
46 | /// Start the Web API
47 | ///
48 | public void Start()
49 | {
50 | #if NET48
51 | Startup.Scheduler = scheduler;
52 | Startup.Logger = logger;
53 | _webApp = WebApp.Start(baseAddress);
54 | #endif
55 |
56 | #if NET6_0
57 | var builder = new WebHostBuilder()
58 | .UseKestrel()
59 | .ConfigureServices(services => services.AddSingleton(scheduler))
60 | .UseStartup()
61 | .UseUrls(baseAddress)
62 | .ConfigureLogging(logging => logging.AddConsole());
63 |
64 | if (logger != null)
65 | builder.ConfigureServices(services => services.AddSingleton(logger));
66 |
67 | _webHost = builder.Build();
68 | _webHost.Start();
69 | #endif
70 | }
71 | #endregion
72 |
73 | #region Stop
74 | ///
75 | /// Stops the Web API
76 | ///
77 | public void Stop()
78 | {
79 | #if NET48
80 | _webApp?.Dispose();
81 | #endif
82 | #if NET6_0
83 | _webHost?.StopAsync();
84 | #endif
85 | }
86 | #endregion
87 | }
88 |
89 | #if NET48
90 | internal class JsonContentNegotiator(MediaTypeFormatter formatter) : IContentNegotiator
91 | {
92 | public ContentNegotiationResult Negotiate(Type type, HttpRequestMessage request, IEnumerable formatters)
93 | {
94 | var result = new ContentNegotiationResult(formatter, new MediaTypeHeaderValue("application/json"));
95 | return result;
96 | }
97 | }
98 |
99 | internal class CustomHttpControllerActivator(Func controllerFactory) : IHttpControllerActivator
100 | {
101 | private readonly Func _controllerFactory = controllerFactory ?? throw new ArgumentNullException(nameof(controllerFactory));
102 |
103 | public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType)
104 | {
105 | return _controllerFactory(request);
106 | }
107 | }
108 | #endif
--------------------------------------------------------------------------------
/QuartzWebApi/Startup.cs:
--------------------------------------------------------------------------------
1 |
2 | using Microsoft.Extensions.Logging;
3 | using Quartz;
4 | #if NET48
5 | using Owin;
6 | using System;
7 | using System.Net.Http;
8 | using System.Net.Http.Formatting;
9 | using System.Web.Http;
10 | using System.Web.Http.Controllers;
11 | using System.Web.Http.Dispatcher;
12 | using QuartzWebApi.Controllers;
13 | #endif
14 |
15 | #if NET6_0
16 | using System;
17 | using Microsoft.AspNetCore.Hosting;
18 | using Microsoft.Extensions.DependencyInjection;
19 | using Microsoft.AspNetCore.Builder;
20 | using Microsoft.Extensions.Logging;
21 | using Microsoft.Extensions.Hosting;
22 | #endif
23 |
24 | namespace QuartzWebApi;
25 |
26 | ///
27 | /// The startup class for OWIN or Kestrel
28 | ///
29 | internal class Startup
30 | {
31 | internal static IScheduler Scheduler;
32 | internal static ILogger Logger;
33 |
34 | #if NET48
35 | ///
36 | /// Configure the Web API that is hosted by OWIN
37 | ///
38 | ///
39 | public void Configuration(IAppBuilder app)
40 | {
41 | var config = new HttpConfiguration();
42 | config.MapHttpAttributeRoutes();
43 | config.Formatters.Clear();
44 | config.Formatters.Add(new JsonMediaTypeFormatter());
45 | var jsonFormatter = new JsonMediaTypeFormatter();
46 | config.Services.Replace(typeof(IContentNegotiator), new JsonContentNegotiator(jsonFormatter));
47 | var controllerFactory = new Func(_ => new SchedulerController(Scheduler, Logger));
48 | config.Services.Replace(typeof(IHttpControllerActivator), new CustomHttpControllerActivator(controllerFactory));
49 |
50 | config.Routes.MapHttpRoute(
51 | name: "DefaultApi",
52 | routeTemplate: "api/{controller}/{id}",
53 | defaults: new { id = RouteParameter.Optional }
54 | );
55 |
56 | app.UseErrorPage();
57 | app.UseWebApi(config);
58 | }
59 | #endif
60 |
61 | #if NET6_0
62 | ///
63 | /// Configure the service
64 | ///
65 | public IServiceProvider ConfigureServices(IServiceCollection services)
66 | {
67 | services.AddRouting();
68 | services.AddControllers();
69 | return services.BuildServiceProvider();
70 | }
71 |
72 | ///
73 | /// Configure the application
74 | ///
75 | ///
76 | ///
77 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
78 | {
79 | if (env.IsDevelopment())
80 | app.UseDeveloperExceptionPage();
81 |
82 | app.UseRouting();
83 |
84 | app.UseEndpoints(endpoints =>
85 | {
86 | endpoints.MapControllers(); // Map controllers for API endpoints
87 | });
88 | }
89 | #endif
90 | }
--------------------------------------------------------------------------------
/QuartzWebApi/Wrappers/Calendars/AbstractClassContractResolver.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Newtonsoft.Json;
3 | using Newtonsoft.Json.Serialization;
4 |
5 | namespace QuartzWebApi.Wrappers.Calendars;
6 |
7 | internal class AbstractClassContractResolver : DefaultContractResolver
8 | {
9 | protected override JsonConverter ResolveContractConverter(Type objectType)
10 | {
11 | if (typeof(BaseCalendar).IsAssignableFrom(objectType) && !objectType.IsAbstract)
12 | return null; // pretend TableSortRuleConvert is not specified (thus avoiding a stack overflow)
13 | return base.ResolveContractConverter(objectType);
14 | }
15 | }
--------------------------------------------------------------------------------
/QuartzWebApi/Wrappers/Calendars/AnnualCalendar.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Newtonsoft.Json;
4 | using Quartz;
5 |
6 | namespace QuartzWebApi.Wrappers.Calendars;
7 |
8 | ///
9 | /// A json wrapper for the
10 | ///
11 | public class AnnualCalendar : BaseCalendar
12 | {
13 | #region Properties
14 | ///
15 | /// Returns a collection of days of the year that are excluded
16 | ///
17 | [JsonProperty("DaysExcluded")]
18 | public List DaysExcluded { get; internal set; } = [];
19 | #endregion
20 |
21 | #region Constructor
22 | ///
23 | /// Takes a and wraps it in a json object
24 | ///
25 | ///
26 | public AnnualCalendar(Quartz.Impl.Calendar.AnnualCalendar annualCalendar) : base(annualCalendar)
27 | {
28 | foreach(var day in annualCalendar.DaysExcluded)
29 | DaysExcluded.Add(day);
30 | }
31 | #endregion
32 |
33 | #region ToCalendar
34 | ///
35 | /// Returns this object as a Quartz
36 | ///
37 | ///
38 | public override ICalendar ToCalendar()
39 | {
40 | var result = new Quartz.Impl.Calendar.AnnualCalendar
41 | {
42 | Description = Description,
43 | TimeZone = TimeZone
44 | };
45 |
46 | foreach (var day in DaysExcluded)
47 | result.SetDayExcluded(day, true);
48 |
49 | return result;
50 | }
51 | #endregion
52 |
53 | #region ToJsonString
54 | ///
55 | /// Returns this object as a json string
56 | ///
57 | ///
58 | public new string ToJsonString()
59 | {
60 | return JsonConvert.SerializeObject(this, Formatting.Indented);
61 | }
62 | #endregion
63 |
64 | #region FromJsonString
65 | ///
66 | /// Returns the object from the given string
67 | ///
68 | /// The json string
69 | ///
70 | ///
71 | ///
72 | public new static AnnualCalendar FromJsonString(string json)
73 | {
74 | return JsonConvert.DeserializeObject(json);
75 | }
76 | #endregion
77 | }
--------------------------------------------------------------------------------
/QuartzWebApi/Wrappers/Calendars/BaseCalendar.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 | using Newtonsoft.Json;
4 | using Newtonsoft.Json.Converters;
5 | using Quartz;
6 |
7 | namespace QuartzWebApi.Wrappers.Calendars;
8 |
9 | ///
10 | /// The base calendar for all calendars
11 | ///
12 | ///
13 | /// Takes a and wraps it in a json object
14 | ///
15 | ///
16 | [JsonConverter(typeof(BaseConverter))]
17 | public abstract class BaseCalendar(ICalendar calendar)
18 | {
19 | #region Properties
20 | ///
21 | /// The name of the calendar
22 | ///
23 | [JsonProperty("Name")]
24 | public string Name { get; internal set; }
25 |
26 | ///
27 | /// The of the calendar
28 | ///
29 | [JsonConverter(typeof(StringEnumConverter))]
30 | [JsonProperty("Type")]
31 | public CalendarType Type { get; internal set; }
32 |
33 | ///
34 | /// The description of the calendar
35 | ///
36 | [JsonProperty("Description", DefaultValueHandling = DefaultValueHandling.Ignore)]
37 | public string Description { get; internal set; } = calendar?.Description;
38 |
39 | ///
40 | /// The time zone of the calendar
41 | ///
42 | [JsonProperty("TimeZone", DefaultValueHandling = DefaultValueHandling.Ignore)]
43 | public TimeZoneInfo TimeZone { get; internal set; }
44 |
45 | ///
46 | /// The base of the calendar
47 | ///
48 | [JsonProperty("CalendarBase", DefaultValueHandling = DefaultValueHandling.Ignore)]
49 | public string CalendarBase { get; internal set; }
50 |
51 | ///
52 | /// If set to true [replace].
53 | ///
54 | [JsonProperty("Replace", DefaultValueHandling = DefaultValueHandling.Ignore)]
55 | public bool Replace { get; internal set; }
56 |
57 | ///
58 | /// Whether to update existing triggers that
59 | /// referenced the already existing calendar so that they are 'correct'
60 | /// based on the new trigger.
61 | ///
62 | [JsonProperty("UpdateTriggers", DefaultValueHandling = DefaultValueHandling.Ignore)]
63 | public bool UpdateTriggers { get; internal set; }
64 |
65 | #endregion
66 |
67 | #region ToJsonString
68 | ///
69 | /// Returns this object as a json string
70 | ///
71 | ///
72 | public string ToJsonString()
73 | {
74 | return JsonConvert.SerializeObject(this, Formatting.Indented);
75 | }
76 | #endregion
77 |
78 | #region FromJsonString
79 | ///
80 | /// Returns the object from the given string
81 | ///
82 | /// The json string
83 | ///
84 | ///
85 | ///
86 | public static BaseCalendar FromJsonString(string json)
87 | {
88 | return JsonConvert.DeserializeObject(json);
89 | }
90 | #endregion
91 |
92 | public abstract ICalendar ToCalendar();
93 | }
--------------------------------------------------------------------------------
/QuartzWebApi/Wrappers/Calendars/BaseConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Newtonsoft.Json;
3 | using Newtonsoft.Json.Linq;
4 |
5 | namespace QuartzWebApi.Wrappers.Calendars;
6 |
7 | ///
8 | /// A json converter for the
9 | ///
10 | internal class BaseConverter : JsonConverter
11 | {
12 | #region Properties
13 | public override bool CanWrite => false;
14 | #endregion
15 |
16 | #region CanConvert
17 | public override bool CanConvert(Type objectType)
18 | {
19 | return objectType == typeof(BaseCalendar);
20 | }
21 | #endregion
22 |
23 | #region ReadJson
24 | public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
25 | {
26 | var jobObject = JObject.Load(reader);
27 |
28 | if (jobObject["Type"] == null)
29 | throw new ArgumentException("Type is not set");
30 |
31 | var type = Enum.Parse(typeof(CalendarType), jobObject["Type"].ToString());
32 | var settings = new JsonSerializerSettings { ContractResolver = new AbstractClassContractResolver() };
33 |
34 | return type switch
35 | {
36 | CalendarType.Cron => JsonConvert.DeserializeObject(jobObject.ToString(), settings),
37 | CalendarType.Daily => JsonConvert.DeserializeObject(jobObject.ToString(), settings),
38 | CalendarType.Weekly => JsonConvert.DeserializeObject(jobObject.ToString(), settings),
39 | CalendarType.Monthly => JsonConvert.DeserializeObject(jobObject.ToString(), settings),
40 | CalendarType.Annual => JsonConvert.DeserializeObject(jobObject.ToString(), settings),
41 | CalendarType.Holiday => JsonConvert.DeserializeObject(jobObject.ToString(), settings),
42 | _ => throw new ArgumentException("Invalid type")
43 | };
44 | }
45 | #endregion
46 |
47 | #region WriteJson
48 | public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
49 | {
50 | throw new NotImplementedException();
51 | }
52 | #endregion
53 | }
--------------------------------------------------------------------------------
/QuartzWebApi/Wrappers/Calendars/CalendarType.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 |
3 | namespace QuartzWebApi.Wrappers.Calendars;
4 |
5 | public enum CalendarType
6 | {
7 | ///
8 | /// It is a cron calendar
9 | ///
10 | [DataMember(Name = "Cron")]
11 | Cron,
12 |
13 | ///
14 | /// It is a daily calendar
15 | ///
16 | [DataMember(Name = "Daily")]
17 | Daily,
18 |
19 | ///
20 | /// It is a week calendar
21 | ///
22 | [DataMember(Name = "Weekly")]
23 | Weekly,
24 |
25 | ///
26 | /// It is a monthly calendar
27 | ///
28 | [DataMember(Name = "Monthly")]
29 | Monthly,
30 |
31 | ///
32 | /// It is an annual calendar
33 | ///
34 | [DataMember(Name = "Annual")]
35 | Annual,
36 |
37 | ///
38 | /// It is a holiday calendar
39 | ///
40 | [DataMember(Name = "Holiday")]
41 | Holiday
42 | }
--------------------------------------------------------------------------------
/QuartzWebApi/Wrappers/Calendars/CronCalendar.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Newtonsoft.Json;
3 | using Quartz;
4 |
5 | namespace QuartzWebApi.Wrappers.Calendars;
6 |
7 | ///
8 | /// A json wrapper for the
9 | ///
10 | public class CronCalendar : BaseCalendar
11 | {
12 | #region Properties
13 | ///
14 | /// The cron expression
15 | ///
16 | ///
17 | /// Only used when the is
18 | ///
19 | [JsonProperty("CronExpression")]
20 | public string CronExpression { get; internal set; }
21 | #endregion
22 |
23 | #region Constructor
24 | ///
25 | /// Takes a and wraps it in a json object
26 | ///
27 | ///
28 | public CronCalendar(Quartz.Impl.Calendar.CronCalendar cronCalendar) : base(cronCalendar)
29 | {
30 | Type = CalendarType.Cron;
31 | CronExpression = cronCalendar?.CronExpression.CronExpressionString;
32 | TimeZone = cronCalendar?.TimeZone;
33 | }
34 | #endregion
35 |
36 | #region ToCalendar
37 | ///
38 | /// Returns this object as a Quartz
39 | ///
40 | ///
41 | public override ICalendar ToCalendar()
42 | {
43 | var result = new Quartz.Impl.Calendar.CronCalendar(CronExpression)
44 | {
45 | Description = Description,
46 | TimeZone = TimeZone
47 | };
48 |
49 | return result;
50 | }
51 | #endregion
52 |
53 | #region ToJsonString
54 | ///
55 | /// Returns this object as a json string
56 | ///
57 | ///
58 | public new string ToJsonString()
59 | {
60 | return JsonConvert.SerializeObject(this, Formatting.Indented);
61 | }
62 | #endregion
63 |
64 | #region FromJsonString
65 | ///
66 | /// Returns the object from the given string
67 | ///
68 | /// The json string
69 | ///
70 | ///
71 | ///
72 | public new static CronCalendar FromJsonString(string json)
73 | {
74 | return JsonConvert.DeserializeObject(json);
75 | }
76 | #endregion
77 | }
--------------------------------------------------------------------------------
/QuartzWebApi/Wrappers/Calendars/DailyCalendar.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Newtonsoft.Json;
3 | using Quartz;
4 |
5 | namespace QuartzWebApi.Wrappers.Calendars;
6 |
7 | ///
8 | /// A json wrapper for the
9 | ///
10 | public class DailyCalendar : BaseCalendar
11 | {
12 | #region Properties
13 | ///
14 | /// Must be in the format "HH:MM[:SS[:mmm]]" where:
15 | ///
16 | /// -
17 | /// HH is the hour of the specified time. The hour should be
18 | /// specified using military (24-hour) time and must be in the range
19 | /// 0 to 23.
20 | ///
21 | /// -
22 | /// MM is the minute of the specified time and must be in the range
23 | /// 0 to 59.
24 | ///
25 | /// -
26 | /// SS is the second of the specified time and must be in the range
27 | /// 0 to 59.
28 | ///
29 | /// -
30 | /// mmm is the millisecond of the specified time and must be in the
31 | /// range 0 to 999.
32 | ///
33 | /// - items enclosed in brackets ('[', ']') are optional.
34 | /// -
35 | /// The time range starting time must be before the time range ending
36 | /// time. Note this means that a time range may not cross daily
37 | /// boundaries (10PM - 2AM)
38 | ///
39 | ///
40 | ///
41 | ///
42 | /// Only used when the is
43 | ///
44 | [JsonProperty("RangeStartingTime")]
45 | public string RangeStartingTime { get; internal set; }
46 |
47 | ///
48 | /// Must be in the format "HH:MM[:SS[:mmm]]" where:
49 | ///
50 | /// -
51 | /// HH is the hour of the specified time. The hour should be
52 | /// specified using military (24-hour) time and must be in the range
53 | /// 0 to 23.
54 | ///
55 | /// -
56 | /// MM is the minute of the specified time and must be in the range
57 | /// 0 to 59.
58 | ///
59 | /// -
60 | /// SS is the second of the specified time and must be in the range
61 | /// 0 to 59.
62 | ///
63 | /// -
64 | /// mmm is the millisecond of the specified time and must be in the
65 | /// range 0 to 999.
66 | ///
67 | /// - items enclosed in brackets ('[', ']') are optional.
68 | /// -
69 | /// The time range starting time must be before the time range ending
70 | /// time. Note this means that a time range may not cross daily
71 | /// boundaries (10PM - 2AM)
72 | ///
73 | ///
74 | ///
75 | [JsonProperty("RangeEndingTime")]
76 | public string RangeEndingTime { get; internal set; }
77 |
78 | ///
79 | /// Indicates whether the time range represents an inverted time range (see
80 | /// class description).
81 | ///
82 | /// true if invert time range; otherwise, false.
83 | [JsonProperty("InvertTimeRange")]
84 | public bool InvertTimeRange { get; internal set; }
85 | #endregion
86 |
87 | #region Constructor
88 | ///
89 | /// Takes a and wraps it in a json object
90 | ///
91 | ///
92 | public DailyCalendar(Quartz.Impl.Calendar.DailyCalendar dailyCalendar) : base(dailyCalendar)
93 | {
94 | Type = CalendarType.Daily;
95 | RangeStartingTime = dailyCalendar.RangeStartingTime;
96 | RangeEndingTime = dailyCalendar.RangeEndingTime;
97 | InvertTimeRange = dailyCalendar.InvertTimeRange;
98 | TimeZone = dailyCalendar.TimeZone;
99 | }
100 | #endregion
101 |
102 | #region ToCalendar
103 | ///
104 | /// Returns this object as a Quartz
105 | ///
106 | ///
107 | public override ICalendar ToCalendar()
108 | {
109 | var result = new Quartz.Impl.Calendar.DailyCalendar(RangeStartingTime, RangeEndingTime)
110 | {
111 | Description = Description,
112 | TimeZone = TimeZone,
113 | InvertTimeRange = InvertTimeRange
114 | };
115 |
116 | return result;
117 | }
118 | #endregion
119 |
120 | #region ToJsonString
121 | ///
122 | /// Returns this object as a json string
123 | ///
124 | ///
125 | public new string ToJsonString()
126 | {
127 | return JsonConvert.SerializeObject(this, Formatting.Indented);
128 | }
129 | #endregion
130 |
131 | #region FromJsonString
132 | ///
133 | /// Returns the object from the given string
134 | ///
135 | /// The json string
136 | ///
137 | ///
138 | ///
139 | public new static DailyCalendar FromJsonString(string json)
140 | {
141 | return JsonConvert.DeserializeObject(json);
142 | }
143 | #endregion
144 | }
--------------------------------------------------------------------------------
/QuartzWebApi/Wrappers/Calendars/HolidayCalendar.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Newtonsoft.Json;
4 | using Quartz;
5 |
6 | namespace QuartzWebApi.Wrappers.Calendars;
7 |
8 | ///
9 | /// A json wrapper for the
10 | ///
11 | public class HolidayCalendar : BaseCalendar
12 | {
13 | #region Properties
14 | ///
15 | /// Returns a collection of dates representing the excluded
16 | /// days. Only the month, day and year of the returned dates are
17 | /// significant
18 | ///
19 | [JsonProperty("ExcludedDates")]
20 | public List ExcludedDates { get; internal set; }
21 | #endregion
22 |
23 | #region Constructor
24 | ///
25 | /// Takes a and wraps it in a json object
26 | ///
27 | ///
28 | public HolidayCalendar(Quartz.Impl.Calendar.HolidayCalendar holidayCalendar) : base(holidayCalendar)
29 | {
30 | Type = CalendarType.Holiday;
31 |
32 | foreach (var excludedDate in holidayCalendar.ExcludedDates)
33 | ExcludedDates.Add(excludedDate);
34 |
35 | TimeZone = holidayCalendar.TimeZone;
36 | }
37 | #endregion
38 |
39 | #region ToCalendar
40 | ///
41 | /// Returns this object as a Quartz
42 | ///
43 | ///
44 | public override ICalendar ToCalendar()
45 | {
46 | var result = new Quartz.Impl.Calendar.HolidayCalendar
47 | {
48 | Description = Description,
49 | TimeZone = TimeZone
50 | };
51 |
52 | foreach (var day in ExcludedDates)
53 | result.AddExcludedDate(day);
54 |
55 | return result;
56 | }
57 | #endregion
58 |
59 | #region ToJsonString
60 | ///
61 | /// Returns this object as a json string
62 | ///
63 | ///
64 | public new string ToJsonString()
65 | {
66 | return JsonConvert.SerializeObject(this, Formatting.Indented);
67 | }
68 | #endregion
69 |
70 | #region FromJsonString
71 | ///
72 | /// Returns the object from the given string
73 | ///
74 | /// The json string
75 | ///
76 | ///
77 | ///
78 | public new static HolidayCalendar FromJsonString(string json)
79 | {
80 | return JsonConvert.DeserializeObject(json);
81 | }
82 | #endregion
83 | }
--------------------------------------------------------------------------------
/QuartzWebApi/Wrappers/Calendars/MonthlyCalendar.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using Newtonsoft.Json;
3 | using Quartz;
4 |
5 | namespace QuartzWebApi.Wrappers.Calendars;
6 |
7 | ///
8 | /// A json wrapper for the
9 | ///
10 | public class MonthlyCalendar : BaseCalendar
11 | {
12 | #region Properties
13 | ///
14 | /// Returns a collection of days of the month that are excluded
15 | ///
16 | [JsonProperty("DaysExcluded")]
17 | public List DaysExcluded { get; internal set; } = [];
18 | #endregion
19 |
20 | #region Constructor
21 | ///
22 | /// Takes a and wraps it in a json object
23 | ///
24 | ///
25 | public MonthlyCalendar(Quartz.Impl.Calendar.MonthlyCalendar monthlyCalendar) : base(monthlyCalendar)
26 | {
27 | Type = CalendarType.Monthly;
28 |
29 | foreach(var day in monthlyCalendar.DaysExcluded)
30 | DaysExcluded.Add(day);
31 |
32 | TimeZone = monthlyCalendar.TimeZone;
33 | }
34 | #endregion
35 |
36 | #region ToCalendar
37 | ///
38 | /// Returns this object as a Quartz
39 | ///
40 | ///
41 | public override ICalendar ToCalendar()
42 | {
43 | var result = new Quartz.Impl.Calendar.MonthlyCalendar
44 | {
45 | Description = Description,
46 | TimeZone = TimeZone
47 | };
48 |
49 | for(var i = 0; i < DaysExcluded.Count; i++)
50 | result.SetDayExcluded(i + 1, DaysExcluded[i]);
51 |
52 | return result;
53 | }
54 | #endregion
55 |
56 | #region ToJsonString
57 | ///
58 | /// Returns this object as a json string
59 | ///
60 | ///
61 | public new string ToJsonString()
62 | {
63 | return JsonConvert.SerializeObject(this, Formatting.Indented);
64 | }
65 | #endregion
66 |
67 | #region FromJsonString
68 | ///
69 | /// Returns the object from the given string
70 | ///
71 | /// The json string
72 | ///
73 | ///
74 | ///
75 | public new static MonthlyCalendar FromJsonString(string json)
76 | {
77 | return JsonConvert.DeserializeObject(json);
78 | }
79 | #endregion
80 | }
--------------------------------------------------------------------------------
/QuartzWebApi/Wrappers/Calendars/WeeklyCalendar.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using Newtonsoft.Json;
4 | using Quartz;
5 |
6 | namespace QuartzWebApi.Wrappers.Calendars;
7 |
8 | ///
9 | /// A json wrapper for the
10 | ///
11 | public class WeeklyCalendar : BaseCalendar
12 | {
13 | #region Properties
14 | ///
15 | /// Returns a collection of days of the week that are excluded
16 | ///
17 | [JsonProperty("DaysExcluded")]
18 | public List DaysExcluded { get; internal set; } = [];
19 | #endregion
20 |
21 | #region Constructor
22 | ///
23 | /// Takes a and wraps it in a json object
24 | ///
25 | ///
26 | public WeeklyCalendar(Quartz.Impl.Calendar.WeeklyCalendar weeklyCalendar) : base(weeklyCalendar)
27 | {
28 | Type = CalendarType.Weekly;
29 |
30 | foreach(var day in weeklyCalendar.DaysExcluded)
31 | DaysExcluded.Add(day);
32 |
33 | TimeZone = weeklyCalendar.TimeZone;
34 | }
35 | #endregion
36 |
37 | #region ToCalendar
38 | ///
39 | /// Returns this object as a Quartz
40 | ///
41 | ///
42 | public override ICalendar ToCalendar()
43 | {
44 | var result = new Quartz.Impl.Calendar.WeeklyCalendar
45 | {
46 | Description = Description,
47 | TimeZone = TimeZone
48 | };
49 |
50 | for(var i = 0; i < DaysExcluded.Count; i++)
51 | result.SetDayExcluded((DayOfWeek) i + 1, DaysExcluded[i]);
52 |
53 | return result;
54 | }
55 | #endregion
56 |
57 | #region ToJsonString
58 | ///
59 | /// Returns this object as a json string
60 | ///
61 | ///
62 | public new string ToJsonString()
63 | {
64 | return JsonConvert.SerializeObject(this, Formatting.Indented);
65 | }
66 | #endregion
67 |
68 | #region FromJsonString
69 | ///
70 | /// Returns the object from the given string
71 | ///
72 | /// The json string
73 | ///
74 | ///
75 | ///
76 | public new static WeeklyCalendar FromJsonString(string json)
77 | {
78 | return JsonConvert.DeserializeObject(json);
79 | }
80 | #endregion
81 | }
--------------------------------------------------------------------------------
/QuartzWebApi/Wrappers/GroupMatcher.cs:
--------------------------------------------------------------------------------
1 | //
2 | // GroupMatcher.cs
3 | //
4 | // Author: Kees van Spelde
5 | //
6 | // Copyright (c) 2022 - 2024 Magic-Sessions. (www.magic-sessions.com)
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 | //
26 |
27 | using System;
28 | using Newtonsoft.Json;
29 | using Newtonsoft.Json.Converters;
30 | using Quartz.Util;
31 |
32 | namespace QuartzWebApi.Wrappers;
33 |
34 | ///
35 | /// Json wrapper for the Quartz
36 | ///
37 | ///
38 | public class GroupMatcher where T : Key
39 | {
40 | #region Properties
41 | ///
42 | /// The
43 | ///
44 | [JsonConverter(typeof(StringEnumConverter))]
45 | [JsonProperty("Type")]
46 | public GroupMatcherType Type { get; private set; }
47 |
48 | ///
49 | /// The value to match
50 | ///
51 | [JsonProperty("Value")]
52 | public string Value { get; private set; }
53 | #endregion
54 |
55 | #region Constructor
56 | ///
57 | /// Makes this object and sets it's needed properties
58 | ///
59 | /// The
60 | /// The value to match
61 | public GroupMatcher(GroupMatcherType type, string value)
62 | {
63 | Type = type;
64 | Value = value;
65 | }
66 | #endregion
67 |
68 | #region ToJsonString
69 | ///
70 | /// Returns this object as a json string
71 | ///
72 | ///
73 | public string ToJsonString()
74 | {
75 | return JsonConvert.SerializeObject(this, Formatting.Indented);
76 | }
77 | #endregion
78 |
79 | #region FromJsonString
80 | ///
81 | /// Returns the object from the given string
82 | ///
83 | /// The json string
84 | ///
85 | ///
86 | ///
87 | public static GroupMatcher FromJsonString(string json)
88 | {
89 | return JsonConvert.DeserializeObject>(json);
90 | }
91 | #endregion
92 |
93 | #region ToGroupMatcher
94 | public Quartz.Impl.Matchers.GroupMatcher ToGroupMatcher()
95 | {
96 | switch (Type)
97 | {
98 | case GroupMatcherType.Contains:
99 | return Quartz.Impl.Matchers.GroupMatcher.GroupContains(Value);
100 |
101 | case GroupMatcherType.EndsWith:
102 | return Quartz.Impl.Matchers.GroupMatcher.GroupEndsWith(Value);
103 |
104 | case GroupMatcherType.Equals:
105 | return Quartz.Impl.Matchers.GroupMatcher.GroupEquals(Value);
106 |
107 | case GroupMatcherType.StartsWith:
108 | return Quartz.Impl.Matchers.GroupMatcher.GroupStartsWith(Value);
109 |
110 | default:
111 | throw new ArgumentOutOfRangeException();
112 | }
113 | }
114 | #endregion
115 | }
--------------------------------------------------------------------------------
/QuartzWebApi/Wrappers/GroupMatcherType.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.Serialization;
2 |
3 | namespace QuartzWebApi.Wrappers;
4 |
5 | ///
6 | /// The matching type
7 | ///
8 | public enum GroupMatcherType
9 | {
10 | ///
11 | /// Should contain
12 | ///
13 | [DataMember(Name = "Contains")]
14 | Contains,
15 |
16 | ///
17 | /// Should end with
18 | ///
19 | [DataMember(Name = "EndsWith")]
20 | EndsWith,
21 |
22 | ///
23 | /// Should equal
24 | ///
25 | [DataMember(Name = "Equals")]
26 | Equals,
27 |
28 | ///
29 | /// Should start with
30 | ///
31 | [DataMember(Name = "StartsWith")]
32 | StartsWith
33 | }
--------------------------------------------------------------------------------
/QuartzWebApi/Wrappers/JobDetail.cs:
--------------------------------------------------------------------------------
1 | //
2 | // JobDetail.cs
3 | //
4 | // Author: Kees van Spelde
5 | //
6 | // Copyright (c) 2022 - 2024 Magic-Sessions. (www.magic-sessions.com)
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 | //
26 |
27 | using System;
28 | using Newtonsoft.Json;
29 | using Quartz;
30 |
31 | namespace QuartzWebApi.Wrappers;
32 |
33 | ///
34 | /// Json wrapper for the Quartz
35 | ///
36 | public class JobDetail
37 | {
38 | #region Properties
39 | ///
40 | /// The key that identifies this jobs uniquely
41 | ///
42 | [JsonProperty("JobKey")]
43 | public JobKey JobKey { get; private set; }
44 |
45 | ///
46 | /// Get or set the description given to the instance by its
47 | /// creator (if any)
48 | ///
49 | [JsonProperty("Description")]
50 | public string Description { get; private set; }
51 |
52 | ///
53 | /// Get or sets the instance of that will be executed
54 | ///
55 | [JsonProperty("JobType")]
56 | public string JobType { get; private set; }
57 |
58 | ///
59 | /// Get or set the that is associated with the
60 | ///
61 | [JsonProperty("JobDataMap")]
62 | public JobDataMap JobDataMap { get; private set; }
63 |
64 | ///
65 | /// Whether the should remain stored after it is
66 | /// orphaned (no s point to it)
67 | ///
68 | ///
69 | /// If not explicitly set, the default value is
70 | ///
71 | ///
72 | /// if the Job should remain persisted after being orphaned
73 | ///
74 | [JsonProperty("Durable")]
75 | public bool Durable { get; private set; }
76 |
77 | ///
78 | /// Whether the should be replaced
79 | ///
80 | [JsonProperty("Replace")]
81 | public bool Replace { get; private set; }
82 |
83 | ///
84 | /// Whether the should be stored durable while awaiting scheduling
85 | ///
86 | [JsonProperty("StoreNonDurableWhileAwaitingScheduling")]
87 | public bool StoreNonDurableWhileAwaitingScheduling { get; private set; }
88 | #endregion
89 |
90 | #region Constructor
91 | ///
92 | /// Creates this object and sets it's needed properties
93 | ///
94 | /// The key that identifies this jobs uniquely
95 | ///
96 | /// Get or set the description given to the instance by its
97 | /// creator (if any)
98 | ///
99 | /// Get or sets the instance of that will be executed
100 | ///
101 | /// Get or set the that is associated with the
102 | ///
103 | ///
104 | /// Whether the should remain stored after it is
105 | /// orphaned (no s point to it)
106 | ///
107 | /// Whether the should be replaced
108 | ///
109 | /// Whether the should be stored durable
110 | /// while awaiting scheduling
111 | ///
112 | public JobDetail(
113 | JobKey jobKey,
114 | string description,
115 | string jobType,
116 | JobDataMap jobDataMap,
117 | bool durable,
118 | bool replace,
119 | bool storeNonDurableWhileAwaitingScheduling)
120 | {
121 | JobKey = jobKey;
122 | Description = description;
123 | JobType = jobType;
124 | JobDataMap = jobDataMap;
125 | Durable = durable;
126 | Replace = replace;
127 | StoreNonDurableWhileAwaitingScheduling = storeNonDurableWhileAwaitingScheduling;
128 | }
129 |
130 | ///
131 | /// Create this object and sets it's needed properties
132 | ///
133 | ///
134 | ///
135 | ///
136 | public JobDetail(IJobDetail jobDetail)
137 | {
138 | JobKey = new JobKey(jobDetail.Key);
139 | Description = jobDetail.Description;
140 | JobType = jobDetail.JobType.ToString();
141 | JobDataMap = jobDetail.JobDataMap;
142 | Durable = jobDetail.Durable;
143 | }
144 | #endregion
145 |
146 | #region ToJobDetail
147 | ///
148 | /// Returns this object as a Quartz
149 | ///
150 | ///
151 | public IJobDetail ToJobDetail()
152 | {
153 | var type = Type.GetType(JobType);
154 |
155 | if (type == null)
156 | throw new Exception($"Could not find an IJob class with the type '{JobType}'");
157 |
158 | var job = JobBuilder.Create(type)
159 | .WithIdentity(JobKey.ToJobKey())
160 | .WithDescription(Description)
161 | .StoreDurably(Durable)
162 | .RequestRecovery()
163 | .Build();
164 |
165 | return job;
166 | }
167 | #endregion
168 |
169 | #region ToJsonString
170 | ///
171 | /// Returns this object as a json string
172 | ///
173 | ///
174 | public string ToJsonString()
175 | {
176 | return JsonConvert.SerializeObject(this, Formatting.Indented);
177 | }
178 | #endregion
179 |
180 | #region FromJsonString
181 | ///
182 | /// Returns the object from the given string
183 | ///
184 | /// The json string
185 | ///
186 | ///
187 | ///
188 | public static JobDetail FromJsonString(string json)
189 | {
190 | return JsonConvert.DeserializeObject(json);
191 | }
192 | #endregion
193 | }
--------------------------------------------------------------------------------
/QuartzWebApi/Wrappers/JobDetailWithTrigger.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 |
3 | namespace QuartzWebApi.Wrappers;
4 |
5 | ///
6 | /// Json wrapper to create a with a
7 | ///
8 | public class JobDetailWithTrigger
9 | {
10 | #region Properties
11 | ///
12 | ///
13 | ///
14 | [JsonProperty("JobDetail")]
15 | public JobDetail JobDetail { get; private set; }
16 |
17 | ///
18 | /// A list with related 's
19 | ///
20 | [JsonProperty("Trigger")]
21 | public Trigger Trigger { get; private set; }
22 | #endregion
23 |
24 | #region Constructor
25 | ///
26 | /// Makes this object and sets it's needed properties
27 | ///
28 | ///
29 | ///
30 | ///
31 | /// 's
32 | public JobDetailWithTrigger(JobDetail jobDetail, Trigger trigger)
33 | {
34 | JobDetail = jobDetail;
35 | Trigger = trigger;
36 | }
37 | #endregion
38 |
39 | #region ToJsonString
40 | ///
41 | /// Returns this object as a json string
42 | ///
43 | ///
44 | public string ToJsonString()
45 | {
46 | return JsonConvert.SerializeObject(this, Formatting.Indented);
47 | }
48 | #endregion
49 |
50 | #region FromJsonString
51 | ///
52 | /// Returns the object from the given string
53 | ///
54 | /// The json string
55 | ///
56 | ///
57 | ///
58 | public static JobDetailWithTrigger FromJsonString(string json)
59 | {
60 | return JsonConvert.DeserializeObject(json);
61 | }
62 | #endregion
63 | }
--------------------------------------------------------------------------------
/QuartzWebApi/Wrappers/JobDetailWithTriggers.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using Newtonsoft.Json;
4 | using Quartz;
5 |
6 | namespace QuartzWebApi.Wrappers;
7 |
8 | ///
9 | /// Json wrapper to create a with a list of s
10 | ///
11 | public class JobDetailWithTriggers
12 | {
13 | #region Properties
14 | ///
15 | ///
16 | ///
17 | [JsonProperty("JobDetail")]
18 | public JobDetail JobDetail { get; private set; }
19 |
20 | ///
21 | /// A list with related 's
22 | ///
23 | [JsonProperty("Triggers")]
24 | public List Triggers { get; private set; }
25 |
26 | ///
27 | /// true when the job needs to be replaced
28 | ///
29 | [JsonProperty("Replace")]
30 | public bool Replace { get; private set; }
31 | #endregion
32 |
33 | #region Constructor
34 | ///
35 | /// Makes this object and sets it's needed properties
36 | ///
37 | ///
38 | ///
39 | ///
40 | /// A list with related 's
41 | public JobDetailWithTriggers(JobDetail jobDetail, List triggers)
42 | {
43 | JobDetail = jobDetail;
44 | Triggers = triggers;
45 | }
46 | #endregion
47 |
48 | #region ToReadOnlyTriggerCollection
49 | ///
50 | /// Returns the as a
51 | ///
52 | ///
53 | public IReadOnlyCollection ToReadOnlyTriggerCollection()
54 | {
55 | return Triggers.Select(trigger => trigger.ToTrigger()).ToList();
56 | }
57 | #endregion
58 |
59 | #region ToJsonString
60 | ///
61 | /// Returns this object as a json string
62 | ///
63 | ///
64 | public string ToJsonString()
65 | {
66 | return JsonConvert.SerializeObject(this, Formatting.Indented);
67 | }
68 | #endregion
69 |
70 | #region FromJsonString
71 | ///
72 | /// Returns the object from the given string
73 | ///
74 | /// The json string
75 | ///
76 | ///
77 | ///
78 | public static JobDetailWithTriggers FromJsonString(string json)
79 | {
80 | return JsonConvert.DeserializeObject(json);
81 | }
82 | #endregion
83 | }
--------------------------------------------------------------------------------
/QuartzWebApi/Wrappers/JobExecutionContext.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Newtonsoft.Json;
3 | using Quartz;
4 |
5 | namespace QuartzWebApi.Wrappers;
6 |
7 | ///
8 | /// Json wrapper for the Quartz
9 | ///
10 | [JsonObject("JobExecutionContext")]
11 | public class JobExecutionContext(IJobExecutionContext jobExecutionContext)
12 | {
13 | #region Properties
14 | ///
15 | /// Get a handle to the instance that fired the
16 | /// .
17 | ///
18 | [JsonProperty("Scheduler")]
19 | public IScheduler Scheduler { get; private set; } = jobExecutionContext.Scheduler;
20 |
21 | ///
22 | /// Get a handle to the instance that fired the
23 | /// .
24 | ///
25 | [JsonProperty("Trigger")]
26 | public Trigger Trigger { get; private set; } = new(jobExecutionContext.Trigger);
27 |
28 | ///
29 | /// Get a handle to the referenced by the
30 | /// instance that fired the .
31 | ///
32 | [JsonProperty("Calender")]
33 | public ICalendar Calendar { get; private set; } = jobExecutionContext.Calendar;
34 |
35 | ///
36 | /// If the is being re-executed because of a 'recovery'
37 | /// situation, this method will return .
38 | ///
39 | [JsonProperty("Recovering")]
40 | public bool Recovering { get; private set; } = jobExecutionContext.Recovering;
41 |
42 | ///
43 | /// Returns the of the originally scheduled and now recovering job.
44 | ///
45 | ///
46 | /// When recovering a previously failed job execution this property returns the identity
47 | /// of the originally firing trigger. This recovering job will have been scheduled for
48 | /// the same firing time as the original job, and so is available via the
49 | /// property. The original firing time of the job can be
50 | /// accessed via the
51 | /// element of this job's .
52 | ///
53 | [JsonProperty("RecoveringTriggerKey")]
54 | public Quartz.TriggerKey RecoveringTriggerKey { get; private set; } = jobExecutionContext.RecoveringTriggerKey;
55 |
56 | ///
57 | /// Gets the refire count.
58 | ///
59 | /// The refire count.
60 | [JsonProperty("RefireCount")]
61 | public int RefireCount { get; private set; } = jobExecutionContext.RefireCount;
62 |
63 | ///
64 | /// Get the convenience of this execution context.
65 | ///
66 | ///
67 | ///
68 | /// The found on this object serves as a convenience -
69 | /// it is a merge of the found on the
70 | /// and the one found on the , with
71 | /// the value in the latter overriding any same-named values in the former.
72 | ///
73 | /// It is thus considered a 'best practice' that the Execute code of a Job
74 | /// retrieve data from the JobDataMap found on this object.
75 | ///
76 | ///
77 | ///
78 | /// NOTE: Do not expect value 'set' into this JobDataMap to somehow be
79 | /// set back onto a job's own JobDataMap.
80 | ///
81 | ///
82 | /// Attempts to change the contents of this map typically result in an
83 | /// illegal state.
84 | ///
85 | ///
86 | [JsonProperty("MergedJobDataMap")]
87 | public JobDataMap MergedJobDataMap { get; private set; } = jobExecutionContext.MergedJobDataMap;
88 |
89 | ///
90 | /// Get the associated with the .
91 | ///
92 | [JsonProperty("JobDetail")]
93 | public JobDetail JobDetail { get; private set; } = new(jobExecutionContext.JobDetail);
94 |
95 | ///
96 | /// Get the instance of the that was created for this
97 | /// execution.
98 | ///
99 | /// Note: The Job instance is not available through remote scheduler
100 | /// interfaces.
101 | ///
102 | ///
103 | [JsonProperty("JobInstance")]
104 | public string JobInstance { get; private set; } = jobExecutionContext.JobInstance.ToString();
105 |
106 | ///
107 | /// The actual time the trigger fired. For instance the scheduled time may
108 | /// have been 10:00:00 but the actual fire time may have been 10:00:03 if
109 | /// the scheduler was too busy.
110 | ///
111 | /// Returns the fireTimeUtc.
112 | ///
113 | [JsonProperty("FireTimeUtc")]
114 | public DateTimeOffset FireTimeUtc { get; private set; } = jobExecutionContext.FireTimeUtc;
115 |
116 | ///
117 | /// The scheduled time the trigger fired for. For instance the scheduled
118 | /// time may have been 10:00:00 but the actual fire time may have been
119 | /// 10:00:03 if the scheduler was too busy.
120 | ///
121 | /// Returns the scheduledFireTimeUtc.
122 | ///
123 | [JsonProperty("ScheduledFireTimeUtc")]
124 | public DateTimeOffset? ScheduledFireTimeUtc { get; private set; } = jobExecutionContext.ScheduledFireTimeUtc;
125 |
126 | ///
127 | /// Gets the previous fire time.
128 | ///
129 | /// The previous fire time.
130 | [JsonProperty("PreviousFireTimeUtc")]
131 | public DateTimeOffset? PreviousFireTimeUtc { get; private set; } = jobExecutionContext.PreviousFireTimeUtc;
132 |
133 | ///
134 | /// Gets the next fire time.
135 | ///
136 | /// The next fire time.
137 | [JsonProperty("NextFireTimeUtc")]
138 | public DateTimeOffset? NextFireTimeUtc { get; private set; } = jobExecutionContext.NextFireTimeUtc;
139 |
140 | ///
141 | /// Get the unique id that identifies this particular firing instance of the
142 | /// trigger that triggered this job execution. It is unique to this
143 | /// JobExecutionContext instance as well.
144 | ///
145 | /// the unique fire instance id
146 | ///
147 | [JsonProperty("FireInstanceId")]
148 | public string FireInstanceId { get; private set; } = jobExecutionContext.FireInstanceId;
149 |
150 | /////
151 | ///// Returns the result (if any) that the set before its
152 | ///// execution completed (the type of object set as the result is entirely up
153 | ///// to the particular job).
154 | /////
155 | /////
156 | /////
157 | ///// The result itself is meaningless to Quartz, but may be informative
158 | ///// to s or
159 | ///// s that are watching the job's
160 | ///// execution.
161 | /////
162 | ///// Set the result (if any) of the 's execution (the type of
163 | ///// object set as the result is entirely up to the particular job).
164 | /////
165 | ///// The result itself is meaningless to Quartz, but may be informative
166 | ///// to s or
167 | ///// s that are watching the job's
168 | ///// execution.
169 | /////
170 | /////
171 | //[JsonProperty("Result")]
172 | //public object Result { get; private set; }
173 |
174 | ///
175 | /// The amount of time the job ran for. The returned
176 | /// value will be until the job has actually completed (or thrown an
177 | /// exception), and is therefore generally only useful to
178 | /// s and s.
179 | ///
180 | [JsonProperty("JobRunTime")]
181 | public TimeSpan JobRunTime { get; private set; } = jobExecutionContext.JobRunTime;
182 | #endregion
183 |
184 | #region Constructor
185 | //Result = jobExecutionContext.Result;
186 | #endregion
187 | }
--------------------------------------------------------------------------------
/QuartzWebApi/Wrappers/JobExecutionContexts.cs:
--------------------------------------------------------------------------------
1 | //
2 | // JobExecutionContexts.cs
3 | //
4 | // Author: Kees van Spelde
5 | //
6 | // Copyright (c) 2022 - 2024 Magic-Sessions. (www.magic-sessions.com)
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 | //
26 |
27 | using System.Collections.Generic;
28 | using System.Collections.ObjectModel;
29 | using Newtonsoft.Json;
30 | using Quartz;
31 |
32 | namespace QuartzWebApi.Wrappers;
33 |
34 | ///
35 | /// Json wrapper for a list of Quartz s
36 | ///
37 | [JsonArray]
38 | public class JobExecutionContexts : List
39 | {
40 | #region Constructor
41 | ///
42 | /// Makes this object and sets it's needed properties
43 | ///
44 | ///
45 | /// A of
46 | ///
47 | public JobExecutionContexts(IReadOnlyCollection jobExecutionContexts)
48 | {
49 | foreach (var jobExecutionContext in jobExecutionContexts)
50 | Add(new JobExecutionContext(jobExecutionContext));
51 | }
52 | #endregion
53 |
54 | #region ToJsonString
55 | ///
56 | /// Returns this object as a json string
57 | ///
58 | ///
59 | public string ToJsonString()
60 | {
61 | return JsonConvert.SerializeObject(this, Formatting.Indented);
62 | }
63 | #endregion
64 |
65 | #region FromJsonString
66 | ///
67 | /// Returns the object from the given string
68 | ///
69 | /// The json string
70 | ///
71 | ///
72 | ///
73 | public static JobExecutionContexts FromJsonString(string json)
74 | {
75 | return JsonConvert.DeserializeObject(json);
76 | }
77 | #endregion
78 | }
--------------------------------------------------------------------------------
/QuartzWebApi/Wrappers/JobKey.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 |
3 | namespace QuartzWebApi.Wrappers;
4 |
5 | ///
6 | /// A json wrapper for the
7 | ///
8 | public class JobKey : Key
9 | {
10 | #region Constructor
11 | ///
12 | /// Makes this object and sets it's needed properties
13 | ///
14 | /// The name of the job
15 | [JsonConstructor]
16 | public JobKey(string name) : base(name)
17 | {
18 | }
19 |
20 | ///
21 | /// Makes this object and sets it's needed properties
22 | ///
23 | /// The name of the trigger
24 | /// The group of the trigger
25 | public JobKey(string name, string group) : base(name, group)
26 | {
27 | }
28 |
29 | ///
30 | /// Makes this object and sets it's needed properties
31 | ///
32 | /// The
33 | public JobKey(Quartz.JobKey key) : base(key.Name, key.Group)
34 | {
35 | }
36 | #endregion
37 |
38 | #region ToJobKey
39 | ///
40 | /// Returns this object as a Quartz
41 | ///
42 | ///
43 | public Quartz.JobKey ToJobKey()
44 | {
45 | return new Quartz.JobKey(Name, Group);
46 | }
47 | #endregion
48 |
49 | #region ToJsonString
50 | ///
51 | /// Returns this object as a json string
52 | ///
53 | ///
54 | public string ToJsonString()
55 | {
56 | return JsonConvert.SerializeObject(this, Formatting.Indented);
57 | }
58 | #endregion
59 |
60 | #region FromJsonString
61 | ///
62 | /// Returns the object from the given string
63 | ///
64 | /// The json string
65 | ///
66 | ///
67 | ///
68 | public static JobKey FromJsonString(string json)
69 | {
70 | return JsonConvert.DeserializeObject(json);
71 | }
72 | #endregion
73 | }
--------------------------------------------------------------------------------
/QuartzWebApi/Wrappers/JobKeyWithDataMap.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 | using Quartz;
3 |
4 | namespace QuartzWebApi.Wrappers;
5 |
6 | ///
7 | /// Json wrapper to create a with a
8 | ///
9 | public class JobKeyWithDataMap
10 | {
11 | #region Properties
12 | ///
13 | /// The
14 | ///
15 | [JsonProperty("JobKey")]
16 | public JobKey JobKey { get; private set; }
17 |
18 | ///
19 | /// The
20 | ///
21 | [JsonProperty("JobDataMap")]
22 | public JobDataMap JobDataMap { get; private set; }
23 | #endregion
24 |
25 | #region Constructor
26 | ///
27 | /// Makes this object and sets it's needed properties
28 | ///
29 | /// The
30 | /// The
31 | public JobKeyWithDataMap(JobKey jobKey, JobDataMap jobDataMap)
32 | {
33 | JobKey = jobKey;
34 | JobDataMap = jobDataMap;
35 | }
36 |
37 | ///
38 | /// Makes this object and sets it's needed properties
39 | ///
40 | public JobKeyWithDataMap()
41 | {
42 | }
43 | #endregion
44 |
45 | #region ToJsonString
46 | ///
47 | /// Returns this object as a json string
48 | ///
49 | ///
50 | public string ToJsonString()
51 | {
52 | return JsonConvert.SerializeObject(this, Formatting.Indented);
53 | }
54 | #endregion
55 |
56 | #region FromJsonString
57 | ///
58 | /// Returns the object from the given string
59 | ///
60 | /// The json string
61 | ///
62 | ///
63 | ///
64 | public static JobKeyWithDataMap FromJsonString(string json)
65 | {
66 | return JsonConvert.DeserializeObject(json);
67 | }
68 | #endregion
69 | }
--------------------------------------------------------------------------------
/QuartzWebApi/Wrappers/JobKeys.cs:
--------------------------------------------------------------------------------
1 | //
2 | // JobKeys.cs
3 | //
4 | // Author: Kees van Spelde
5 | //
6 | // Copyright (c) 2022 - 2024 Magic-Sessions. (www.magic-sessions.com)
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | using System.Collections.Generic;
27 | using System.Collections.ObjectModel;
28 | using System.Linq;
29 | using Newtonsoft.Json;
30 |
31 | namespace QuartzWebApi.Wrappers;
32 |
33 | ///
34 | /// A list of s
35 | ///
36 | [JsonArray]
37 | public class JobKeys : List
38 | {
39 | #region Constructor
40 | ///
41 | /// Makes this object and sets all it's needed properties
42 | ///
43 | /// A of s
44 | public JobKeys(IEnumerable jobKeys)
45 | {
46 | foreach (var jobKey in jobKeys)
47 | Add(new JobKey(jobKey.Name, jobKey.Group));
48 | }
49 | #endregion
50 |
51 | #region ToJobKeys
52 | ///
53 | /// Returns a of s
54 | ///
55 | ///
56 | public IReadOnlyCollection ToJobKeys()
57 | {
58 | var result = this.Select(m => m.ToJobKey()).ToList();
59 | return new ReadOnlyCollection(result);
60 | }
61 | #endregion
62 |
63 | #region ToJsonString
64 | ///
65 | /// Returns this object as a json string
66 | ///
67 | ///
68 | public string ToJsonString()
69 | {
70 | return JsonConvert.SerializeObject(this, Formatting.Indented);
71 | }
72 | #endregion
73 |
74 | #region FromJsonString
75 | ///
76 | /// Returns the object from the given string
77 | ///
78 | /// The json string
79 | ///
80 | ///
81 | ///
82 | public static JobKeys FromJsonString(string json)
83 | {
84 | return JsonConvert.DeserializeObject(json);
85 | }
86 | #endregion
87 | }
--------------------------------------------------------------------------------
/QuartzWebApi/Wrappers/Key.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Key.cs
3 | //
4 | // Author: Kees van Spelde
5 | //
6 | // Copyright (c) 2022 - 2024 Magic-Sessions. (www.magic-sessions.com)
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | using Newtonsoft.Json;
27 |
28 | namespace QuartzWebApi.Wrappers;
29 |
30 | ///
31 | /// A json wrapper for the or
32 | ///
33 | public class Key
34 | {
35 | #region Fields
36 | ///
37 | /// Returns the name of the trigger
38 | ///
39 | [JsonProperty("Name")]
40 | public string Name { get; internal set; }
41 |
42 | ///
43 | /// Returns the group of the trigger
44 | ///
45 | [JsonProperty("Group")]
46 | public string Group { get; internal set; }
47 | #endregion
48 |
49 | #region Constructor
50 | ///
51 | /// Makes this object and sets it's needed properties
52 | ///
53 | /// The name
54 | public Key(string name)
55 | {
56 | Name = name;
57 | }
58 |
59 | ///
60 | /// Makes this object and sets it's needed properties
61 | ///
62 | /// The name
63 | /// The group
64 | public Key(string name, string group)
65 | {
66 | Name = name;
67 | Group = group;
68 | }
69 | #endregion
70 | }
--------------------------------------------------------------------------------
/QuartzWebApi/Wrappers/RescheduleJob.cs:
--------------------------------------------------------------------------------
1 | //
2 | // RescheduleJob.cs
3 | //
4 | // Author: Kees van Spelde
5 | //
6 | // Copyright (c) 2022 - 2024 Magic-Sessions. (www.magic-sessions.com)
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 | //
26 |
27 | using Newtonsoft.Json;
28 |
29 | namespace QuartzWebApi.Wrappers;
30 |
31 | ///
32 | /// Class used to read or create json to reschedule a job
33 | ///
34 | public class RescheduleJob
35 | {
36 | #region Properties
37 | ///
38 | /// The current trigger key
39 | ///
40 | [JsonProperty("CurrentTriggerKey")]
41 | public TriggerKey CurrentTriggerKey { get; private set; }
42 |
43 | ///
44 | /// The new trigger
45 | ///
46 | [JsonProperty("NewTrigger")]
47 | public Trigger Trigger { get; private set; }
48 | #endregion
49 |
50 | #region ToJsonString
51 | ///
52 | /// Returns this object as a json string
53 | ///
54 | ///
55 | public string ToJsonString()
56 | {
57 | return JsonConvert.SerializeObject(this, Formatting.Indented);
58 | }
59 | #endregion
60 |
61 | #region FromJsonString
62 | ///
63 | /// Returns the object from the given string
64 | ///
65 | /// The json string
66 | ///
67 | ///
68 | ///
69 | public static RescheduleJob FromJsonString(string json)
70 | {
71 | return JsonConvert.DeserializeObject(json);
72 | }
73 | #endregion
74 | }
--------------------------------------------------------------------------------
/QuartzWebApi/Wrappers/RunningJobs.cs:
--------------------------------------------------------------------------------
1 | //
2 | // RunningJobs.cs
3 | //
4 | // Author: Kees van Spelde
5 | //
6 | // Copyright (c) 2022 - 2024 Magic-Sessions. (www.magic-sessions.com)
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 | //
26 |
27 | namespace QuartzWebApi.Wrappers;
28 | //public class RunningJobs : IJobExecutionContext
29 | //{
30 | // public void Put(object key, object objectValue)
31 | // {
32 | // throw new NotImplementedException();
33 | // }
34 |
35 | // public object Get(object key)
36 | // {
37 | // throw new NotImplementedException();
38 | // }
39 |
40 | // public IScheduler Scheduler { get; }
41 | // public ITrigger Trigger { get; }
42 | // public ICalendar Calendar { get; }
43 | // public bool Recovering { get; }
44 | // public TriggerKey RecoveringTriggerKey { get; }
45 | // public int RefireCount { get; }
46 | // public JobDataMap MergedJobDataMap { get; }
47 | // public IJobDetail JobDetail { get; }
48 | // public IJob JobInstance { get; }
49 | // public DateTimeOffset FireTimeUtc { get; }
50 | // public DateTimeOffset? ScheduledFireTimeUtc { get; }
51 | // public DateTimeOffset? PreviousFireTimeUtc { get; }
52 | // public DateTimeOffset? NextFireTimeUtc { get; }
53 | // public string FireInstanceId { get; }
54 | // public object Result { get; set; }
55 | // public TimeSpan JobRunTime { get; }
56 | // public CancellationToken CancellationToken { get; }
57 | //}
--------------------------------------------------------------------------------
/QuartzWebApi/Wrappers/ScheduleJobs.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace QuartzWebApi.Wrappers;
4 |
5 | public class ScheduleJobs : List
6 | {
7 | }
--------------------------------------------------------------------------------
/QuartzWebApi/Wrappers/SchedulerContext.cs:
--------------------------------------------------------------------------------
1 | using System.Web;
2 | using Newtonsoft.Json;
3 |
4 | namespace QuartzWebApi.Wrappers;
5 |
6 | ///
7 | /// A json wrapper for the
8 | ///
9 | public sealed class SchedulerContext : Quartz.SchedulerContext
10 | {
11 | #region Constructor
12 | ///
13 | /// Needed for json de-serialization
14 | ///
15 | [JsonConstructor]
16 | internal SchedulerContext()
17 | {
18 |
19 | }
20 |
21 | internal SchedulerContext(Quartz.SchedulerContext schedulerContext)
22 | {
23 | foreach (var item in schedulerContext)
24 | Add(item.Key, item.Value);
25 | }
26 | #endregion
27 |
28 | #region ToJsonString
29 | ///
30 | /// Returns this object as a json string
31 | ///
32 | ///
33 | public string ToJsonString()
34 | {
35 | return JsonConvert.SerializeObject(this, Formatting.Indented);
36 | }
37 | #endregion
38 |
39 | #region FromJsonString
40 | ///
41 | /// Returns the object from the given string
42 | ///
43 | /// The json string
44 | ///
45 | ///
46 | ///
47 | public static SchedulerContext FromJsonString(string json)
48 | {
49 | var str = JsonConvert.DeserializeObject(json);
50 | var result = JsonConvert.DeserializeObject(str);
51 | return new SchedulerContext(result);
52 | }
53 | #endregion
54 | }
--------------------------------------------------------------------------------
/QuartzWebApi/Wrappers/SchedulerMetaData.cs:
--------------------------------------------------------------------------------
1 | //
2 | // SchedulerMetaData.cs
3 | //
4 | // Author: Kees van Spelde
5 | //
6 | // Copyright (c) 2022 - 2024 Magic-Sessions. (www.magic-sessions.com)
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 | //
26 |
27 | using System;
28 | using Newtonsoft.Json;
29 |
30 | namespace QuartzWebApi.Wrappers;
31 |
32 | ///
33 | /// Class used to read or create json to get the schedulers meta-data
34 | ///
35 | public class SchedulerMetaData
36 | {
37 | #region Properties
38 | ///
39 | /// Returns true when in standby mode
40 | ///
41 | [JsonProperty("InStandbyMode")]
42 | public bool InStandbyMode { get; private set; }
43 |
44 | ///
45 | /// Returns the job store type
46 | ///
47 | [JsonProperty("JobStoreType")]
48 | public Type JobStoreType { get; private set; }
49 |
50 | ///
51 | /// Returns true when the job store is clustered
52 | ///
53 | [JsonProperty("JobStoreClustered")]
54 | public bool JobStoreClustered { get; private set; }
55 |
56 | ///
57 | /// Returns true when the job store supports persistence
58 | ///
59 | [JsonProperty("JobsStoreSupportsPersistence")]
60 | public bool JobStoreSupportsPersistence { get; private set; }
61 |
62 | ///
63 | /// Returns the numbers of jobs executed
64 | ///
65 | [JsonProperty("NumbersOfJobsExecuted")]
66 | public int NumbersOfJobsExecuted { get; private set; }
67 |
68 | ///
69 | /// Returns the date time since the scheduler is running
70 | ///
71 | [JsonProperty("RunningSince")]
72 | public DateTimeOffset? RunningSince { get; private set; }
73 |
74 | ///
75 | /// Returns the scheduler instance id
76 | ///
77 | [JsonProperty("SchedulerInstanceId")]
78 | public string SchedulerInstanceId { get; private set; }
79 |
80 | ///
81 | /// Returns the scheduler name
82 | ///
83 | [JsonProperty("SchedulerName")]
84 | public string SchedulerName { get; private set; }
85 |
86 | ///
87 | /// Returns true when the scheduler is remote
88 | ///
89 | [JsonProperty("SchedulerRemote")]
90 | public bool SchedulerRemote { get; private set; }
91 |
92 | ///
93 | /// Returns the scheduler type
94 | ///
95 | [JsonProperty("SchedulerType")]
96 | public Type SchedulerType { get; private set; }
97 |
98 | ///
99 | /// Returns true when the scheduler is shutdown
100 | ///
101 | [JsonProperty("Shutdown")]
102 | public bool Shutdown { get; private set; }
103 |
104 | ///
105 | /// Returns true when the scheduler is started
106 | ///
107 | [JsonProperty("Started")]
108 | public bool Started { get; private set; }
109 |
110 | ///
111 | /// Returns the thread pool size
112 | ///
113 | [JsonProperty("ThreadPoolSize")]
114 | public int ThreadPoolSize { get; private set; }
115 |
116 | ///
117 | /// Returns the thread pool type
118 | ///
119 | [JsonProperty("ThreadPoolType")]
120 | public Type ThreadPoolType { get; private set; }
121 |
122 | ///
123 | /// Returns the scheduler version
124 | ///
125 | [JsonProperty("Version")]
126 | public string Version { get; private set; }
127 |
128 | [JsonProperty("Summary")]
129 | public string Summary { get; private set; }
130 | #endregion
131 |
132 | #region Constructor
133 | ///
134 | /// Needed for json de-serialization
135 | ///
136 | [JsonConstructor]
137 | internal SchedulerMetaData()
138 | {
139 | }
140 |
141 | ///
142 | /// Creates this object and sets all it's needed properties
143 | ///
144 | ///
145 | public SchedulerMetaData(Quartz.SchedulerMetaData metaData)
146 | {
147 | InStandbyMode = metaData.InStandbyMode;
148 | JobStoreType = metaData.JobStoreType;
149 | JobStoreClustered = metaData.JobStoreClustered;
150 | JobStoreSupportsPersistence = metaData.JobStoreSupportsPersistence;
151 | NumbersOfJobsExecuted = metaData.NumberOfJobsExecuted;
152 | RunningSince = metaData.RunningSince;
153 | SchedulerInstanceId = metaData.SchedulerInstanceId;
154 | SchedulerName = metaData.SchedulerName;
155 | SchedulerRemote = metaData.SchedulerRemote;
156 | SchedulerType = metaData.SchedulerType;
157 | Shutdown = metaData.Shutdown;
158 | Started = metaData.Started;
159 | ThreadPoolSize = metaData.ThreadPoolSize;
160 | ThreadPoolType = metaData.ThreadPoolType;
161 | Version = metaData.Version;
162 | Summary = metaData.GetSummary();
163 | }
164 | #endregion
165 |
166 | #region ToJsonString
167 | ///
168 | /// Returns this object as a json string
169 | ///
170 | ///
171 | public string ToJsonString()
172 | {
173 | return JsonConvert.SerializeObject(this, Formatting.Indented);
174 | }
175 | #endregion
176 |
177 | #region FromJsonString
178 | ///
179 | /// Returns the object from the given string
180 | ///
181 | /// The json string
182 | ///
183 | ///
184 | ///
185 | public static SchedulerMetaData FromJsonString(string json)
186 | {
187 | var str = JsonConvert.DeserializeObject(json);
188 | return JsonConvert.DeserializeObject(str);
189 | }
190 | #endregion
191 | }
--------------------------------------------------------------------------------
/QuartzWebApi/Wrappers/Trigger.cs:
--------------------------------------------------------------------------------
1 | //
2 | // Trigger.cs
3 | //
4 | // Author: Kees van Spelde
5 | //
6 | // Copyright (c) 2022 - 2024 Magic-Sessions. (www.magic-sessions.com)
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 | //
26 |
27 | using System;
28 | using Newtonsoft.Json;
29 | using Quartz;
30 |
31 | namespace QuartzWebApi.Wrappers;
32 |
33 | ///
34 | /// Class used to create or read json to get a trigger with a job key and data map
35 | ///
36 | public class Trigger : JobKeyWithDataMap
37 | {
38 | #region Properties
39 | ///
40 | /// The
41 | ///
42 | [JsonProperty("TriggerKey")]
43 | public TriggerKey TriggerKey { get; private set; }
44 |
45 | ///
46 | /// A description for the
47 | ///
48 | [JsonProperty("Description")]
49 | public string Description { get; private set; }
50 |
51 | ///
52 | /// The name of the calendar to use or null when not
53 | ///
54 | [JsonProperty("CalendarName")]
55 | public string CalendarName { get; private set; }
56 |
57 | ///
58 | /// The cron schedule
59 | ///
60 | [JsonProperty("CronSchedule")]
61 | public string CronSchedule { get; private set; }
62 |
63 | ///
64 | /// The next fire time in UTC format
65 | ///
66 | [JsonProperty("NextFireTimeUtc")]
67 | public DateTimeOffset? NextFireTimeUtc { get; private set; }
68 |
69 | ///
70 | /// The previous fire time in UTC format
71 | ///
72 | [JsonProperty("PreviousFireTimeUtc")]
73 | public DateTimeOffset? PreviousFireTimeUtc { get; private set; }
74 |
75 | ///
76 | /// The start time in UTC format
77 | ///
78 | [JsonProperty("StartTimeUtc")]
79 | public DateTimeOffset StartTimeUtc { get; private set; }
80 |
81 | ///
82 | /// The end time in UTC format
83 | ///
84 | [JsonProperty("EndTimeUtc")]
85 | public DateTimeOffset? EndTimeUtc { get; private set; }
86 |
87 | ///
88 | /// The final fire time in UTC format
89 | ///
90 | [JsonProperty("FinalFireTimeUtc")]
91 | public DateTimeOffset? FinalFireTimeUtc { get; private set; }
92 |
93 | ///
94 | /// The priority
95 | ///
96 | [JsonProperty("Priority")]
97 | public int Priority { get; private set; }
98 |
99 | ///
100 | /// Returns true when it has millisecond precision
101 | ///
102 | [JsonProperty("HasMillisecondPrecision")]
103 | public bool HasMillisecondPrecision { get; private set; }
104 | #endregion
105 |
106 | #region Constructor
107 | ///
108 | /// Makes this object and sets all it's needed properties
109 | ///
110 | /// The
111 | /// A description for the
112 | /// The name of the calendar to use or null when not
113 | /// The cron schedule
114 | /// The next fire time in UTC format
115 | /// The previous fire time in UTC format
116 | /// The start time in UTC format
117 | /// The end time in UTC format
118 | /// The final fire time in UTC format
119 | /// The priority
120 | /// The
121 | /// The
122 | public Trigger(
123 | TriggerKey triggerKey,
124 | string description,
125 | string calendarName,
126 | string cronSchedule,
127 | DateTimeOffset? nextFireTimeUtc,
128 | DateTimeOffset? previousFireTimeUtc,
129 | DateTimeOffset startTimeUtc,
130 | DateTimeOffset? endTimeUtc,
131 | DateTimeOffset? finalFireTimeUtc,
132 | int priority,
133 | JobKey jobKey,
134 | JobDataMap jobDataMap) : base(jobKey, jobDataMap)
135 | {
136 | TriggerKey = triggerKey;
137 | Description = description;
138 | CalendarName = calendarName;
139 | CronSchedule = cronSchedule;
140 | NextFireTimeUtc = nextFireTimeUtc;
141 | PreviousFireTimeUtc = previousFireTimeUtc;
142 | StartTimeUtc = startTimeUtc;
143 | EndTimeUtc = endTimeUtc;
144 | FinalFireTimeUtc = finalFireTimeUtc;
145 | Priority = priority;
146 | }
147 |
148 | ///
149 | /// Makes this object and sets all it's needed properties
150 | ///
151 | ///
152 | public Trigger(ITrigger trigger)
153 | {
154 | TriggerKey = new TriggerKey(trigger.Key);
155 | Description = trigger.Description;
156 | CalendarName = trigger.CalendarName;
157 | //CronSchedule = trigger;
158 | NextFireTimeUtc = trigger.GetNextFireTimeUtc();
159 | PreviousFireTimeUtc = trigger.GetPreviousFireTimeUtc();
160 | StartTimeUtc = trigger.StartTimeUtc;
161 | EndTimeUtc = trigger.EndTimeUtc;
162 | FinalFireTimeUtc = trigger.FinalFireTimeUtc;
163 | Priority = trigger.Priority;
164 | HasMillisecondPrecision = trigger.HasMillisecondPrecision;
165 | }
166 | #endregion
167 |
168 | #region ToTrigger
169 | ///
170 | /// Returns this object as a Quartz
171 | ///
172 | ///
173 | public ITrigger ToTrigger()
174 | {
175 | var trigger = TriggerBuilder
176 | .Create()
177 | .ForJob(JobKey.ToJobKey())
178 | .WithIdentity(TriggerKey.ToTriggerKey())
179 | .WithPriority(Priority)
180 | .StartAt(StartTimeUtc);
181 |
182 | if (EndTimeUtc.HasValue)
183 | trigger = trigger.EndAt(EndTimeUtc.Value);
184 |
185 | if (!string.IsNullOrWhiteSpace(CronSchedule))
186 | trigger = trigger.WithCronSchedule(CronSchedule);
187 |
188 | if (!string.IsNullOrWhiteSpace(CalendarName))
189 | trigger = trigger.ModifiedByCalendar(CalendarName);
190 |
191 | if (!string.IsNullOrWhiteSpace(Description))
192 | trigger = trigger.WithDescription(Description);
193 |
194 | if (JobDataMap != null)
195 | trigger = trigger.UsingJobData(JobDataMap);
196 |
197 | return trigger.Build();
198 | }
199 | #endregion
200 |
201 | #region ToJsonString
202 | ///
203 | /// Returns this object as a json string
204 | ///
205 | ///
206 | public new string ToJsonString()
207 | {
208 | return JsonConvert.SerializeObject(this, Formatting.Indented);
209 | }
210 | #endregion
211 |
212 | #region FromJsonString
213 | ///
214 | /// Returns the object from the given string
215 | ///
216 | /// The json string
217 | ///
218 | ///
219 | ///
220 | public new static Trigger FromJsonString(string json)
221 | {
222 | return JsonConvert.DeserializeObject(json);
223 | }
224 | #endregion
225 | }
--------------------------------------------------------------------------------
/QuartzWebApi/Wrappers/TriggerKey.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 |
3 | namespace QuartzWebApi.Wrappers;
4 |
5 | ///
6 | /// A json wrapper for the
7 | ///
8 | public class TriggerKey : Key
9 | {
10 | #region Constructor
11 | ///
12 | /// Makes this object and sets it's needed properties
13 | ///
14 | /// The name of the trigger
15 | [JsonConstructor]
16 | public TriggerKey(string name) : base(name)
17 | {
18 | }
19 |
20 | ///
21 | /// Makes this object and sets it's needed properties
22 | ///
23 | /// The name of the trigger
24 | /// The group of the trigger
25 | public TriggerKey(string name, string group) : base(name, group)
26 | {
27 | }
28 |
29 | ///
30 | /// Makes this object and sets it's needed properties
31 | ///
32 | /// The
33 | public TriggerKey(Quartz.TriggerKey key) : base(key.Name, key.Group)
34 | {
35 | }
36 | #endregion
37 |
38 | #region ToTriggerKey
39 | ///
40 | /// Returns this object as a Quartz
41 | ///
42 | ///
43 | public Quartz.TriggerKey ToTriggerKey()
44 | {
45 | return new Quartz.TriggerKey(Name, Group);
46 | }
47 | #endregion
48 |
49 | #region ToJsonString
50 | ///
51 | /// Returns this object as a json string
52 | ///
53 | ///
54 | public string ToJsonString()
55 | {
56 | return JsonConvert.SerializeObject(this, Formatting.Indented);
57 | }
58 | #endregion
59 |
60 | #region FromJsonString
61 | ///
62 | /// Returns the object from the given string
63 | ///
64 | /// The json string
65 | ///
66 | ///
67 | ///
68 | public static TriggerKey FromJsonString(string json)
69 | {
70 | return JsonConvert.DeserializeObject(json);
71 | }
72 | #endregion
73 | }
--------------------------------------------------------------------------------
/QuartzWebApi/Wrappers/TriggerKeys.cs:
--------------------------------------------------------------------------------
1 | //
2 | // TriggerKeys.cs
3 | //
4 | // Author: Kees van Spelde
5 | //
6 | // Copyright (c) 2022 - 2024 Magic-Sessions. (www.magic-sessions.com)
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in
16 | // all copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 | // THE SOFTWARE.
25 |
26 | using System.Collections.Generic;
27 | using System.Collections.ObjectModel;
28 | using System.Linq;
29 | using Newtonsoft.Json;
30 |
31 | namespace QuartzWebApi.Wrappers;
32 |
33 | [JsonArray]
34 | public class TriggerKeys : List
35 | {
36 | #region Constructor
37 | ///
38 | /// Makes this object and sets all it's needed properties
39 | ///
40 | /// A of s
41 | public TriggerKeys(IEnumerable triggerKeys)
42 | {
43 | foreach (var triggerKey in triggerKeys)
44 | Add(new TriggerKey(triggerKey.Name, triggerKey.Group));
45 | }
46 | #endregion
47 |
48 | #region ToTriggerKeys
49 | ///
50 | /// Returns a of s
51 | ///
52 | ///
53 | public IReadOnlyCollection ToTriggerKeys()
54 | {
55 | var result = this.Select(m => m.ToTriggerKey()).ToList();
56 | return new ReadOnlyCollection(result);
57 | }
58 | #endregion
59 |
60 | #region ToJsonString
61 | ///
62 | /// Returns this object as a json string
63 | ///
64 | ///
65 | public string ToJsonString()
66 | {
67 | return JsonConvert.SerializeObject(this, Formatting.Indented);
68 | }
69 | #endregion
70 |
71 | #region FromJsonString
72 | ///
73 | /// Returns the object from the given string
74 | ///
75 | /// The json string
76 | ///
77 | ///
78 | ///
79 | public static TriggerKeys FromJsonString(string json)
80 | {
81 | return JsonConvert.DeserializeObject(json);
82 | }
83 | #endregion
84 | }
--------------------------------------------------------------------------------
/QuartzWebApi/Wrappers/Triggers.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Collections.ObjectModel;
3 | using Newtonsoft.Json;
4 | using Quartz;
5 |
6 | namespace QuartzWebApi.Wrappers;
7 |
8 | ///
9 | /// A list of s
10 | ///
11 | [JsonArray]
12 | public class Triggers : List
13 | {
14 | #region Constructor
15 | ///
16 | /// Makes this object and sets all it's needed properties
17 | ///
18 | /// A of s
19 | public Triggers(IEnumerable triggers)
20 | {
21 | foreach (var trigger in triggers)
22 | Add(new Trigger(trigger));
23 | }
24 | #endregion
25 |
26 | #region ToJsonString
27 | ///
28 | /// Returns this object as a json string
29 | ///
30 | ///
31 | public string ToJsonString()
32 | {
33 | return JsonConvert.SerializeObject(this, Formatting.Indented);
34 | }
35 | #endregion
36 |
37 | #region FromJsonString
38 | ///
39 | /// Returns the object from the given string
40 | ///
41 | /// The json string
42 | ///
43 | ///
44 | ///
45 | public static Triggers FromJsonString(string json)
46 | {
47 | return JsonConvert.DeserializeObject(json);
48 | }
49 | #endregion
50 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # QuartzWebApi
2 | A self hosted Web API for Quartz.Net, hosting on .net 4.8 is done with OWIN and on .net6 and higher with Kestrel
3 |
4 | ## Installing via NuGet (not yet done)
5 |
6 | [](https://www.nuget.org/packages/QuartzWebApi)
7 |
8 | # How to host Quartz.Net
9 |
10 | ```c#
11 | var host = new SchedulerHost("http://localhost:44344", , );
12 | host.Start();
13 | ```
14 |
15 | Where `IScheduler` is your Quartz.Net scheduler and `ILogger` any logger that implements the Microsoft ILogger interface (or null if you don't want any logging)
16 |
17 | # How to connect to the host
18 |
19 | ```c#
20 | var connector = new SchedulerConnector("http://localhost:44344");
21 | ```
22 |
23 | ## License Information
24 |
25 | QuartzWebApi is Copyright (C) 2022 - 2024 Magic-Sessions and is licensed under the MIT license:
26 |
27 | Permission is hereby granted, free of charge, to any person obtaining a copy
28 | of this software and associated documentation files (the "Software"), to deal
29 | in the Software without restriction, including without limitation the rights
30 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
31 | copies of the Software, and to permit persons to whom the Software is
32 | furnished to do so, subject to the following conditions:
33 |
34 | The above copyright notice and this permission notice shall be included in
35 | all copies or substantial portions of the Software.
36 |
37 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
38 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
39 | FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE
40 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
41 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
42 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
43 | THE SOFTWARE.
44 |
45 | Core Team
46 | =========
47 | Sicos1977 (Kees van Spelde)
48 |
49 | Logging
50 | =======
51 |
52 | QuartzWebApi uses the Microsoft ILogger interface (https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.logging.ilogger?view=dotnet-plat-ext-5.0). You can use any logging library that uses this interface.
53 |
54 | QuartzWebApi has some build in loggers that can be found in the ```QuartzWebApi.Logger``` namespace.
55 |
56 | For example
57 |
58 | ```csharp
59 | var logger = !string.IsNullOrWhiteSpace()
60 | ? new ChromeHtmlToPdfLib.Loggers.Stream(File.OpenWrite())
61 | : new ChromeHtmlToPdfLib.Loggers.Console();
62 | ```
63 |
64 | Most of the log informartion is logged at the `information` level, small answers like `booleans`, `DateTimeOffsets` and small `strings` (like the schedulers name) are also logged at this level. All the json that is received and sent back is logged at the `debug` level.
65 |
66 | How to use the API directly
67 | ==========
68 |
69 | ### Check if a job group is paused
70 |
71 | Do a `POST` request to `Scheduler/IsJobGroupPaused/{groupName}`, where `{groupName}` is the name of the group this will return `true` or `false`
72 |
73 | ### Check if a trigger group is paused
74 |
75 | Do a `POST` request to `Scheduler/IsTriggerGroupPaused/{groupName}`, where `{groupName}` is the name of the group this will return `true` or `false`
76 |
77 | ### Get the schedulers name
78 |
79 | Do a `GET` request to `Scheduler/SchedulerName`, this will return the name of the scheduler
80 |
81 | ### Get the schedulers instance id
82 |
83 | Do a `GET` request to `Scheduler/SchedulerInstanceId`, this will return the schedulers instance id
84 |
85 | ### Get the schedulers context
86 |
87 | Do a `GET` request to `Scheduler/SchedulerContext`
88 |
89 | When the context is;
90 |
91 | - key1 - value1
92 | - key2 - value2
93 | - key3 - value3
94 |
95 | it will return
96 |
97 | ```json
98 | {
99 | "key1": "value1",
100 | "key2": "value2",
101 | "key3": "value3"
102 | }
103 | ```
104 |
105 | ### Check if a scheduler is in standby mode
106 |
107 | Do a `GET` request to `Scheduler/InStandbyMode` , this will return `true` or `false`
108 |
109 | ### Check if a scheduler is in shutdown
110 |
111 | Do a `GET` request to `Scheduler/Isshutdown` , this will return `true` or `false`
112 |
113 | ### Get the schedulers meta-data
114 |
115 | Do a `GET` request to `Scheduler/GetMetaData` , this will return the meta-data that will look something like this
116 |
117 | ```json
118 | {
119 | "InStandbyMode": false,
120 | "JobStoreType": "Quartz.Simpl.RAMJobStore, Quartz, Version=3.4.0.0, Culture=neutral, PublicKeyToken=f6b8c98a402cc8a4",
121 | "JobStoreClustered": false,
122 | "JobsStoreSupportsPersistence": false,
123 | "NumbersOfJobsExecuted": 0,
124 | "RunningSince": "2022-05-11T16:30:06.5957565+00:00",
125 | "SchedulerInstanceId": "NON_CLUSTERED",
126 | "SchedulerName": "The name of the scheduler",
127 | "SchedulerRemote": false,
128 | "SchedulerType": "Quartz.Impl.StdScheduler, Quartz, Version=3.4.0.0, Culture=neutral, PublicKeyToken=f6b8c98a402cc8a4",
129 | "Shutdown": false,
130 | "Started": true,
131 | "ThreadPoolSize": 10,
132 | "ThreadPoolType": "Quartz.Simpl.DefaultThreadPool, Quartz, Version=3.4.0.0, Culture=neutral, PublicKeyToken=f6b8c98a402cc8a4",
133 | "Version": "3.4.0.0"
134 | }
135 | ```
136 |
137 | ### Get the currently executing jobs
138 |
139 | Do a `GET` request to `Scheduler/GetCurrentlyExecutingJobs` , this will return the currently executing jobs that will look like this
140 |
141 | ```json
142 | [
143 | "JobGroup1",
144 | "JobGroup2"
145 | ]
146 | ```
147 |
148 | ### Get the job group names
149 |
150 | Do a `GET` request to `Scheduler/GetJobGroupNames` , this will return the job group names that will look like this
151 |
152 | ```json
153 | [
154 | "JobGroup1",
155 | "JobGroup2"
156 | ]
157 | ```
158 |
159 | ### Get the trigger group names
160 |
161 | Do a `GET` request to `Scheduler/GetTriggerGroupNames` , this will return
162 |
163 | ```json
164 | [
165 | "TriggerGroup1",
166 | "TriggerGroup2"
167 | ]
168 | ```
169 |
170 | ### Get the paused trigger groups
171 |
172 | Do a `GET` request to `Scheduler/GetPausedTriggerGroups` , this will return
173 |
174 | ```json
175 | [
176 | "PausedTriggerGroup1",
177 | "PausedTriggerGroup2"
178 | ]
179 | ```
180 |
181 | ### Start the scheduler
182 |
183 | Do a `POST` request to `Scheduler/Start`
184 |
185 | ### Start the scheduler with a delay
186 |
187 | Do a `POST` request to `Scheduler/StartDelayed/{delay}` where `{delay}` is the amount of *seconds* you want to delay the start
188 |
189 | ### Check if the scheduler is started
190 |
191 | Do a `GET` request to `Scheduler/IsStarted`, this will return `true` or `false`
192 |
193 | ### Check if the scheduler is in standby mode
194 |
195 | Do a `GET` request to `Scheduler/Standby`, this will return `true` or `false`
196 |
197 | ### Shutdown the scheduler
198 |
199 | Do a `POST` request to `Scheduler/Shutdown`
200 |
201 | ### Shutdown the scheduler but wait for all jobs to complete
202 |
203 | Do a `POST` request to `Scheduler/Shutdown/{waitForJobsToComplete}` where `{waitForJobsToComplete}` is `true`
204 |
205 | ### Schedule a job with a job detail and a trigger
206 |
207 | Do a `POST` request to `Scheduler/ScheduleJobWithJobDetailAndTrigger` with in the body the job detail and the trigger
208 |
209 | ```json
210 | {
211 | "JobDetail": {
212 | "JobKey": {
213 | "Name": "Name",
214 | "Group": "Group"
215 | },
216 | "Description": "description",
217 | "JobType": "jobType",
218 | "JobDataMap": {
219 | "key": "value"
220 | },
221 | "Durable": true,
222 | "Replace": false,
223 | "StoreNonDurableWhileAwaitingScheduling": false
224 | },
225 | "Trigger": {
226 | "TriggerKey": {
227 | "Name": "name",
228 | "Group": "group"
229 | },
230 | "Description": "description",
231 | "StartTimeUtc": "2022-08-15T17:34:04.5786231+00:00",
232 | "EndTimeUtc": "2022-08-15T17:34:04.5786231+00:00",
233 | "Priority": 5,
234 | "CronSchedule": "0 * * ? * *",
235 | "Priority": 5,
236 | "JobKey": {
237 | "Name": "name",
238 | "Group": "value"
239 | },
240 | "JobDataMap": {
241 | "key": "value"
242 | }
243 | }
244 | }
245 | ```
246 |
247 | ### Schedule the give trigger with the job identified by the trigger
248 |
249 | Do a `POST` request to `Scheduler/ScheduleJobIdentifiedWithTrigger` with in the body
250 |
251 | ```json
252 | {
253 | "TriggerKey": {
254 | "Name": "TriggerKeyName",
255 | "Group": "TriggerKeyGroup"
256 | },
257 | "JobKey": {
258 | "Name": "JobKeyName",
259 | "Group": "JobKeyGroup"
260 | },
261 | "Description": "Description",
262 | "CalendarName": "CalendarName",
263 | "JobDataMap": {
264 | "Key1": "Value1",
265 | "Key2": "Value2"
266 | },
267 | "StartTimeUtc": "2022-05-12T16:16:37.7210025+00:00",
268 | "EndTimeUtc": "2022-05-13T02:16:37.7210025+00:00",
269 | "FinalFireTimeUtc": "2022-05-13T22:16:37.7210025+00:00",
270 | "CronSchedule": "0 * * ? * *",
271 | "Priority": 5
272 | }
273 | ```
274 |
275 | This will return a datetime offset about when the job will be executed, for example `"2022-05-12T16:17:00+00:00"`
276 |
277 | ### Schedule multiple jobs with one or more associated trigger
278 |
279 | TODO: Task ScheduleJobs(IReadOnlyDictionary> triggersAndJobs, bool replace);
280 |
281 | ### Schedule a job with one or more associated trigger
282 |
283 | TODO: Task ScheduleJobs(IReadOnlyDictionary> triggersAndJobs, bool replace);
284 |
285 | ### Schedule a job with a job detail and a related set of triggers
286 |
287 | Do a `POST` request to `Scheduler/ScheduleJobWithJobDetailAndTriggers` with in the body the job detail and a related set of triggers
288 |
289 | ```json
290 | {
291 | "JobDetail": {
292 | "JobKey": {
293 | "Name": "Name",
294 | "Group": "Group"
295 | },
296 | "Description": "description",
297 | "JobType": "jobType",
298 | "JobDataMap": {
299 | "key": "value"
300 | },
301 | "Durable": true,
302 | "Replace": false,
303 | "StoreNonDurableWhileAwaitingScheduling": false
304 | },
305 | "Triggers": [
306 | {
307 | "TriggerKey": {
308 | "Name": "name",
309 | "Group": "group"
310 | },
311 | "Description": "description",
312 | "CalendarName": "calenderName",
313 | "CronSchedule": "0 * * ? * *",
314 | "Priority": 5,
315 | "JobKey": {
316 | "Name": "name",
317 | "Group": "value"
318 | },
319 | "JobDataMap": {
320 | "key": "value"
321 | }
322 | }
323 | ],
324 | "Replace": false
325 | }
326 | ```
327 |
328 | When you get an error like `Could not find an IJob class with the type ''` then make sure that you have added the full namespace with the `JobType`
329 |
330 | ### Unschedule a job
331 |
332 | Do a `POST` request to `Scheduler/UnscheduleJob` with in the body the trigger of the job
333 |
334 | ```json
335 | {
336 | "Name": "TriggerKeyName",
337 | "Group": "TriggerKeyGroup"
338 | }
339 | ```
340 |
341 | this will return `true` when the job is unscheduled or `false` when not
342 |
343 | ### Unschedule multiple jobs
344 |
345 | Do a `POST` request to `Scheduler/UnscheduleJobs` with in the body the triggers of the jobs to unschedule
346 |
347 | ```json
348 | [
349 | {
350 | "Name": "TriggerKeyName1",
351 | "Group": "TriggerKeyGroup1"
352 | },
353 | {
354 | "Name": "TriggerKeyName2",
355 | "Group": "TriggerKeyGroup2"
356 | }
357 | ]
358 | ```
359 |
360 | this will return `true` when the jobs are unscheduled or `false` when not
361 |
362 | ### Reschedule job
363 |
364 | Do a `POST` request to `Scheduler/RescheduleJob` with in the body the reschedulejob object
365 |
366 | ```json
367 | {
368 | "CurrentTriggerKey": {
369 | "Name": "CurrentTriggerKeyName",
370 | "Group": "CurrentTriggerKeyGroup"
371 | },
372 | "NewTrigger": {
373 | "TriggerKey": {
374 | "Name": "NewTriggerKeyName",
375 | "Group": "NewTriggerKeyGroup"
376 | },
377 | "JobKey": {
378 | "Name": "NewJobKeyName",
379 | "Group": "NewJobKeyGroup"
380 | },
381 | "Description": "Description",
382 | "CalendarName": "CalendarName",
383 | "JobDataMap": {
384 | "Key1": "Value1",
385 | "Key2": "Value2"
386 | },
387 | "StartTimeUtc": "2022-05-12T16:16:37.7210025+00:00",
388 | "EndTimeUtc": "2022-05-13T02:16:37.7210025+00:00",
389 | "FinalFireTimeUtc": "2022-05-13T22:16:37.7210025+00:00",
390 | "CronSchedule": "0 * * ? * *",
391 | "Priority": 5
392 | }
393 | }
394 | ```
395 |
396 | Returns 'null' if a trigger with the given name and group was not found and removed from the store (and the new trigger is therefore not stored), otherwise the first fire time of the newly scheduled trigger
397 |
398 | ### Add a job with no associated trigger
399 |
400 | Do a `POST` request to `Scheduler/AddJob` with in the body the addjob object
401 |
402 | ```json
403 | {
404 | "JobKey": {
405 | "Name": "JobKeyName",
406 | "Group": "JobKeyGroup"
407 | },
408 | "Description": "Description",
409 | "JobType": "JobType",
410 | "JobDataMap": {
411 | "Key1": "Value1",
412 | "Key2": "Value2"
413 | },
414 | "Durable": true,
415 | "Replace": false,
416 | "StoreNonDurableWhileAwaitingScheduling": true
417 | }
418 | ```
419 |
420 | ### Delete a job
421 |
422 | Do a `POST` request to `Scheduler/DeleteJob` with in the body the key of the job
423 |
424 | ```json
425 | {
426 | "Name": "JobKeyName",
427 | "Group": "JobKeyGroup"
428 | }
429 | ```
430 |
431 | this will return `true` when the job is deleted or `false` when not
432 |
433 | ### Delete multiple jobs
434 |
435 | Do a `DELETE` request to `Scheduler/DeleteJobs` with in the body the keys of the jobs
436 |
437 | ```json
438 | [
439 | {
440 | "Name": "JobKeyName1",
441 | "Group": "JobKeyGroup1"
442 | },
443 | {
444 | "Name": "JobKeyName2",
445 | "Group": "JobKeyGroup2"
446 | }
447 | ]
448 | ```
449 |
450 | ### Trigger a job to execute NOW
451 |
452 | Do a `POST` request to `Scheduler/TriggerJobWithJobkey` with in the body the key of the job
453 |
454 | ```json
455 | {
456 | "Name": "JobKeyName1",
457 | "Group": "JobKeyGroup1"
458 | }
459 | ```
460 |
461 | ### Trigger a job to execute NOW and associated a JobDataMap
462 |
463 | Do a `POST` request to `Scheduler/TriggerJobWithDataMap` with in the body
464 |
465 | ```json
466 | {
467 | "JobKey": {
468 | "Name": "JobKeyName",
469 | "Group": "JobKeyGroup"
470 | },
471 | "JobDataMap": {
472 | "Key1": "Value1",
473 | "Key2": "Value2"
474 | }
475 | }
476 | ```
477 |
478 | ### Pause a job
479 |
480 | Do a `POST` request to `Scheduler/PauseJob` with in the body the key of the job
481 |
482 | ```json
483 | {
484 | "Name": "JobKeyName",
485 | "Group": "JobKeyGroup"
486 | }
487 | ```
488 |
489 | ### Pause multiple jobs
490 |
491 | Do a `POST` request to `Scheduler/PauseJobs` with in the body the group matching object that defined what jobs to pause
492 |
493 | The values for `Type` can be: `Contains`, `EndsWith`, `Equals` or `StartsWith`
494 |
495 | ```json
496 | {
497 | "Type": "Contains",
498 | "Value": ""
499 | }
500 | ```
501 |
502 | ### Pause a trigger
503 |
504 | Do a `POST` request to `Scheduler/PauseTrigger` with in the body the triggerkey
505 |
506 | ```json
507 | {
508 | "Name": "TriggerKeyName",
509 | "Group": "TriggerKeyGroup"
510 | }
511 | ```
512 |
513 | ### Pause multiple triggers
514 |
515 | Do a `POST` request to `Scheduler/PauseTriggers` with in the body the group matching object that defined what triggers to pause
516 |
517 | The values for `Type` can be: `Contains`, `EndsWith`, `Equals` or `StartsWith`
518 |
519 | ```json
520 | {
521 | "Type": "Contains",
522 | "Value": ""
523 | }
524 | ```
525 |
526 | ### Resume a job
527 |
528 | Do a `POST` request to `Scheduler/ResumeJob` with in the body the key of the job
529 |
530 | ```json
531 | {
532 | "Name": "JobKeyName",
533 | "Group": "JobKeyGroup"
534 | }
535 | ```
536 |
537 | ### Resume multiple jobs
538 |
539 | Do a `POST` request to `Scheduler/ResumeJobs` with in the body the group matching object that defined what jobs to resume
540 |
541 | The values for `Type` can be: `Contains`, `EndsWith`, `Equals` or `StartsWith`
542 |
543 | ```json
544 | {
545 | "Type": "Contains",
546 | "Value": ""
547 | }
548 | ```
549 |
550 | ### Resume a trigger
551 |
552 | Do a `POST` request to `Scheduler/ResumeTrigger` with in the body the key of the trigger
553 |
554 | ```json
555 | {
556 | "Name": "TriggerKeyName",
557 | "Group": "TriggerKeyGroup"
558 | }
559 | ```
560 |
561 | ### Resume multiple triggers
562 |
563 | Do a `POST` request to `Scheduler/ResumeTriggers` with in the body the group matching object that defined what triggers to resume
564 |
565 | The values for `Type` can be: `Contains`, `EndsWith`, `Equals` or `StartsWith`
566 |
567 | ```json
568 | {
569 | "Type": "Contains",
570 | "Value": ""
571 | }
572 | ```
573 |
574 | ### Pause all triggers
575 |
576 | Do a `POST` request to `Scheduler/PauseAllTriggers`
577 |
578 | ### Resume all triggers
579 |
580 | Do a `POST` request to `Scheduler/ResumeAllTriggers`
581 |
582 | ### Get job keys
583 |
584 | Do a `GET` request to `Scheduler/GetJobKeys`
585 |
586 | The values for `Type` can be: `Contains`, `EndsWith`, `Equals` or `StartsWith`
587 |
588 | ```json
589 | {
590 | "Type": "Contains",
591 | "Value": ""
592 | }
593 | ```
594 |
595 | it will return something like this
596 |
597 | ```json
598 | [
599 | {
600 | "Name": "JobKeyName",
601 | "Group": "JobKeyGroup"
602 | }
603 | ]
604 | ```
605 |
606 | ### Get triggers of job
607 |
608 | Do a `GET` request to `Scheduler/GetTriggersOfJob` with in the body the key of the job
609 |
610 | ```json
611 | {
612 | "Name": "JobKeyName",
613 | "Group": "JobKeyGroup"
614 | }
615 | ```
616 |
617 | It will return something like this
618 |
619 | ```json
620 | [
621 | {
622 | "TriggerKey": {
623 | "Name": "triggerKey",
624 | "Group": "DEFAULT"
625 | },
626 | "Description": "TestTrigger",
627 | "CalendarName": null,
628 | "CronSchedule": null,
629 | "NextFireTimeUtc": null,
630 | "PreviousFireTimeUtc": "2024-01-28T11:21:14.4966492+01:00",
631 | "StartTimeUtc": "2024-01-28T11:21:14.4966492+01:00",
632 | "EndTimeUtc": null,
633 | "FinalFireTimeUtc": "2024-01-28T11:21:14.4966492+01:00",
634 | "Priority": 5,
635 | "HasMillisecondPrecision": true,
636 | "JobKey": null,
637 | "JobDataMap": null
638 | }
639 | ]
640 | ```
641 |
642 | ### Get trigger keys
643 |
644 | Do a `GET` request to `Scheduler/GetTriggerKeys`
645 |
646 | The values for `Type` can be: `Contains`, `EndsWith`, `Equals` or `StartsWith`
647 |
648 | ```json
649 | {
650 | "Type": "Contains",
651 | "Value": ""
652 | }
653 | ```
654 |
655 | it will return something like this
656 |
657 | ```json
658 | [
659 | {
660 | "Name": "triggerKey",
661 | "Group": "DEFAULT"
662 | }
663 | ]
664 | ```
665 |
666 | ### Get the job detail
667 |
668 | Do a `GET` request to `Scheduler/GetJobDetail` with in the body the key of the job
669 |
670 | ```json
671 | {
672 | "Name": "JobKeyName",
673 | "Group": "JobKeyGroup"
674 | }
675 | ```
676 |
677 | It will return something like this
678 |
679 | ```json
680 | {
681 | "JobKey": {
682 | "Name": "JobKeyName",
683 | "Group": "JobKeyGroup"
684 | },
685 | "Description": "Test",
686 | "JobType": "QuartzWebApi.TestJob",
687 | "JobDataMap": {},
688 | "Durable": false,
689 | "Replace": false,
690 | "StoreNonDurableWhileAwaitingScheduling": false
691 | }
692 | ```
693 |
694 | ### Get trigger
695 |
696 | Do a `GET` request to `Scheduler/GetTrigger` with in the body the key of the trigger
697 |
698 | ```json
699 | {
700 | "Name": "TriggerKeyName",
701 | "Group": "TriggerKeyGroup"
702 | }
703 | ```
704 |
705 | It will return something like this
706 |
707 | ```json
708 | {
709 | "TriggerKey": {
710 | "Name": "triggerKey",
711 | "Group": "DEFAULT"
712 | },
713 | "Description": "TestTrigger",
714 | "CalendarName": null,
715 | "CronSchedule": null,
716 | "NextFireTimeUtc": null,
717 | "PreviousFireTimeUtc": "2024-01-28T14:09:21.9475007+01:00",
718 | "StartTimeUtc": "2024-01-28T14:09:21.9475007+01:00",
719 | "EndTimeUtc": null,
720 | "FinalFireTimeUtc": "2024-01-28T14:09:21.9475007+01:00",
721 | "Priority": 5,
722 | "HasMillisecondPrecision": true,
723 | "JobKey": null,
724 | "JobDataMap": null
725 | }
726 | ```
727 |
728 | Do a `GET` request to `Scheduler/GetTriggerState` with in the body the key of the trigger
729 |
730 | ```json
731 | {
732 | "Name": "TriggerKeyName",
733 | "Group": "TriggerKeyGroup"
734 | }
735 | ```
736 |
737 | It will return something like this
738 |
739 | ```json
740 | "Normal"
741 | ```
742 |
743 | ### Add calendar
744 |
745 | Do a `POST` request to `Scheduler/AddCalendar` with in the body the body the calendar you want to add, for example
746 |
747 | ```json
748 | {
749 | "Name" : "My new CRON calendar",
750 | "Type": "Cron"
751 | "CronExpression": "0 0-5 14 * * ?",
752 | "Description": "my description"
753 | "Replace": true
754 | "UpdateTriggers": true
755 | }
756 | ```
757 |
758 | ### Delete a calendar
759 |
760 | Do a `DELETE` request to `Scheduler/DeleteCalendar/{calName}` where `calName` is het name of the calendar to delete, this will return `true` or `false`
761 |
762 | ### Get a calendar
763 |
764 | Do a `GET` request to `Scheduler/GetCalendar/{calName}` where `calName` is het name of the calendar to get, when the calendar exists it will return something like this
765 |
766 | ```json
767 | {
768 | "CronExpression": "0 0-51 4 * * ?",
769 | "Name": null,
770 | "Type": "Cron",
771 | "TimeZone": {
772 | "Id": "W. Europe Standard Time",
773 | "DisplayName": "(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna",
774 | "StandardName": "W. Europe Standard Time",
775 | "DaylightName": "W. Europe Daylight Time",
776 | "BaseUtcOffset": "01:00:00",
777 | "AdjustmentRules": [
778 | {
779 | "DateStart": "0001-01-01T00:00:00",
780 | "DateEnd": "9999-12-31T00:00:00",
781 | "DaylightDelta": "01:00:00",
782 | "DaylightTransitionStart": {
783 | "TimeOfDay": "0001-01-01T02:00:00",
784 | "Month": 3,
785 | "Week": 5,
786 | "Day": 1,
787 | "DayOfWeek": 0,
788 | "IsFixedDateRule": false
789 | },
790 | "DaylightTransitionEnd": {
791 | "TimeOfDay": "0001-01-01T03:00:00",
792 | "Month": 10,
793 | "Week": 5,
794 | "Day": 1,
795 | "DayOfWeek": 0,
796 | "IsFixedDateRule": false
797 | },
798 | "BaseUtcOffsetDelta": "00:00:00"
799 | }
800 | ],
801 | "SupportsDaylightSavingTime": true
802 | }
803 | }
804 | ```
805 |
806 | ### Get calendar names
807 |
808 | Do a `GET` request to `Scheduler/GetCalendarNames`, it will return something like this
809 |
810 | ```json
811 | [
812 | "monthlyCalendar",
813 | "MynewCRONcalendar"
814 | ]
815 | ```
816 |
817 |
818 | Errors returned
819 | ===============
820 |
821 | When an error occures this is returned as a .NET exception in JSON format like this
822 |
823 | ```json
824 | {
825 | "Message": "An error has occurred.",
826 | "ExceptionMessage": "Unable to store Trigger: 'TriggerKeyGroup.TriggerKeyName', because one already exists with this identification.",
827 | "ExceptionType": "Quartz.ObjectAlreadyExistsException",
828 | "StackTrace": "... the .NET stack trace ..."
829 | }
830 | ```
831 |
--------------------------------------------------------------------------------