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     * Schedules work for execution at a later time.
079     * <p>
080     * This method is identical to {@link #schedule(Work, boolean)} with {@code afterCommit = false}.
081     *
082     * @param work the work to execute
083     */
084    void schedule(Work work);
085
086    /**
087     * Schedules work for execution at a later time, after the current transaction (if any) has committed.
088     *
089     * @param work the work to execute
090     * @param afterCommit if {@code true} and the work is scheduled, it will only be run after the current transaction
091     *            (if any) has committed
092     */
093    void schedule(Work work, boolean afterCommit);
094
095    /**
096     * Schedules work for execution at a later time, with a specific {@linkplain Scheduling scheduling} policy.
097     * <p>
098     * This method is identical to {@link #schedule(Work, Scheduling, boolean)} with {@code afterCommit = false}.
099     *
100     * @param work the work to execute
101     * @param scheduling the scheduling policy
102     * @see #schedule(Work)
103     */
104    void schedule(Work work, Scheduling scheduling);
105
106    /**
107     * Schedules work for execution at a later time, with a specific {@linkplain Scheduling scheduling} policy.
108     *
109     * @param work the work to execute
110     * @param scheduling the scheduling policy
111     * @param afterCommit if {@code true} and the work is scheduled, it will only be run after the current transaction
112     *            (if any) has committed
113     * @see #schedule(Work)
114     */
115    void schedule(Work work, Scheduling scheduling, boolean afterCommit);
116
117    /** Admin API **/
118    /**
119     * Lists the ids of the existing work queues.
120     *
121     * @return the list of queue ids
122     */
123    List<String> getWorkQueueIds();
124
125    /**
126     * Gets the queue id used for a given work category.
127     *
128     * @param category the category
129     * @return the queue id
130     */
131    String getCategoryQueueId(String category);
132
133    /**
134     * Gets the work queue descriptor for a given queue id.
135     *
136     * @param queueId the queue id
137     * @return the work queue descriptor, or {@code null}
138     */
139    WorkQueueDescriptor getWorkQueueDescriptor(String queueId);
140
141
142    /**
143     * Is processing enabled for at least one queue
144     *
145     * @param queueId
146     *
147     * @since 8.3
148     */
149    boolean isProcessingEnabled();
150
151    /**
152     * Set processing for all queues
153     *
154     * @param queueId
155     *
156     * @since 8.3
157     */
158
159    void enableProcessing(boolean value);
160
161    /**
162     * Is processing enabled for a given queue id.
163     *
164     * @param queueId
165     *
166     * @since 8.3
167     */
168    boolean isProcessingEnabled(String queueId);
169
170    /**
171     * Set processing for a given queue id.
172     *
173     * @param queueId
174     * @throws InterruptedException
175     *
176     * @since 8.3
177     */
178    void enableProcessing(String queueId, boolean value) throws InterruptedException;
179
180    /**
181     * Is queuing enabled for a given queue id.
182     *
183     * @param queueId
184     *
185     * @since 8.3
186     */
187    boolean isQueuingEnabled(String queueId);
188
189    /**
190     * Starts up this {@link WorkManager} and attempts to resume work previously suspended and saved at
191     * {@link #shutdown} time.
192     */
193    void init();
194
195    /**
196     * Shuts down a work queue and attempts to suspend and save the running and scheduled work instances.
197     *
198     * @param queueId the queue id
199     * @param timeout the time to wait
200     * @param unit the timeout unit
201     * @return {@code true} if shutdown is done, {@code false} if there are still some threads executing after the
202     *         timeout
203     */
204    boolean shutdownQueue(String queueId, long timeout, TimeUnit unit) throws InterruptedException;
205
206    /**
207     * Shuts down this {@link WorkManager} and attempts to suspend and save the running and scheduled work instances.
208     *
209     * @param timeout the time to wait
210     * @param unit the timeout unit
211     * @return {@code true} if shutdown is done, {@code false} if there are still some threads executing after the
212     *         timeout
213     */
214    boolean shutdown(long timeout, TimeUnit unit) throws InterruptedException;
215
216
217
218    /**
219     * Gets the number of work instances in a given queue in a defined state.
220     * <p>
221     *
222     * @param queueId the queue id
223     * @param state the state defining the state to look into, {@link State#SCHEDULED SCHEDULED}, {@link State#RUNNING
224     *            RUNNING}, {@link State#COMPLETED COMPLETED}, or {@code null} for non-completed (
225     *            {@link State#SCHEDULED SCHEDULED} or {@link State#RUNNING RUNNING})
226     * @return the number of work instances in the given state
227     * @since 5.8
228     * @deprecated since 5.8,
229     */
230    @Deprecated
231    int getQueueSize(String queueId, State state);
232
233    /**
234     * Gets the size of the non-completed work (scheduled + running) for a give queue.
235     *
236     * @param queueId the queue id
237     * @return the number of non-completed work instances
238     * @deprecated since 5.8, use {@link #getQueueSize} with {@code null} state instead
239     */
240    @Deprecated
241    int getNonCompletedWorkSize(String queueId);
242
243    /**
244     * Gets the metrics for the {@code queueId}
245     *
246     * @since 8.3
247     */
248    WorkQueueMetrics getMetrics(String queueId);
249
250    /**
251     * Waits for completion of work in a given queue.
252     *
253     * @param queueId the queue id
254     * @param timeout the time to wait
255     * @param unit the timeout unit
256     * @return {@code true} if all work completed in the queue, or {@code false} if there is still some non-completed
257     *         work after the timeout
258     */
259    boolean awaitCompletion(String queueId, long timeout, TimeUnit unit) throws InterruptedException;
260
261    /**
262     * Waits for completion of all work.
263     *
264     * @param timeout the time to wait
265     * @param unit the timeout unit
266     * @return {@code true} if all work completed, or {@code false} if there is still some non-completed work after the
267     *         timeout
268     */
269    boolean awaitCompletion(long timeout, TimeUnit unit) throws InterruptedException;
270
271    /**
272     * @return {@code true} if active
273     * @see org.nuxeo.runtime.model.DefaultComponent#applicationStarted(org.nuxeo.runtime.model.ComponentContext)
274     * @see #init()
275     * @see #shutdown(long, TimeUnit)
276     * @since 6.0
277     */
278    boolean isStarted();
279
280    /** Works lookup API **/
281    /**
282     * Gets the state in which a work instance is.
283     * <p>
284     * This can be {@link State#SCHEDULED SCHEDULED}, {@link State#RUNNING RUNNING}, or null.
285     *
286     * @param workId the id of the work to find
287     * @return the work state, or {@code null} if not found
288     * @since 5.8
289     */
290    @Deprecated
291    State getWorkState(String workId);
292
293    /**
294     * Finds a work instance.
295     *
296     * @param work the work to find
297     * @param state the state defining the state to look into, {@link State#SCHEDULED SCHEDULED}, {@link State#RUNNING
298     *            RUNNING}, {@link State#COMPLETED COMPLETED}, or {@code null} for non-completed
299     * @param useEquals ignored, always uses work id equality
300     * @param pos ignored, pass null
301     * @return the found work instance, or {@code null} if not found
302     * @deprecated since 5.8, use {@link #getWorkState} instead
303     */
304    @Deprecated
305    Work find(Work work, State state, boolean useEquals, int[] pos);
306
307    /**
308     * Finds a work instance.
309     *
310     * @param workId the id of the work to find
311     * @param state the state defining the state to look into, {@link State#SCHEDULED SCHEDULED}, {@link State#RUNNING
312     *            RUNNING},  or {@code null} for non-completed
313     * @return the found work instance, or {@code null} if not found
314     * @since 7.3
315     */
316    Work find(String workId, State state);
317
318
319    /**
320     * Lists the work instances in a given queue in a defined state.
321     *
322     * @param queueId the queue id
323     * @param state the state defining the state to look into, {@link State#SCHEDULED SCHEDULED}, {@link State#RUNNING
324     *            RUNNING}, or {@code null} for non-completed
325     * @return the list of work instances in the given state
326     */
327    List<Work> listWork(String queueId, State state);
328
329    /**
330     * Lists the work ids in a given queue in a defined state.
331     *
332     * @param queueId the queue id
333     * @param state the state defining the state to look into, {@link State#SCHEDULED SCHEDULED}, {@link State#RUNNING
334     *            RUNNING}, or {@code null} for non-completed
335     * @return the list of work ids in the given state
336     * @since 5.8
337     */
338    List<String> listWorkIds(String queueId, State state);
339
340}