Search in sources :

Example 1 with TaskSchedulingStateType

use of com.evolveum.midpoint.xml.ns._public.common.common_3.TaskSchedulingStateType in project midpoint by Evolveum.

the class TaskSynchronizer method synchronizeTask.

/**
 * Task should be refreshed when entering this method.
 *
 * @return true if task info in Quartz was updated
 */
public boolean synchronizeTask(TaskQuartzImpl task, OperationResult parentResult) {
    if (!task.isPersistent()) {
        // transient tasks are not scheduled via Quartz!
        return false;
    }
    boolean changed = false;
    StringBuilder message = new StringBuilder();
    OperationResult result = parentResult.createSubresult(OP_SYNCHRONIZE_TASK);
    result.addArbitraryObjectAsParam("task", task);
    try {
        taskMigrator.migrateIfNeeded(task, result);
        LOGGER.trace("Synchronizing task {}; isRecreateQuartzTrigger = {}", task, task.isRecreateQuartzTrigger());
        Scheduler scheduler = localScheduler.getQuartzScheduler();
        String oid = task.getOid();
        JobKey jobKey = QuartzUtil.createJobKeyForTask(task);
        TriggerKey standardTriggerKey = QuartzUtil.createTriggerKeyForTask(task);
        TaskSchedulingStateType schedulingState = task.getSchedulingState();
        boolean waitingOrClosedOrSuspended = schedulingState == TaskSchedulingStateType.WAITING || schedulingState == TaskSchedulingStateType.CLOSED || schedulingState == TaskSchedulingStateType.SUSPENDED;
        if (!scheduler.checkExists(jobKey) && !waitingOrClosedOrSuspended) {
            String m1 = "Quartz job does not exist for a task, adding it. Task = " + task;
            message.append("[").append(m1).append("] ");
            LOGGER.trace(" - {}", m1);
            scheduler.addJob(QuartzUtil.createJobDetailForTask(task), false);
            changed = true;
        }
        // CLOSED tasks should have no triggers; SUSPENDED and WAITING tasks should have no extra triggers
        List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
        boolean standardTriggerExists = triggers.stream().anyMatch(t -> t.getKey().equals(standardTriggerKey));
        if (waitingOrClosedOrSuspended) {
            for (Trigger trigger : triggers) {
                if (schedulingState == TaskSchedulingStateType.CLOSED || !trigger.getKey().equals(standardTriggerKey)) {
                    String m1 = "Removing Quartz trigger " + trigger.getKey() + " for WAITING/CLOSED/SUSPENDED task " + task;
                    message.append("[").append(m1).append("] ");
                    LOGGER.trace(" - {}", m1);
                    scheduler.unscheduleJob(trigger.getKey());
                    changed = true;
                } else {
                // For SUSPENDED/WAITING tasks, we keep the standard trigger untouched. We want to preserve original
                // scheduled time. (This might or might not be what the user wants ... but it has been so for so
                // many years, so let's not change it now.)
                // 
                // It's harmless to keep the standard trigger, because:
                // 1) If a trigger is mistakenly alive, JobExecutor will take care of it.
                // 2) If a trigger has wrong parameters, this will be corrected on task resume/unpause.
                }
            }
        } else if (schedulingState == TaskSchedulingStateType.READY) {
            Trigger triggerToBe;
            try {
                triggerToBe = QuartzUtil.createTriggerForTask(task);
            } catch (ParseException e) {
                String message2 = "Cannot create a trigger for a task " + this + " because of a cron expression parsing exception";
                LoggingUtils.logUnexpectedException(LOGGER, message2, e);
                result.recordFatalError(message2, e);
                // TODO: implement error handling correctly
                throw new SystemException("Cannot a trigger for a task because of a cron expression parsing exception", e);
            }
            if (triggerToBe == null) {
                if (standardTriggerExists) {
                    // TODO what about non-standard triggers?
                    // These may be legal here (e.g. for a manually-run recurring task waiting to get a chance to run)
                    String m1 = "Removing standard Quartz trigger for RUNNABLE task that should not have it; task = " + task;
                    message.append("[").append(m1).append("] ");
                    LOGGER.trace(" - " + m1);
                    scheduler.unscheduleJob(TriggerKey.triggerKey(oid));
                    changed = true;
                }
            } else {
                // if the trigger should exist and it does not...
                if (!standardTriggerExists) {
                    String m1 = "Creating standard trigger for a RUNNABLE task " + task;
                    LOGGER.trace(" - " + m1);
                    message.append("[").append(m1).append("] ");
                    scheduler.scheduleJob(triggerToBe);
                    changed = true;
                } else {
                    // we have to compare trigger parameters with the task's ones
                    Trigger triggerAsIs = scheduler.getTrigger(standardTriggerKey);
                    if (task.isRecreateQuartzTrigger() || QuartzUtil.triggersDiffer(triggerAsIs, triggerToBe)) {
                        String m1 = "Existing trigger has incompatible parameters or was explicitly requested to be recreated; recreating it. Task = " + task;
                        LOGGER.trace(" - " + m1);
                        message.append("[").append(m1).append("] ");
                        scheduler.rescheduleJob(standardTriggerKey, triggerToBe);
                        changed = true;
                    } else {
                        String m1 = "Existing trigger is OK, leaving it as is; task = " + task;
                        LOGGER.trace(" - " + m1);
                        message.append("[").append(m1).append("] ");
                        Trigger.TriggerState state = scheduler.getTriggerState(standardTriggerKey);
                        if (state == Trigger.TriggerState.PAUSED) {
                            String m2 = "However, the trigger is paused, resuming it; task = " + task;
                            LOGGER.trace(" - " + m2);
                            message.append("[").append(m2).append("] ");
                            scheduler.resumeTrigger(standardTriggerKey);
                            changed = true;
                        }
                    }
                }
            }
        }
    } catch (Exception e) {
        String message2 = "Cannot synchronize repository/Quartz Job Store information for task " + task;
        LoggingUtils.logUnexpectedException(LOGGER, message2, e);
        result.recordFatalError(message2, e);
    } finally {
        if (result.isUnknown()) {
            result.computeStatus();
            result.recordStatus(result.getStatus(), message.toString());
        }
    }
    LOGGER.trace("synchronizeTask finishing (changed: {}) for {}", changed, task);
    return changed;
}
Also used : Scheduler(org.quartz.Scheduler) OperationResult(com.evolveum.midpoint.schema.result.OperationResult) SchemaException(com.evolveum.midpoint.util.exception.SchemaException) SchedulerException(org.quartz.SchedulerException) ParseException(java.text.ParseException) ObjectNotFoundException(com.evolveum.midpoint.util.exception.ObjectNotFoundException) SystemException(com.evolveum.midpoint.util.exception.SystemException) TriggerKey(org.quartz.TriggerKey) JobKey(org.quartz.JobKey) Trigger(org.quartz.Trigger) SystemException(com.evolveum.midpoint.util.exception.SystemException) TaskSchedulingStateType(com.evolveum.midpoint.xml.ns._public.common.common_3.TaskSchedulingStateType) ParseException(java.text.ParseException)

