nu.yona.server.batch.quartz.TriggerManagementService.java Source code

Java tutorial

Introduction

Here is the source code for nu.yona.server.batch.quartz.TriggerManagementService.java

Source

/*******************************************************************************
 * Copyright (c) 2017 Stichting Yona Foundation This Source Code Form is subject to the terms of the Mozilla Public License, v.
 * 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *******************************************************************************/
package nu.yona.server.batch.quartz;

import static java.util.stream.Collectors.toSet;
import static org.quartz.CronScheduleBuilder.cronSchedule;
import static org.quartz.TriggerBuilder.newTrigger;

import java.util.List;
import java.util.Set;
import java.util.TimeZone;

import javax.transaction.Transactional;

import org.quartz.CronTrigger;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.TriggerKey;
import org.quartz.impl.matchers.GroupMatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import nu.yona.server.exceptions.YonaException;

@Service
public class TriggerManagementService {
    private enum ChangeType {
        ADD, UPDATE
    }

    private static final Logger logger = LoggerFactory.getLogger(TriggerManagementService.class);

    @Autowired
    private Scheduler scheduler;

    public Set<CronTriggerDto> getAllTriggers() {
        return getTriggerGroupNames().stream().flatMap(gn -> getTriggerKeys(gn).stream()).map(this::getTrigger)
                .filter(t -> t instanceof CronTrigger).map(CronTriggerDto::createInstance).collect(toSet());
    }

    public Set<CronTriggerDto> getTriggersInGroup(String group) {
        return getTriggerKeys(group).stream().map(this::getTrigger).filter(t -> t instanceof CronTrigger)
                .map(CronTriggerDto::createInstance).collect(toSet());
    }

    public CronTriggerDto getTrigger(String name, String group) {
        return CronTriggerDto.createInstance(getTrigger(TriggerKey.triggerKey(name, group)));
    }

    @Transactional
    public CronTriggerDto addTrigger(String group, CronTriggerDto trigger) {
        logger.info("Adding trigger '{}' to group '{}'", trigger.getName(), group);
        return addOrUpdateTrigger(group, trigger, ChangeType.ADD);
    }

    @Transactional
    public CronTriggerDto updateTrigger(String group, CronTriggerDto trigger) {
        logger.info("Updating trigger '{}' in group '{}'", trigger.getName(), group);
        return addOrUpdateTrigger(group, trigger, ChangeType.UPDATE);
    }

    @Transactional
    public void deleteTrigger(String group, String name) {
        try {
            logger.info("Deleting trigger '{}' from group '{}'", name, group);
            scheduler.unscheduleJob(TriggerKey.triggerKey(name, group));
        } catch (SchedulerException e) {
            throw YonaException.unexpected(e);
        }
    }

    @Transactional
    public Set<CronTriggerDto> updateTriggerGroup(String group, Set<CronTriggerDto> triggers) {
        try {
            Set<String> trgNamesToBe = triggers.stream().map(CronTriggerDto::getName).collect(toSet());
            Set<TriggerKey> existingTrgs = scheduler.getTriggerKeys(GroupMatcher.triggerGroupEquals(group));
            Set<TriggerKey> keysOfTrgsToDelete = existingTrgs.stream().filter(tk -> !contains(trgNamesToBe, tk))
                    .collect(toSet());
            Set<CronTriggerDto> trgsToUpdate = triggers.stream().filter(t -> contains(existingTrgs, group, t))
                    .collect(toSet());
            Set<CronTriggerDto> trgsToAdd = triggers.stream().filter(t -> !contains(existingTrgs, group, t))
                    .collect(toSet());

            keysOfTrgsToDelete.forEach(tk -> deleteTrigger(tk.getGroup(), tk.getName()));
            trgsToUpdate.forEach(t -> updateTrigger(group, t));
            trgsToAdd.forEach(t -> addTrigger(group, t));

            return getTriggersInGroup(group);
        } catch (SchedulerException e) {
            throw YonaException.unexpected(e);
        }
    }

    private CronTriggerDto addOrUpdateTrigger(String group, CronTriggerDto triggerDto, ChangeType changeType) {
        try {
            CronTrigger trigger = createTrigger(group, triggerDto);
            if (changeType == ChangeType.ADD) {
                scheduler.scheduleJob(trigger);
            } else {
                scheduler.rescheduleJob(getTriggerKey(group, triggerDto), trigger);
            }
            logger.info("Next fire time for trigger '{}' in group '{}': {}", triggerDto.getName(), group,
                    trigger.getNextFireTime());
            return CronTriggerDto.createInstance(trigger);
        } catch (SchedulerException e) {
            throw YonaException.unexpected(e);
        }
    }

    private CronTrigger createTrigger(String group, CronTriggerDto triggerDto) {
        return newTrigger().forJob(triggerDto.getJobName(), group).withIdentity(triggerDto.getName(), group)
                .startNow()
                .withSchedule(cronSchedule(triggerDto.getCronExpression())
                        .inTimeZone(TimeZone.getTimeZone(triggerDto.getTimeZone()))
                        .withMisfireHandlingInstructionFireAndProceed())
                .build();
    }

    private TriggerKey getTriggerKey(String group, CronTriggerDto trigger) {
        return TriggerKey.triggerKey(trigger.getName(), group);
    }

    private boolean contains(Set<String> triggerNamesToBe, TriggerKey triggerKey) {
        return triggerNamesToBe.contains(triggerKey.getName());
    }

    private boolean contains(Set<TriggerKey> existingTriggers, String group, CronTriggerDto trigger) {
        return existingTriggers.contains(getTriggerKey(group, trigger));
    }

    private List<String> getTriggerGroupNames() {
        try {
            return scheduler.getTriggerGroupNames();
        } catch (SchedulerException e) {
            throw YonaException.unexpected(e);
        }
    }

    private CronTrigger getTrigger(TriggerKey tk) {
        try {
            return (CronTrigger) scheduler.getTrigger(tk);
        } catch (SchedulerException e) {
            throw YonaException.unexpected(e);
        }
    }

    private Set<TriggerKey> getTriggerKeys(String gn) {
        try {
            return scheduler.getTriggerKeys(GroupMatcher.triggerGroupEquals(gn));
        } catch (SchedulerException e) {
            throw YonaException.unexpected(e);
        }
    }
}