private void SyncJobs(DateTime runTime) { try { //Convert time to UTC runTime = runTime.ToUniversalTime(); var systemJobs = _schedulerDbTools.GetSystemJobs(); var jobGroups = new List <string>(); //Get all quartz job group names jobGroups.AddRange(_quartzScheduler.GetJobGroupNames()); //Get all database jobs that are not in quartz jobGroups.AddRange(systemJobs.Select(s => s.JobClassType).Where(s => !jobGroups.Contains(s))); //Here all jobs will be saved based on their state var jobsToAdd = new List <JobKey>(); var jobsToUpdate = new List <JobKey>(); var jobsToRemove = new List <JobKey>(); foreach (var quartzJobName in jobGroups) { //Get all system and quartz jobs by current job group name var groupSysJobs = systemJobs.Where(s => s.JobClassType.Equals(quartzJobName)).ToArray(); var groupJobKeys = _quartzScheduler.GetJobKeys(GroupMatcher <JobKey> .GroupEquals(quartzJobName)); //If there are no jobs for such group name continue if (!groupSysJobs.Any() && !groupJobKeys.Any()) { continue; } //If there are no system jobs and some quartz jobs exist for given group name they have to be stopped if (!groupSysJobs.Any() && groupJobKeys.Any()) { jobsToRemove.AddRange(groupJobKeys); continue; } //Get available system jobs var availableSysJobs = groupSysJobs.Where(j => j.IsEnabled && ((j.AllowMultipleInstances) || (!j.AllowMultipleInstances && _isPrimary))).ToArray(); //If there are some system jobs avaialble and no such quartz jobs, they all have to be added if (availableSysJobs.Any() && !groupJobKeys.Any()) { jobsToAdd.AddRange(availableSysJobs.Select(j => new JobKey(j.SystemJobId, j.JobClassType))); continue; } //Keys that are in quartz jobs but not in available system jobs var remove = groupJobKeys.Where(gk => availableSysJobs.All(j => j.SystemJobId != gk.Name)); //Keys that are in system jobs but not in quartz var add = availableSysJobs.Where(j => groupJobKeys.All(gk => j.SystemJobId != gk.Name)) .Select(j => new JobKey(j.SystemJobId, j.JobClassType)); jobsToRemove.AddRange(remove); jobsToAdd.AddRange(add); //Remaining keys that are in both system and quartz so need to be checked for changes foreach (var updateKey in groupJobKeys.Except(remove)) { var job = systemJobs.First(s => s.SystemJobId == updateKey.Name); if (job.IsEnabled && ((job.AllowMultipleInstances) || (!job.AllowMultipleInstances && _isPrimary))) { //check if job was modified during current interval if (job.LastModified.HasValue && job.LastModified.Value.AddMilliseconds(Interval) >= runTime || job.JobParameters.Any(x => x.LastModified.HasValue && x.LastModified.Value.AddMilliseconds(Interval) >= runTime)) { jobsToUpdate.Add(updateKey); } } else { jobsToRemove.Add(updateKey); } } } //Remove jobs foreach (var jobKey in jobsToRemove.Where(jobKey => _quartzScheduler.CheckExists(jobKey))) { _quartzScheduler.DeleteJob(jobKey); } //Add and Update Jobs foreach (var jobKey in jobsToAdd.Union(jobsToUpdate)) { AddJob(_quartzScheduler, systemJobs.First(x => x.SystemJobId == jobKey.Name), _getJob); } if (!_quartzScheduler.IsStarted) { _quartzScheduler.Start(); } } catch (Exception ex) { _traceSource.Error(ex.ToString()); //If database does not exist if (ex is ConfigurationErrorsException) { Stop(); } } }