Example 2 with TaskSchedulingStateType

use of com.evolveum.midpoint.xml.ns._public.common.common_3.TaskSchedulingStateType in project midpoint by Evolveum.

the class ScheduleNowHelper method scheduleCoordinatorAndWorkersNow.

public void scheduleCoordinatorAndWorkersNow(String coordinatorOid, OperationResult result) throws SchemaException, ObjectNotFoundException {
    TaskQuartzImpl coordinatorTask = taskRetriever.getTaskPlain(coordinatorOid, result);
    TaskSchedulingStateType state = coordinatorTask.getSchedulingState();
    switch(state) {
        case CLOSED:
        case READY:
            // hoping that the task handler will do what is needed (i.e. recreate or restart workers)
            scheduleTaskNow(coordinatorTask, result);
            break;
        case WAITING:
            // this means that workers are either busy (runnable) or are suspended; administrator should do something with that
            String msg1 = "Coordinator " + coordinatorTask + " cannot be run now, because it is in WAITING scheduling state. " + "Please check and resolve state of its worker tasks.";
            LOGGER.error(msg1);
            result.recordFatalError(msg1);
            break;
        case SUSPENDED:
            String msg2 = "Coordinator " + coordinatorTask + " cannot be run now, because it is in SUSPENDED state. " + "Please use appropriate method to schedule its execution.";
            LOGGER.error(msg2);
            result.recordFatalError(msg2);
            break;
        default:
            throw new IllegalStateException("Coordinator " + coordinatorTask + " is in unsupported state: " + state);
    }
}
Also used : TaskQuartzImpl(com.evolveum.midpoint.task.quartzimpl.TaskQuartzImpl) TaskSchedulingStateType(com.evolveum.midpoint.xml.ns._public.common.common_3.TaskSchedulingStateType)

Aggregations

TaskSchedulingStateType (com.evolveum.midpoint.xml.ns._public.common.common_3.TaskSchedulingStateType)2 OperationResult (com.evolveum.midpoint.schema.result.OperationResult)1 TaskQuartzImpl (com.evolveum.midpoint.task.quartzimpl.TaskQuartzImpl)1 ObjectNotFoundException (com.evolveum.midpoint.util.exception.ObjectNotFoundException)1 SchemaException (com.evolveum.midpoint.util.exception.SchemaException)1 SystemException (com.evolveum.midpoint.util.exception.SystemException)1 ParseException (java.text.ParseException)1 JobKey (org.quartz.JobKey)1 Scheduler (org.quartz.Scheduler)1 SchedulerException (org.quartz.SchedulerException)1 Trigger (org.quartz.Trigger)1 TriggerKey (org.quartz.TriggerKey)1