All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.kagkarlsson.scheduler.ExecutePicked Maven / Gradle / Ivy

There is a newer version: 15.1.2
Show newest version
/*
 * Copyright (C) Gustav Karlsson
 *
 * 

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of the License at * *

http://www.apache.org/licenses/LICENSE-2.0 * *

Unless required by applicable law or agreed to in writing, software distributed under the * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language governing permissions and * limitations under the License. */ package com.github.kagkarlsson.scheduler; import static com.github.kagkarlsson.scheduler.ExceptionUtils.describe; import com.github.kagkarlsson.scheduler.event.ExecutionChain; import com.github.kagkarlsson.scheduler.event.ExecutionInterceptor; import com.github.kagkarlsson.scheduler.event.SchedulerListener.CandidateEventType; import com.github.kagkarlsson.scheduler.event.SchedulerListener.SchedulerEventType; import com.github.kagkarlsson.scheduler.event.SchedulerListeners; import com.github.kagkarlsson.scheduler.logging.ConfigurableLogger; import com.github.kagkarlsson.scheduler.task.CompletionHandler; import com.github.kagkarlsson.scheduler.task.Execution; import com.github.kagkarlsson.scheduler.task.ExecutionComplete; import com.github.kagkarlsson.scheduler.task.ExecutionContext; import com.github.kagkarlsson.scheduler.task.ExecutionHandler; import com.github.kagkarlsson.scheduler.task.ExecutionOperations; import com.github.kagkarlsson.scheduler.task.Task; import java.time.Instant; import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.UUID; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @SuppressWarnings({"rawtypes", "unchecked"}) class ExecutePicked implements Runnable { private static final Logger LOG = LoggerFactory.getLogger(ExecutePicked.class); private final Executor executor; private final TaskRepository taskRepository; private final SchedulerClient schedulerClient; private final SchedulerListeners schedulerListeners; private final List executionInterceptors; private final TaskResolver taskResolver; private final SchedulerState schedulerState; private final ConfigurableLogger failureLogger; private final Clock clock; private HeartbeatConfig heartbeatConfig; private final Execution pickedExecution; public ExecutePicked( Executor executor, TaskRepository taskRepository, SchedulerClient schedulerClient, SchedulerListeners schedulerListeners, List executionInterceptors, TaskResolver taskResolver, SchedulerState schedulerState, ConfigurableLogger failureLogger, Clock clock, HeartbeatConfig heartbeatConfig, Execution pickedExecution) { this.executor = executor; this.taskRepository = taskRepository; this.schedulerClient = schedulerClient; this.schedulerListeners = schedulerListeners; this.executionInterceptors = executionInterceptors; this.taskResolver = taskResolver; this.schedulerState = schedulerState; this.failureLogger = failureLogger; this.clock = clock; this.heartbeatConfig = heartbeatConfig; this.pickedExecution = pickedExecution; } @Override public void run() { // FIXLATER: need to cleanup all the references back to scheduler fields CurrentlyExecuting currentlyExecuting = new CurrentlyExecuting(pickedExecution, clock, heartbeatConfig); final UUID executionId = executor.addCurrentlyProcessing(currentlyExecuting); try { schedulerListeners.onCandidateEvent(CandidateEventType.EXECUTED); schedulerListeners.onExecutionStart(currentlyExecuting); executePickedExecution(pickedExecution, currentlyExecuting); } finally { executor.removeCurrentlyProcessing(executionId); } } private void executePickedExecution(Execution execution, CurrentlyExecuting currentlyExecuting) { final Optional task = taskResolver.resolve(execution.taskInstance.getTaskName()); if (!task.isPresent()) { LOG.error( "Failed to find implementation for task with name '{}'. Should have been excluded in JdbcRepository.", execution.taskInstance.getTaskName()); schedulerListeners.onSchedulerEvent(SchedulerEventType.UNEXPECTED_ERROR); return; } Instant executionStarted = clock.now(); try { LOG.debug("Executing: " + execution); ExecutionHandler handler = task.get(); ExecutionContext executionContext = new ExecutionContext(schedulerState, execution, schedulerClient, currentlyExecuting); ExecutionChain chain = new ExecutionChain(new ArrayList<>(executionInterceptors), handler); CompletionHandler completion = chain.proceed(execution.taskInstance, executionContext); LOG.debug("Execution done: " + execution); complete(completion, execution, executionStarted); } catch (RuntimeException unhandledException) { failure(task.get(), execution, unhandledException, executionStarted, "Unhandled exception"); } catch (Throwable unhandledError) { failure(task.get(), execution, unhandledError, executionStarted, "Error"); } } private void complete( CompletionHandler completion, Execution execution, Instant executionStarted) { ExecutionComplete completeEvent = ExecutionComplete.success(execution, executionStarted, clock.now()); try { completion.complete( completeEvent, new ExecutionOperations(taskRepository, schedulerListeners, execution)); } catch (Throwable e) { schedulerListeners.onSchedulerEvent(SchedulerEventType.COMPLETIONHANDLER_ERROR); schedulerListeners.onSchedulerEvent(SchedulerEventType.UNEXPECTED_ERROR); LOG.error( "Failed while completing execution {}, because {}. Execution will likely remain scheduled and locked/picked. " + "The execution should be detected as dead after a while, and handled according to the tasks DeadExecutionHandler.", execution, describe(e), e); } finally { schedulerListeners.onExecutionComplete(completeEvent); } } private void failure( Task task, Execution execution, Throwable cause, Instant executionStarted, String errorMessagePrefix) { String logMessage = "{} {} during execution of task with name '{}'. Treating as failure."; failureLogger.log(logMessage, cause, errorMessagePrefix, describe(cause), task.getName()); ExecutionComplete completeEvent = ExecutionComplete.failure(execution, executionStarted, clock.now(), cause); try { task.getFailureHandler() .onFailure( completeEvent, new ExecutionOperations(taskRepository, schedulerListeners, execution)); } catch (Throwable e) { schedulerListeners.onSchedulerEvent(SchedulerEventType.FAILUREHANDLER_ERROR); schedulerListeners.onSchedulerEvent(SchedulerEventType.UNEXPECTED_ERROR); LOG.error( "Failed while completing execution {}, because {}. Execution will likely remain scheduled and locked/picked. " + "The execution should be detected as dead after a while, and handled according to the tasks DeadExecutionHandler.", execution, describe(cause), e); } finally { schedulerListeners.onExecutionComplete(completeEvent); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy