asp.net-coreasp.net-core-mvcquartz.net

how change automatic job time with quartz for asp.net core?


Hi I try create website with asp.net core MVC(.net 7). I want automate get backup from my database. for this I use quartz and everything worked fine when I hard coding the Crone Expression for the every 5 min. but I want change this dynamically. so I create dropdown list in view for admin, that can change between every hour, every week, and every month. the code is run but the time of job is not change. also for test of this I user the crone for every 10 second after the change complete. the code is not showing error, but the time is not change to 10 sec. how to fix this? this is my code in program.cs file for configure quartz:

builder.Services.AddSingleton<IJobFactory, SingletonJobFactory>();
builder.Services.AddSingleton<ISchedulerFactory, StdSchedulerFactory>();
builder.Services.AddSingleton<IScheduler>(provider =>
{
    var schedulerFactory = new StdSchedulerFactory();
    return schedulerFactory.GetScheduler().Result;
});


builder.Services.AddSingleton<BackUpdatabase>();
builder.Services.AddSingleton(new Jobschedule(jobType: typeof(BackUpdatabase), cronExpression:
    "* 0./5 * * * ?"));
builder.Services.AddHostedService<QuartzHostService>();

and this is my controller for changing the time:

public class SettingMenuController : Controller
    {
        private readonly IScheduler _scheduler;

        public SettingMenuController( IScheduler scheduler)
        {
            _scheduler = scheduler;
        }

        public IActionResult Index(string? message = null)
        {

            if (!string.IsNullOrEmpty(message))
            {
                ViewBag.message = message;
            }


            return View("SettingMenu", refreshSettingPage());
        }

  

        [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> changeAutoTime(int cron)
        {
            //if (cron == 0) //day
            //{ 
            //    await UpdateJobSchedule("0 0 0 * * ?");
            //}
            //else if (cron == 1) //week
            //{
            //    await UpdateJobSchedule("0 0 0 ? * MON");
            //}
            //else if (cron == 2) //month
            //{
            //    await UpdateJobSchedule("0 0 12 1 1/1 ? *");
            //}
            //else
            //{
            //    await UpdateJobSchedule("0 0 0 * * ?");
            //}

            await UpdateJobSchedule("0/10 * * * * ?");
            return RedirectToAction("Index", new { message = "time is change" });
        }



        private async Task UpdateJobSchedule(string cronExpression)
        {
            var jobKey = new JobKey("BackUpdatabase"); // Specify the job name as "BackUpdatabase"
            var defaultGroup = "DEFAULT"; // Use the default group for triggers if not explicitly specified

            var jobDetail = await _scheduler.GetJobDetail(jobKey);
            if (jobDetail != null)
            {
                var triggerKeys = await _scheduler.GetTriggerKeys(GroupMatcher<TriggerKey>.GroupEquals(defaultGroup));
                foreach (var triggerKey in triggerKeys)
                {
                    // Loop through all triggers associated with the job and update their schedule
                    var trigger = await _scheduler.GetTrigger(triggerKey);
                    if (trigger != null && trigger.JobKey.Equals(jobKey))
                    {
                        var newTrigger = TriggerBuilder.Create()
                            .WithIdentity(triggerKey)
                            .WithSchedule(CronScheduleBuilder.CronSchedule(cronExpression))
                            .Build();

                        await _scheduler.RescheduleJob(triggerKey, newTrigger);
                    }
                }
            }
        }

    }

how to fix this? please help.


Solution

  • Make sure that the job's name is "BackUpdatabase" when it's first scheduled.

    var jobKey = new JobKey("BackUpdatabase");
    

    Check the Quartz and Quartz.Extensions.Hosting NuGet packages installed in the project.

    In your QuartzHostService or wherever you schedule the job for the first time, ensure you're setting a `JobKey:

    JobBuilder.Create<BackUpdatabase>()
              .WithIdentity("BackUpdatabase") 
              .Build();
    

    Here is the updated code of UpdateJobSchedule method this will help you removing old triggers associated with the job and adding a new one.

    private async Task UpdateJobSchedule(string cronExpression)
    {
        var jobKey = new JobKey("BackUpdatabase");
        var triggerKey = new TriggerKey("BackupTrigger"); 
    
        var jobDetail = await _scheduler.GetJobDetail(jobKey);
        if (jobDetail != null)
        {
            var existingTriggers = await _scheduler.GetTriggersOfJob(jobKey);
            foreach (var trigger in existingTriggers)
            {
                await _scheduler.UnscheduleJob(trigger.Key);
            }
    
            var newTrigger = TriggerBuilder.Create()
                .WithIdentity(triggerKey)
                .ForJob(jobKey)
                .WithCronSchedule(cronExpression)
                .Build();
    
            await _scheduler.ScheduleJob(newTrigger);
        }
    

    If it does not work enable logging in your methods to see if the methods are being hit as expected or not.