001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.camel.util.backoff; 018 019import java.util.concurrent.ScheduledExecutorService; 020import java.util.concurrent.TimeUnit; 021import java.util.function.BiConsumer; 022 023import org.apache.camel.util.function.ThrowingFunction; 024 025/** 026 * A simple timer utility that use a linked {@link BackOff} to determine when a task should be executed. 027 */ 028public class BackOffTimer { 029 private final ScheduledExecutorService scheduler; 030 031 public BackOffTimer(ScheduledExecutorService scheduler) { 032 this.scheduler = scheduler; 033 } 034 035 /** 036 * Schedule the given function/task to be executed some time in the future according to the given backOff. 037 */ 038 public Task schedule(BackOff backOff, ThrowingFunction<Task, Boolean, Exception> function) { 039 final BackOffTimerTask task = new BackOffTimerTask(backOff, scheduler, function); 040 041 long delay = task.next(); 042 if (delay != BackOff.NEVER) { 043 scheduler.schedule(task, delay, TimeUnit.MILLISECONDS); 044 } else { 045 task.cancel(); 046 } 047 048 return task; 049 } 050 051 // **************************************** 052 // TimerTask 053 // **************************************** 054 055 public interface Task { 056 enum Status { 057 Active, 058 Inactive, 059 Exhausted 060 } 061 062 /** 063 * The back-off associated with this task. 064 */ 065 BackOff getBackOff(); 066 067 /** 068 * Gets the task status. 069 */ 070 Status getStatus(); 071 072 /** 073 * The number of attempts so far. 074 */ 075 long getCurrentAttempts(); 076 077 /** 078 * The current computed delay. 079 */ 080 long getCurrentDelay(); 081 082 /** 083 * The current elapsed time. 084 */ 085 long getCurrentElapsedTime(); 086 087 /** 088 * The time the first attempt was performed. 089 */ 090 long getFirstAttemptTime(); 091 092 /** 093 * The time the last attempt has been performed. 094 */ 095 long getLastAttemptTime(); 096 097 /** 098 * An indication about the time the next attempt will be made. 099 */ 100 long getNextAttemptTime(); 101 102 /** 103 * Reset the task. 104 */ 105 void reset(); 106 107 /** 108 * Cancel the task. 109 */ 110 void cancel(); 111 112 /** 113 * Action to execute when the context is completed (cancelled or exhausted) 114 * 115 * @param whenCompleted the consumer. 116 */ 117 void whenComplete(BiConsumer<Task, Throwable> whenCompleted); 118 } 119}