ISchedulerFactory schedulerFactory = new StdSchedulerFactory(schedulerProperties);
_scheduler = await schedulerFactory.GetScheduler();
IJobFactory jobFactory = new PeregrineJobFactory(_container); // my custom job factory
_scheduler.JobFactory = jobFactory;
// these are objects I can grab within the job factory class
_container.RegisterInstance(_scheduler);
_container.RegisterInstance(_log);
_container.RegisterInstance(_configuration);
_container.RegisterInstance(_logconfig);
// use reflection to get all the jobs to register. They all have to implement IPeregrineJob interface
var path = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "PeregrineJobs");
var jobAssemblies =
from file in new DirectoryInfo(path).GetFiles()
where file.Extension.ToLower() == ".dll"
select Assembly.Load(AssemblyName.GetAssemblyName(file.FullName));
_container.Collection.Register<IPeregrineJob>(jobAssemblies);
public class PeregrineJobFactory : IJobFactory
{
private readonly IServiceProvider serviceProvider;
private ILog log;
private LogConfiguration logconfig;
private static Dictionary<string, ILog> jobLogs = new Dictionary<string, ILog>();
private IScheduler scheduler;
/// <summary>
/// The serviceProvider is the container being passed to the constructor by the Peregrine Scheduler Service
/// </summary>
/// <param name="serviceProvider"></param>
public PeregrineJobFactory(IServiceProvider serviceProvider)
{
this.serviceProvider = serviceProvider;
}
/// <summary>
/// Creates a new Peregrine Scheduler Job, by using Simple Injection (i.e. GetService(type) )
/// off of the container passed by the Peregrine Scheduler Service.
/// This handles logging and creating a log specific to the Peregrine Scheduler Job Type and then
/// injecting the log as well as the several parameters from the Quartz JobDataMap into the
/// instance of the job created.
///
/// if an error occurs, its logged and a SchedulerException() is thrown.
/// </summary>
/// <param name="bundle"></param>
/// <param name="scheduler"></param>
/// <returns>Quartz.NET Scheudler Job</returns>
public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler)
{
IJobDetail jobDetail = bundle.JobDetail;
//Retreive the log and LogConfiguration object from the container. originally set the Peregrine Scheduler Service
this.log = this.serviceProvider.GetService(typeof(ILog)) as ILog;
this.logconfig = this.serviceProvider.GetService(typeof(LogConfiguration)) as LogConfiguration;
this.scheduler = this.serviceProvider.GetService(typeof(IScheduler)) as IScheduler;
var configuration = this.serviceProvider.GetService(typeof(ESBConfiguration)) as ESBConfiguration;
try
{
Type jobType = jobDetail.JobType;
if (this.log.IsDebugEnabled)
this.log.Debug($"Received request to create instance of Job '{jobDetail.Key}', class='{jobType.FullName}'");
// Retreive the parameters to inject into the Peregrine Job that's created. The Job will be able to use and update
// these.
var requestMessage = bundle.JobDetail.JobDataMap.GetString("peregrine.requestMessage");
var responseMessage = bundle.JobDetail.JobDataMap.GetString("peregrine.responseMessage");
var lastexecutionTime = bundle.JobDetail.JobDataMap.GetString("peregrine.lastExecutionTimeUTC");
// copy the jobdatamap to a serialized dictionary
SerializableDictionary<string, object> jobDataMapDictionary = new SerializableDictionary<string, object>();
foreach (var item in bundle.JobDetail.JobDataMap)
{
jobDataMapDictionary.Add(item.Key, item.Value);
if (this.log.IsInfoEnabled)
this.log.Info($"Job Data Map key '{item.Key}' with value of '{item.Value}' added to Job Dictionary");
}
if (this.log.IsDebugEnabled)
{
this.log.Debug($"Retrieved Request Message to pass to scheduled instance of Job '{jobDetail.Key}', class='{jobType.FullName}'. Request Message={requestMessage}");
this.log.Debug($"Retrieved the last Response Message to pass to scheduled instance of Job '{jobDetail.Key}', class='{jobType.FullName}'. Response Message={responseMessage}");
this.log.Debug($"Retrieved the Last Execution Timestamp to pass to scheduled instance of Job '{jobDetail.Key}', class='{jobType.FullName}'. Last Execution Timestamp UTC={lastexecutionTime}");
}
// Create an instance of the job using the container service injected
var job = serviceProvider.GetService(jobType) as IPeregrineJob;
if (job == null)
throw new ArgumentNullException($"job", "The service provider returned a NULL instance of Job '{jobDetail.Key}', class='{jobType.FullName}'");
if (this.log.IsDebugEnabled)
this.log.Debug($"Instance of Job '{jobDetail.Key}', class='{jobType.FullName}' returned and properties being set.");
// Set the properties of the Job with the Parameters from the JobDataMap
job.RequestMessage = requestMessage;
job.ResponseMessage = responseMessage;
job.LastExecutionTimeUTC = lastexecutionTime;
job.Configuration = configuration;
job.JobDataDictionary = jobDataMapDictionary;
job.Key = bundle.JobDetail.Key;
// set log object specific to the job type. Each job type will have its own unique log file generated.
if (jobLogs.ContainsKey(jobType.FullName))
job.Log = jobLogs[jobType.FullName];
else
{
var jobLog = logconfig.ConfigureLogger("PeregrineScheduler", "Default", "MyApplicationName", System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "EndpointHost", "PeregrineScheduler", jobType);
jobLogs.Add(jobType.FullName, jobLog);
job.Log = jobLog;
}
if (this.log.IsInfoEnabled)
this.log.Info($"Instance of Job '{jobDetail.Key}', class='{jobType.FullName}' was created successfully!");
return job as IJob;
}
catch (Exception ex)
{
this.log.Error($"An error occurred creating the Job '{jobDetail.Key}' class='{jobDetail.JobType.FullName}'. {ex.Message}", ex);
throw new SchedulerException($"An error occurred creating the Job '{jobDetail.Key}' class='{jobDetail.JobType.FullName}'", ex);
}
}
public void ReturnJob(IJob job)
{
var disposable = job as IDisposable;
disposable?.Dispose();
}
}