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