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

com.github.kagkarlsson.scheduler.task.FailureHandler Maven / Gradle / Ivy

The 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.task; import static java.lang.Math.pow; import static java.lang.Math.round; import com.github.kagkarlsson.scheduler.task.helper.ScheduleAndData; import com.github.kagkarlsson.scheduler.task.schedule.Schedule; import java.time.Duration; import java.time.Instant; import java.util.function.BiConsumer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public interface FailureHandler { void onFailure(ExecutionComplete executionComplete, ExecutionOperations executionOperations); class ExponentialBackoffFailureHandler implements FailureHandler { private static final Logger LOG = LoggerFactory.getLogger(ExponentialBackoffFailureHandler.class); private static final double DEFAULT_MULTIPLIER = 1.5; private final Duration sleepDuration; private final double exponentialRate; public ExponentialBackoffFailureHandler(Duration sleepDuration) { this.sleepDuration = sleepDuration; this.exponentialRate = DEFAULT_MULTIPLIER; } public ExponentialBackoffFailureHandler(Duration sleepDuration, double exponentialRate) { this.sleepDuration = sleepDuration; this.exponentialRate = exponentialRate; } @Override public void onFailure( final ExecutionComplete executionComplete, final ExecutionOperations executionOperations) { long retryDurationMs = round( sleepDuration.toMillis() * pow(exponentialRate, executionComplete.getExecution().consecutiveFailures)); Instant nextTry = executionComplete.getTimeDone().plusMillis(retryDurationMs); LOG.debug( "Execution failed {}. Retrying task {} at {}", executionComplete.getTimeDone(), executionComplete.getExecution().taskInstance, nextTry); executionOperations.reschedule(executionComplete, nextTry); } } class MaxRetriesFailureHandler implements FailureHandler { private static final Logger LOG = LoggerFactory.getLogger(MaxRetriesFailureHandler.class); private final int maxRetries; private final FailureHandler failureHandler; private final BiConsumer> maxRetriesExceededHandler; public MaxRetriesFailureHandler(int maxRetries, FailureHandler failureHandler) { this(maxRetries, failureHandler, (executionComplete, executionOperations) -> {}); } public MaxRetriesFailureHandler( int maxRetries, FailureHandler failureHandler, BiConsumer> maxRetriesExceededHandler) { this.maxRetries = maxRetries; this.failureHandler = failureHandler; this.maxRetriesExceededHandler = maxRetriesExceededHandler; } @Override public void onFailure( final ExecutionComplete executionComplete, final ExecutionOperations executionOperations) { int consecutiveFailures = executionComplete.getExecution().consecutiveFailures; int totalNumberOfFailures = consecutiveFailures + 1; if (totalNumberOfFailures > maxRetries) { LOG.error( "Execution has failed {} times for task instance {}. Cancelling execution.", totalNumberOfFailures, executionComplete.getExecution().taskInstance); executionOperations.stop(); maxRetriesExceededHandler.accept(executionComplete, executionOperations); } else { this.failureHandler.onFailure(executionComplete, executionOperations); } } } class OnFailureRetryLater implements FailureHandler { private static final Logger LOG = LoggerFactory.getLogger(CompletionHandler.OnCompleteReschedule.class); private final Duration sleepDuration; public OnFailureRetryLater(Duration sleepDuration) { this.sleepDuration = sleepDuration; } @Override public void onFailure( ExecutionComplete executionComplete, ExecutionOperations executionOperations) { Instant nextTry = executionComplete.getTimeDone().plus(sleepDuration); LOG.debug( "Execution failed. Retrying task {} at {}", executionComplete.getExecution().taskInstance, nextTry); executionOperations.reschedule(executionComplete, nextTry); } } class OnFailureReschedule implements FailureHandler { private static final Logger LOG = LoggerFactory.getLogger(CompletionHandler.OnCompleteReschedule.class); private final Schedule schedule; public OnFailureReschedule(Schedule schedule) { this.schedule = schedule; } @Override public void onFailure( ExecutionComplete executionComplete, ExecutionOperations executionOperations) { Instant nextExecution = schedule.getNextExecutionTime(executionComplete); LOG.debug( "Execution failed. Rescheduling task {} to {}", executionComplete.getExecution().taskInstance, nextExecution); executionOperations.reschedule(executionComplete, nextExecution); } } @SuppressWarnings("unchecked") class OnFailureRescheduleUsingTaskDataSchedule implements FailureHandler { private static final Logger LOG = LoggerFactory.getLogger(CompletionHandler.OnCompleteReschedule.class); @Override public void onFailure( ExecutionComplete executionComplete, ExecutionOperations executionOperations) { final T data = (T) executionComplete.getExecution().taskInstance.getData(); final Instant nextExecutionTime = data.getSchedule().getNextExecutionTime(executionComplete); LOG.debug( "Execution failed. Rescheduling task {} to {}", executionComplete.getExecution().taskInstance, nextExecutionTime); executionOperations.reschedule(executionComplete, nextExecutionTime); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy