001/*
002 * (C) Copyright 2012-2014 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Florent Guillaume
018 */
019package org.nuxeo.ecm.core.work.api;
020
021import java.util.List;
022import java.util.concurrent.TimeUnit;
023
024import org.nuxeo.ecm.core.work.api.Work.State;
025
026/**
027 * A {@link WorkManager} executes {@link Work} instances asynchronously.
028 * <p>
029 * A {@link Work} can be scheduled by calling {@link #schedule}.
030 * <p>
031 * Work is executed in a thread pool and a work queue that depends on the work's category.
032 *
033 * @since 5.6
034 */
035public interface WorkManager {
036
037    /**
038     * The scheduling policy to use when adding a work instance using {@link #schedule(Work, Scheduling)}.
039     */
040    enum Scheduling {
041        /**
042         * Always schedule the work.
043         */
044        ENQUEUE,
045        /**
046         * Any other scheduled work equals to this one is removed from scheduling and canceled first, before this work
047         * is scheduled.
048         */
049        CANCEL_SCHEDULED,
050        /**
051         * If there is a scheduled work equals to this one, then don't schedule the work.
052         */
053        IF_NOT_SCHEDULED(State.SCHEDULED),
054        /**
055         * If there is a running work equals to this one, then don't schedule the work.
056         *
057         * @deprecated unused
058         */
059        @Deprecated
060        IF_NOT_RUNNING(State.RUNNING),
061        /**
062         * If there is a running or scheduled work equals to this one, then don't schedule the work.
063         */
064        IF_NOT_RUNNING_OR_SCHEDULED;
065
066        public final State state;
067
068        private Scheduling() {
069            state = null;
070        }
071
072        private Scheduling(State state) {
073            this.state = state;
074        }
075    }
076
077    /**
078     * Lists the ids of the existing work queues.
079     *
080     * @return the list of queue ids
081     */
082    List<String> getWorkQueueIds();
083
084    /**
085     * Gets the queue id used for a given work category.
086     *
087     * @param category the category
088     * @return the queue id
089     */
090    String getCategoryQueueId(String category);
091
092    /**
093     * Gets the work queue descriptor for a given queue id.
094     *
095     * @param queueId the queue id
096     * @return the work queue descriptor, or {@code null}
097     */
098    WorkQueueDescriptor getWorkQueueDescriptor(String queueId);
099
100    /**
101     * Starts up this {@link WorkManager} and attempts to resume work previously suspended and saved at
102     * {@link #shutdown} time.
103     */
104    void init();
105
106    /**
107     * Shuts down a work queue and attempts to suspend and save the running and scheduled work instances.
108     *
109     * @param queueId the queue id
110     * @param timeout the time to wait
111     * @param unit the timeout unit
112     * @return {@code true} if shutdown is done, {@code false} if there are still some threads executing after the
113     *         timeout
114     */
115    boolean shutdownQueue(String queueId, long timeout, TimeUnit unit) throws InterruptedException;
116
117    /**
118     * Shuts down this {@link WorkManager} and attempts to suspend and save the running and scheduled work instances.
119     *
120     * @param timeout the time to wait
121     * @param unit the timeout unit
122     * @return {@code true} if shutdown is done, {@code false} if there are still some threads executing after the
123     *         timeout
124     */
125    boolean shutdown(long timeout, TimeUnit unit) throws InterruptedException;
126
127    /**
128     * Schedules work for execution at a later time.
129     * <p>
130     * This method is identical to {@link #schedule(Work, boolean)} with {@code afterCommit = false}.
131     *
132     * @param work the work to execute
133     */
134    void schedule(Work work);
135
136    /**
137     * Schedules work for execution at a later time, after the current transaction (if any) has committed.
138     *
139     * @param work the work to execute
140     * @param afterCommit if {@code true} and the work is scheduled, it will only be run after the current transaction
141     *            (if any) has committed
142     */
143    void schedule(Work work, boolean afterCommit);
144
145    /**
146     * Schedules work for execution at a later time, with a specific {@linkplain Scheduling scheduling} policy.
147     * <p>
148     * This method is identical to {@link #schedule(Work, Scheduling, boolean)} with {@code afterCommit = false}.
149     *
150     * @param work the work to execute
151     * @param scheduling the scheduling policy
152     * @see #schedule(Work)
153     */
154    void schedule(Work work, Scheduling scheduling);
155
156    /**
157     * Schedules work for execution at a later time, with a specific {@linkplain Scheduling scheduling} policy.
158     *
159     * @param work the work to execute
160     * @param scheduling the scheduling policy
161     * @param afterCommit if {@code true} and the work is scheduled, it will only be run after the current transaction
162     *            (if any) has committed
163     * @see #schedule(Work)
164     */
165    void schedule(Work work, Scheduling scheduling, boolean afterCommit);
166
167    /**
168     * Finds a work instance.
169     *
170     * @param work the work to find
171     * @param state the state defining the state to look into, {@link State#SCHEDULED SCHEDULED}, {@link State#RUNNING
172     *            RUNNING}, {@link State#COMPLETED COMPLETED}, or {@code null} for non-completed
173     * @param useEquals ignored, always uses work id equality
174     * @param pos ignored, pass null
175     * @return the found work instance, or {@code null} if not found
176     * @deprecated since 5.8, use {@link #getWorkState} instead
177     */
178    @Deprecated
179    Work find(Work work, State state, boolean useEquals, int[] pos);
180
181    /**
182     * Finds a work instance.
183     *
184     * @param workId the id of the work to find
185     * @param state the state defining the state to look into, {@link State#SCHEDULED SCHEDULED}, {@link State#RUNNING
186     *            RUNNING}, {@link State#COMPLETED COMPLETED}, or {@code null} for non-completed
187     * @return the found work instance, or {@code null} if not found
188     * @since 7.3
189     */
190    Work find(String workId, State state);
191
192    /**
193     * Finds a work result.
194     *
195     * @param workId the id of the work to find the result
196     * @return the found work result, or {@code null} if there is no result or if work is not {@link State#COMPLETED
197     *         COMPLETED}
198     * @since 7.4
199     */
200    String findResult(String workId);
201
202    /**
203     * Gets the state in which a work instance is.
204     * <p>
205     * This can be {@link State#SCHEDULED SCHEDULED}, {@link State#RUNNING RUNNING}, {@link State#COMPLETED COMPLETED},
206     * {@link State#CANCELED} or {@link State#FAILED}.
207     *
208     * @param workId the id of the work to find
209     * @return the work state, or {@code null} if not found
210     * @since 5.8
211     */
212    State getWorkState(String workId);
213
214    /**
215     * Lists the work instances in a given queue in a defined state.
216     *
217     * @param queueId the queue id
218     * @param state the state defining the state to look into, {@link State#SCHEDULED SCHEDULED}, {@link State#RUNNING
219     *            RUNNING}, {@link State#COMPLETED COMPLETED}, or {@code null} for non-completed
220     * @return the list of work instances in the given state
221     */
222    List<Work> listWork(String queueId, State state);
223
224    /**
225     * Lists the work ids in a given queue in a defined state.
226     *
227     * @param queueId the queue id
228     * @param state the state defining the state to look into, {@link State#SCHEDULED SCHEDULED}, {@link State#RUNNING
229     *            RUNNING}, {@link State#COMPLETED COMPLETED}, or {@code null} for non-completed
230     * @return the list of work ids in the given state
231     * @since 5.8
232     */
233    List<String> listWorkIds(String queueId, State state);
234
235    /**
236     * Gets the number of work instances in a given queue in a defined state.
237     * <p>
238     *
239     * @param queueId the queue id
240     * @param state the state defining the state to look into, {@link State#SCHEDULED SCHEDULED}, {@link State#RUNNING
241     *            RUNNING}, {@link State#COMPLETED COMPLETED}, or {@code null} for non-completed (
242     *            {@link State#SCHEDULED SCHEDULED} or {@link State#RUNNING RUNNING})
243     * @return the number of work instances in the given state
244     * @since 5.8
245     */
246    int getQueueSize(String queueId, State state);
247
248    /**
249     * Gets the size of the non-completed work (scheduled + running) for a give queue.
250     *
251     * @param queueId the queue id
252     * @return the number of non-completed work instances
253     * @deprecated since 5.8, use {@link #getQueueSize} with {@code null} state instead
254     */
255    @Deprecated
256    int getNonCompletedWorkSize(String queueId);
257
258    /**
259     * Waits for completion of work in a given queue.
260     *
261     * @param queueId the queue id
262     * @param timeout the time to wait
263     * @param unit the timeout unit
264     * @return {@code true} if all work completed in the queue, or {@code false} if there is still some non-completed
265     *         work after the timeout
266     */
267    boolean awaitCompletion(String queueId, long timeout, TimeUnit unit) throws InterruptedException;
268
269    /**
270     * Waits for completion of all work.
271     *
272     * @param timeout the time to wait
273     * @param unit the timeout unit
274     * @return {@code true} if all work completed, or {@code false} if there is still some non-completed work after the
275     *         timeout
276     */
277    boolean awaitCompletion(long timeout, TimeUnit unit) throws InterruptedException;
278
279    /**
280     * Clears the list of completed work instances for a given queue.
281     *
282     * @param queueId the queue id
283     */
284    void clearCompletedWork(String queueId);
285
286    /**
287     * Clears the list of completed work instances older than the given time.
288     *
289     * @param completionTime the completion time (milliseconds since epoch) before which completed work instances are
290     *            cleared, or {@code 0} for all
291     */
292    void clearCompletedWork(long completionTime);
293
294    /**
295     * Clears the list of completed work instances older than what's configured for each queue.
296     */
297    void cleanup();
298
299    /**
300     * @return {@code true} if active
301     * @see org.nuxeo.runtime.model.DefaultComponent#applicationStarted(org.nuxeo.runtime.model.ComponentContext)
302     * @see #init()
303     * @see #shutdown(long, TimeUnit)
304     * @since 6.0
305     */
306    boolean isStarted();
307
308}