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.io.Closeable;
020import java.util.Collections;
021import java.util.Set;
022import java.util.concurrent.CopyOnWriteArraySet;
023import java.util.concurrent.ScheduledExecutorService;
024import java.util.concurrent.TimeUnit;
025
026import org.apache.camel.util.function.ThrowingFunction;
027
028/**
029 * A simple timer utility that use a linked {@link BackOff} to determine when a task should be executed.
030 */
031public class SimpleBackOffTimer implements BackOffTimer, Closeable {
032    private final ScheduledExecutorService scheduler;
033    private final String name;
034    private final Set<BackOffTimerTask> tasks = new CopyOnWriteArraySet<>();
035
036    public SimpleBackOffTimer(ScheduledExecutorService scheduler) {
037        this("SimpleBackOffTimer", scheduler);
038    }
039
040    public SimpleBackOffTimer(String name, ScheduledExecutorService scheduler) {
041        this.name = name;
042        this.scheduler = scheduler;
043    }
044
045    /**
046     * Schedule the given function/task to be executed some time in the future according to the given backOff.
047     */
048    public Task schedule(BackOff backOff, ThrowingFunction<Task, Boolean, Exception> function) {
049        final BackOffTimerTask task = new BackOffTimerTask(this, backOff, scheduler, function);
050
051        long delay = task.next();
052        if (delay != BackOff.NEVER) {
053            tasks.add(task);
054            scheduler.schedule(task, delay, TimeUnit.MILLISECONDS);
055        } else {
056            task.cancel();
057        }
058
059        return task;
060    }
061
062    /**
063     * Gets the name of this timer.
064     */
065    public String getName() {
066        return name;
067    }
068
069    /**
070     * Removes the task
071     */
072    public void remove(Task task) {
073        tasks.remove(task);
074    }
075
076    /**
077     * Access to unmodifiable set of all the tasks
078     */
079    public Set<Task> getTasks() {
080        return Collections.unmodifiableSet(tasks);
081    }
082
083    /**
084     * Number of tasks
085     */
086    public int size() {
087        return tasks.size();
088    }
089
090    /**
091     * Stops and closes this timer.
092     */
093    public void close() {
094        tasks.clear();
095    }
096}