web-dev-qa-db-fra.com

Impossible de stocker le travail car un existe déjà avec cette identification

Je suis nouveau avec Quartz. J'ai réussi à l'installer et à l'exécuter. Mais j'ai une erreur lorsque je l'exécute pour la deuxième fois car le travail existe déjà avec cette identification.

Voici mon code:

public void scheduleJobs() throws Exception {

    try {
        int i = 0;

        scheduler = new StdSchedulerFactory().getScheduler();

        JobKey job1Key = JobKey.jobKey("job"+i, "my-jobs"+i);
        JobDetail job1 = JobBuilder
                .newJob(SimpleJob.class)
                .withIdentity(job1Key)
                .build();

        TriggerKey tk1 = TriggerKey.triggerKey("trigger"+i, "my-jobs"+i);
        Trigger trigger1 = TriggerBuilder
                .newTrigger()
                .withIdentity(tk1)
                .withSchedule(CronScheduleBuilder.dailyAtHourAndMinute(11, 25))
                .build();

        scheduler.start(); // start before scheduling jobs
        scheduler.scheduleJob(job1, trigger1);
        i++;

        printJobsAndTriggers(scheduler);

    } catch (SchedulerException e) {
        LOG.error("Error while creating scheduler", e);
    }   
}

J'ai essayé d'utiliser un entier i pour changer le nom mais cela ne fonctionne pas. Avez-vous une idée de comment y remédier? Merci beaucoup.

12
Majestic

Vous pouvez:

  • vérifiez si la "clé de tâche" existe déjà et supprimez la tâche existante avant d'en créer une nouvelle:

    scheduler.deleteJob(job1Key);

  • ou créez un nouveau travail avec une autre clé (dans votre cas, chaque fois que vous exécutez scheduleJobs(), la variable i a la même valeur (0)

  • ou simplement réutiliser le même travail (pourquoi créer un nouveau travail si l'ancien est toujours bon)

  • ou utilisez le RAM Job Store, qui ne conserve pas les jobs dans la base de données (chaque fois que vous utiliserez votre logiciel, vous aurez un magasin de jobs vide))

Cela dépend vraiment de ce que vous voulez faire de votre travail!

15
olivierlemasle

Ce n'est pas une réponse directe au code spécifique répertorié dans la question, mais je ne l'ai pas remarqué lors d'une recherche ailleurs et j'ai pensé que cela pourrait être utile pour les futurs lecteurs:

Si vous êtes dans une situation où vous avez un existantJob mais que vous souhaitez simplement ajouter un nouveaTrigger, vous pouvez appeler:

scheduler.ScheduleJob(trigger);

et il ajoutera le Trigger au Job sans essayer de recréer le Job. La seule astuce est que vous devez vous assurer que le TriggerJobKey est correct.

Mon code global pour cette interaction ressemble à peu près à:

IJobDetail job;   // Handed in
ITrigger trigger; // Handed in

// Keeping track of this because we need to know later whether it's new or not
var newJob = job == null;
if (newJob)
{
    job = JobBuilder.Create<TargetJob>()
                 .WithIdentity([whatever]) 
                 [.OtherConfiguration()]
                 .Build();
}

var trigger = TriggerBuilder
    .Create()
    .WithIdentity([whatever])
    // ** Gotcha #1: Make sure it's linked to the job **
    .ForJob(job.Key) 
    [.OtherConfiguration()]
    .Build();

if (newJob)
{
    _scheduler.ScheduleJob(job, trigger);
}
else
{
    // ** Gotcha #2: Make sure you don't reschedule the job **
    _scheduler.ScheduleJob(trigger);
}
6
eouw0o83hf

Vérifiez la tâche existante avant de planifier:

JobDetail job;
SimpleTrigger trigger;

//Create your trigger and job

Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.start();

if (scheduler.checkExists(job.getKey())){
    scheduler.deleteJob(job.getKey());
}
scheduler.scheduleJob(job, trigger);
4
Oleg Mikhailov

Si l'un d'entre vous est confronté au même problème et que votre solution est en C #. Voici comment vous pouvez corriger cette erreur.

C'est là que nous configurons le planificateur.

public async Task StartAsync(CancellationToken cancellationToken) {
    try {
        var scheduler = await GetScheduler();
        var serviceProvider = GetConfiguredServiceProvider();
        scheduler.JobFactory = new CustomJobFactory(serviceProvider);
        await scheduler.Start();
        await ConfigureDailyJob(scheduler);
    }
    catch(Exception ex) {
        _logger.Error(new CustomConfigurationException(ex.Message));
    }
}

C'est ainsi que nous pouvons configurer le Job, veuillez noter que nous vérifions si le Job est déjà là, et si la await scheduler.CheckExists(dailyJob.Key) retourne vrai, nous supprimons ces informations de Job et en créons une nouvelle avec la même clé .

private async Task ConfigureDailyJob(IScheduler scheduler) {
    var dailyJob = GetDailyJob();
    if (await scheduler.CheckExists(dailyJob.Key)) {
        await scheduler.DeleteJob(dailyJob.Key);
        _logger.Info($ "The job key {dailyJob.Key} was already existed, thus deleted the same");
    }
    await scheduler.ScheduleJob(dailyJob, GetDailyJobTrigger());
}

Il y a les fonctions privées de support.

private IJobDetail GetDailyJob() {
    return JobBuilder.Create < IDailyJob > ().WithIdentity("dailyjob", "dailygroup").Build();
}
private ITrigger GetDailyJobTrigger() {
    return TriggerBuilder.Create().WithIdentity("dailytrigger", "dailygroup").StartNow().WithSimpleSchedule(x = >x.WithIntervalInHours(24).RepeatForever()).Build();
}

Vous pouvez obtenir le code source complet de ce référentiel GitHub .

0
Sibeesh Venu