using System.Data; using FictionArchive.Service.SchedulerService.Models; using FictionArchive.Service.SchedulerService.Models.JobTemplates; using FictionArchive.Service.Shared.Services.EventBus; using Quartz; using Quartz.Impl.Matchers; namespace FictionArchive.Service.SchedulerService.Services; public class JobManagerService { private readonly ILogger _logger; private readonly ISchedulerFactory _schedulerFactory; public JobManagerService(ILogger logger, ISchedulerFactory schedulerFactory) { _logger = logger; _schedulerFactory = schedulerFactory; } public async Task> GetScheduledJobs() { var scheduler = await _schedulerFactory.GetScheduler(); var groups = await scheduler.GetJobGroupNames(); var result = new List<(IJobDetail Job, IReadOnlyCollection Triggers)>(); foreach (var group in groups) { var jobKeys = await scheduler.GetJobKeys(GroupMatcher.GroupEquals(group)); foreach (var jobKey in jobKeys) { var jobDetail = await scheduler.GetJobDetail(jobKey); var triggers = await scheduler.GetTriggersOfJob(jobKey); result.Add((jobDetail, triggers)); } } return result.Select(tuple => new SchedulerJob() { JobKey = tuple.Job.Key, Description = tuple.Job.Description, JobTypeName = tuple.Job.JobType.FullName, JobData = tuple.Job.JobDataMap.ToDictionary(kv => kv.Key, kv => kv.Value.ToString()), CronSchedule = tuple.Triggers.Where(trigger => trigger is ICronTrigger).Select(trigger => (trigger as ICronTrigger).CronExpressionString).ToList() }).ToList(); } public async Task ScheduleEventJob(string? jobKey, string? description, string eventType, string eventData, string cronSchedule) { var scheduler = await _schedulerFactory.GetScheduler(); if (await scheduler.GetJobDetail(new JobKey(jobKey)) != null) { throw new DuplicateNameException("A job with the same key already exists."); } jobKey ??= Guid.NewGuid().ToString(); var jobData = new JobDataMap { { EventJobTemplate.EventTypeParameter, eventType }, { EventJobTemplate.EventDataParameter, eventData } }; var job = JobBuilder.Create() .WithIdentity(jobKey) .WithDescription(description ?? $"Fires off an event on a set schedule") .SetJobData(jobData) .Build(); var trigger = TriggerBuilder.Create() .WithIdentity(jobKey) .WithCronSchedule(cronSchedule) .StartNow() .Build(); await scheduler.ScheduleJob(job, trigger); return new SchedulerJob() { CronSchedule = new List { cronSchedule }, Description = description, JobKey = new JobKey(jobKey), JobTypeName = typeof(EventJobTemplate).FullName, JobData = jobData.ToDictionary(kv => kv.Key, kv => kv.Value.ToString()) }; } public async Task TriggerJob(string jobKey) { var scheduler = await _schedulerFactory.GetScheduler(); await scheduler.TriggerJob(new JobKey(jobKey)); return true; } public async Task DeleteJob(string jobKey) { var scheduler = await _schedulerFactory.GetScheduler(); return await scheduler.DeleteJob(new JobKey(jobKey)); } }