/* * Copyright (c) 2008-2017, Hazelcast, Inc. All Rights Reserved. * * 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.hazelcast.scheduledexecutor; import com.hazelcast.core.DistributedObject; import com.hazelcast.core.Member; import com.hazelcast.spi.annotation.Beta; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.concurrent.Callable; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; /** * Distributed & durable implementation similar to, but not directly inherited {@link ScheduledExecutorService}. * <code>IScheduledExecutorService</code> provides similar API to the <code>ScheduledExecutorService</code> with some * exceptions but also additional methods like scheduling tasks on a specific member, on a member who is owner of a specific key, * executing a tasks on multiple members etc. * *</p> * * Tasks (<tt>Runnable</tt> and/or <tt>Callable</tt>) scheduled on any partition through an <tt>IScheduledExecutorService</tt>, * yield some durability characteristics. * <ul> * <li>When a node goes down (up to <tt>durability</tt> config), the scheduled task will get re-scheduled * on a replica node.</li> * <li>In the event of a partition migration, the task will be re-scheduled on the destination node.</li> * </ul> * <b>Note: </b> The above characteristics don't apply when scheduled on a <tt>Member</tt>. * * <br/> * <br/> * * Tasks that are holding state that needs to be also durable across partitions, will need to implement the {@link StatefulTask} * interface. * * <br/> * <br/> * * Upon scheduling a task acquires a resource handler, see {@link ScheduledTaskHandler}. The handler is generated before * the actual scheduling of the task on the node, which allows for a way to access the future in an event of a node failure * immediately after scheduling, and also guarantees no duplicates in the cluster by utilising a unique name per task. * A name can also be defined by the user by having the <tt>Runnable</tt> or <tt>Callable</tt> implement the {@link NamedTask}. * Alternatively, one can wrap any task using the {@link TaskUtils#named(String, Callable)} or * {@link TaskUtils#named(String, Runnable)} for simplicity. * * <p/> * * One difference of this service in comparison to {@link ScheduledExecutorService} is the * {@link #scheduleAtFixedRate(Runnable, long, long, TimeUnit)} which has similar semantic * to {@link java.util.concurrent.ScheduledExecutorService#scheduleAtFixedRate(Runnable, long, long, TimeUnit)}. It * guarantees a task won't be executed by multiple threads concurrently. The difference is that this service will * skip a scheduled execution if another thread is still running the same task, instead of postponing its execution. * * <br/><br/> * The other difference is this service does not offer an equivalent of * {@link java.util.concurrent.ScheduledExecutorService#scheduleWithFixedDelay(Runnable, long, long, TimeUnit)} */ @Beta public interface IScheduledExecutorService extends DistributedObject { /** * Creates and executes a one-shot action that becomes enabled * after the given delay. * * @param command the task to execute * @param delay the time from now to delay execution * @param unit the time unit of the delay parameter * @return a ScheduledFuture representing pending completion of * the task and whose {@code get()} method will return * {@code null} upon completion * @throws RejectedExecutionException if the task cannot be * scheduled for execution * @throws NullPointerException if command is null */ IScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit); /** * Creates and executes a one-shot action that becomes enabled * after the given delay. * * @param command the task to execute * @param delay the time from now to delay execution * @param unit the time unit of the delay parameter * @return a ScheduledFuture representing pending completion of * the task and whose {@code get()} method will return * {@code null} upon completion * @throws RejectedExecutionException if the task cannot be * scheduled for execution * @throws NullPointerException if command is null */ <V> IScheduledFuture<V> schedule(Callable<V> command, long delay, TimeUnit unit); /** * Creates and executes a periodic action that becomes enabled first * after the given initial delay, and subsequently with the given * period. Executions will commence after * {@code initialDelay} then {@code initialDelay+period}, then * {@code initialDelay + 2 * period}, and so on. * If any execution of this task * takes longer than its period, then subsequent execution will be skipped. * * @param command the task to execute * @param initialDelay the time to delay first execution * @param period the period between successive executions * @param unit the time unit of the initialDelay and period parameters * @return a ScheduledFuture representing pending completion of * the task, and whose {@code get()} method will throw an * exception upon cancellation * @throws RejectedExecutionException if the task cannot be * scheduled for execution * @throws NullPointerException if command is null */ IScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit); /** * Creates and executes a one-shot action that becomes enabled * after the given delay at the given {@link Member}. * * @param command the task to execute * @param member the member to execute the task * @param delay the time from now to delay execution * @param unit the time unit of the delay parameter * @return a ScheduledFuture representing pending completion of * the task and whose {@code get()} method will return * {@code null} upon completion * @throws RejectedExecutionException if the task cannot be * scheduled for execution * @throws NullPointerException if command is null */ IScheduledFuture<?> scheduleOnMember(Runnable command, Member member, long delay, TimeUnit unit); /** * Creates and executes a one-shot action that becomes enabled * after the given delay at the given {@link Member}. * * @param command the task to execute * @param member the member to execute the task * @param delay the time from now to delay execution * @param unit the time unit of the delay parameter * @return a ScheduledFuture representing pending completion of * the task and whose {@code get()} method will return * {@code null} upon completion * @throws RejectedExecutionException if the task cannot be * scheduled for execution * @throws NullPointerException if command is null */ <V> IScheduledFuture<V> scheduleOnMember(Callable<V> command, Member member, long delay, TimeUnit unit); /** * Creates and executes a periodic action that becomes enabled first * after the given initial delay, and subsequently with the given * period at the given {@link Member}. Executions will commence after * {@code initialDelay} then {@code initialDelay+period}, then * {@code initialDelay + 2 * period}, and so on. * If any execution of this task * takes longer than its period, then subsequent execution will be skipped. * * @param command the task to execute * @param member the member to execute the task * @param initialDelay the time to delay first execution * @param period the period between successive executions * @param unit the time unit of the initialDelay and period parameters * @return a ScheduledFuture representing pending completion of * the task, and whose {@code get()} method will throw an * exception upon cancellation * @throws RejectedExecutionException if the task cannot be * scheduled for execution * @throws NullPointerException if command is null */ IScheduledFuture<?> scheduleOnMemberAtFixedRate(Runnable command, Member member, long initialDelay, long period, TimeUnit unit); /** * Creates and executes a one-shot action that becomes enabled * after the given delay on the partition owner of the given key. * * @param command the task to execute * @param key the key to identify the partition owner, which will execute the task * @param delay the time from now to delay execution * @param unit the time unit of the delay parameter * @return a ScheduledFuture representing pending completion of * the task and whose {@code get()} method will return * {@code null} upon completion * @throws RejectedExecutionException if the task cannot be * scheduled for execution * @throws NullPointerException if command is null */ IScheduledFuture<?> scheduleOnKeyOwner(Runnable command, Object key, long delay, TimeUnit unit); /** * Creates and executes a one-shot action that becomes enabled * after the given delay on the partition owner of the given key. * * @param command the task to execute * @param key the key to identify the partition owner, which will execute the task * @param delay the time from now to delay execution * @param unit the time unit of the delay parameter * @return a ScheduledFuture representing pending completion of * the task and whose {@code get()} method will return * {@code null} upon completion * @throws RejectedExecutionException if the task cannot be * scheduled for execution * @throws NullPointerException if command is null */ <V> IScheduledFuture<V> scheduleOnKeyOwner(Callable<V> command, Object key, long delay, TimeUnit unit); /** * Creates and executes a periodic action that becomes enabled first * after the given initial delay, and subsequently with the given * period on the partition owner of the given key. Executions will commence after * {@code initialDelay} then {@code initialDelay+period}, then * {@code initialDelay + 2 * period}, and so on. * If any execution of this task * takes longer than its period, then subsequent execution will be skipped. * * @param command the task to execute * @param key the key to identify the partition owner, which will execute the task * @param initialDelay the time to delay first execution * @param period the period between successive executions * @param unit the time unit of the initialDelay and period parameters * @return a ScheduledFuture representing pending completion of * the task, and whose {@code get()} method will throw an * exception upon cancellation * @throws RejectedExecutionException if the task cannot be * scheduled for execution * @throws NullPointerException if command is null */ IScheduledFuture<?> scheduleOnKeyOwnerAtFixedRate(Runnable command, Object key, long initialDelay, long period, TimeUnit unit); /** * Creates and executes a one-shot action that becomes enabled * after the given delay on all cluster {@link Member}s. * * <br/> * <b>Note: </b> In the event of Member leaving the cluster, for whatever reason, the task is lost. * If a new member is added, the task will not get scheduled there automatically. * * @param command the task to execute * @param delay the time from now to delay execution * @param unit the time unit of the delay parameter * @return a ScheduledFuture representing pending completion of * the task and whose {@code get()} method will return * {@code null} upon completion * @throws RejectedExecutionException if the task cannot be * scheduled for execution * @throws NullPointerException if command is null */ Map<Member, IScheduledFuture<?>> scheduleOnAllMembers(Runnable command, long delay, TimeUnit unit); /** * Creates and executes a one-shot action that becomes enabled * after the given delay on all cluster {@link Member}s. * * <br/> * <b>Note: </b> In the event of Member leaving the cluster, for whatever reason, the task is lost. * If a new member is added, the task will not get scheduled there automatically. * * @param command the task to execute * @param delay the time from now to delay execution * @param unit the time unit of the delay parameter * @return a ScheduledFuture representing pending completion of * the task and whose {@code get()} method will return * {@code null} upon completion * @throws RejectedExecutionException if the task cannot be * scheduled for execution * @throws NullPointerException if command is null */ <V> Map<Member, IScheduledFuture<V>> scheduleOnAllMembers(Callable<V> command, long delay, TimeUnit unit); /** * Creates and executes a periodic action that becomes enabled first * after the given initial delay, and subsequently with the given * period on all cluster {@link Member}s. Executions will commence after * {@code initialDelay} then {@code initialDelay+period}, then * {@code initialDelay + 2 * period}, and so on. * If any execution of this task * takes longer than its period, then subsequent execution will be skipped. * * <br/> * <b>Note: </b> In the event of Member leaving the cluster, for whatever reason, the task is lost. * If a new member is added, the task will not get scheduled there automatically. * * @param command the task to execute * @param initialDelay the time to delay first execution * @param period the period between successive executions * @param unit the time unit of the initialDelay and period parameters * @return a ScheduledFuture representing pending completion of * the task, and whose {@code get()} method will throw an * exception upon cancellation * @throws RejectedExecutionException if the task cannot be * scheduled for execution * @throws NullPointerException if command is null */ Map<Member, IScheduledFuture<?>> scheduleOnAllMembersAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit); /** * Creates and executes a one-shot action that becomes enabled * after the given delay on all {@link Member}s given. * * <br/> * <b>Note: </b> In the event of Member leaving the cluster, for whatever reason, the task is lost. * * @param command the task to execute * @param members the collections of members - where to execute the task * @param delay the time from now to delay execution * @param unit the time unit of the delay parameter * @return a ScheduledFuture representing pending completion of * the task and whose {@code get()} method will return * {@code null} upon completion * @throws RejectedExecutionException if the task cannot be * scheduled for execution * @throws NullPointerException if command is null */ Map<Member, IScheduledFuture<?>> scheduleOnMembers(Runnable command, Collection<Member> members, long delay, TimeUnit unit); /** * Creates and executes a one-shot action that becomes enabled * after the given delay on all {@link Member}s given. * * <br/> * <b>Note: </b> In the event of Member leaving the cluster, for whatever reason, the task is lost. * * @param command the task to execute * @param members the collections of members - where to execute the task * @param delay the time from now to delay execution * @param unit the time unit of the delay parameter * @return a ScheduledFuture representing pending completion of * the task and whose {@code get()} method will return * {@code null} upon completion * @throws RejectedExecutionException if the task cannot be * scheduled for execution * @throws NullPointerException if command is null */ <V> Map<Member, IScheduledFuture<V>> scheduleOnMembers(Callable<V> command, Collection<Member> members, long delay, TimeUnit unit); /** * Creates and executes a periodic action that becomes enabled first * after the given initial delay, and subsequently with the given * period on all {@link Member}s given. Executions will commence after * {@code initialDelay} then {@code initialDelay+period}, then * {@code initialDelay + 2 * period}, and so on. * If any execution of this task * takes longer than its period, then subsequent execution will be skipped. * * <br/> * <b>Note: </b> In the event of Member leaving the cluster, for whatever reason, the task is lost. * * @param command the task to execute * @param members the collections of members - where to execute the task * @param initialDelay the time to delay first execution * @param period the period between successive executions * @param unit the time unit of the initialDelay and period parameters * @return a ScheduledFuture representing pending completion of * the task, and whose {@code get()} method will throw an * exception upon cancellation * @throws RejectedExecutionException if the task cannot be * scheduled for execution * @throws NullPointerException if command is null */ Map<Member, IScheduledFuture<?>> scheduleOnMembersAtFixedRate(Runnable command, Collection<Member> members, long initialDelay, long period, TimeUnit unit); /** * Creates a new {@link IScheduledFuture} from the given handler. * This is useful in case your member node or client from which the original * scheduling happened, went down, and now you want to access the <tt>ScheduledFuture</tt> again. * * @param handler The handler of the task as found from {@link IScheduledFuture#getHandler()} * @param <V> The return type of callable tasks * @return A new {@link IScheduledFuture} from the given handler. */ <V> IScheduledFuture<V> getScheduledFuture(ScheduledTaskHandler handler); /** * Fetches and returns all scheduled (not disposed yet) futures from all members in the cluster. * If a member has no running tasks for this scheduler, it wont be included in the returned {@link Map}. * * @return A {@link Map} with {@link Member} keys and a List of {@link IScheduledFuture} found for this scheduler. */ <V> Map<Member, List<IScheduledFuture<V>>> getAllScheduledFutures(); /** * Initiates an orderly shutdown in which previously submitted * tasks are executed, but no new tasks will be accepted. * Invocation has no additional effect if already shut down. * * <p>This method does not wait for previously submitted tasks to * complete execution. */ void shutdown(); }