001/*
002 * (C) Copyright 2012-2018 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;
020
021import java.util.UUID;
022import java.util.concurrent.atomic.AtomicInteger;
023
024/**
025 * Simple work that just sleeps, mostly used for tests.
026 */
027public class SleepWork extends AbstractWork {
028
029    public static final String CATEGORY = "SleepWork";
030
031    private static final long serialVersionUID = 1L;
032
033    protected long durationMillis;
034
035    protected String category;
036
037    protected AtomicInteger count = new AtomicInteger();
038
039    protected String partitionKey;
040
041    protected boolean idempotent = true;
042
043    protected boolean coalescing = false;
044
045    /**
046     * Creates a work instance that does nothing but sleep.
047     *
048     * @param durationMillis the sleep duration
049     * @since 10.2
050     */
051    public SleepWork(long durationMillis, String category, String id) {
052        super(id);
053        this.durationMillis = durationMillis;
054        this.category = category;
055        partitionKey = String.valueOf(count.incrementAndGet());
056        setProgress(Progress.PROGRESS_0_PC);
057    }
058
059    /**
060     * @since 10.2
061     */
062    public SleepWork(long durationMillis, String id) {
063        this(durationMillis, CATEGORY, id);
064    }
065
066    /**
067     * @since 10.2
068     */
069    public SleepWork(long durationMillis) {
070        this(durationMillis, CATEGORY, UUID.randomUUID().toString());
071    }
072
073    /**
074     * If debug is true, then the various debug* methods must be called in the proper order for the work to start and
075     * stop: {@link #debugStart}, {@link #debugFinish}.
076     *
077     * @param durationMillis the sleep duration
078     * @param debug {@code true} for debug
079     * @deprecated since 10.2 debug flag is unused
080     */
081    @Deprecated
082    public SleepWork(long durationMillis, boolean debug) {
083        this(durationMillis, null, CATEGORY);
084    }
085
086    /**
087     * @deprecated since 10.2 debug flag is unused
088     */
089    @Deprecated
090    public SleepWork(long durationMillis, boolean debug, String id) {
091        this(durationMillis, null, id);
092    }
093
094    /**
095     * @deprecated since 10.2 debug flag is unused
096     */
097    @Deprecated
098    public SleepWork(long durationMillis, String category, boolean debug) {
099        this(durationMillis, category, CATEGORY);
100    }
101
102    /**
103     * @deprecated since 10.2 debug flag is unused
104     */
105    @Deprecated
106    public SleepWork(long durationMillis, String category, boolean debug, String id) {
107        this(durationMillis, category, id);
108    }
109
110    @Override
111    public String getCategory() {
112        return category;
113    }
114
115    @Override
116    public String getTitle() {
117        return "Sleep " + durationMillis + " ms";
118    }
119
120    @Override
121    public void work() {
122        try {
123            doWork();
124        } catch (InterruptedException e) {
125            Thread.currentThread().interrupt();
126            throw new RuntimeException(e);
127        }
128    }
129
130    protected void doWork() throws InterruptedException {
131        for (;;) {
132            long elapsed = System.currentTimeMillis() - getStartTime();
133            if (elapsed > durationMillis) {
134                break;
135            }
136            setProgress(new Progress(100F * elapsed / durationMillis));
137
138            if (isSuspending()) {
139                durationMillis -= elapsed; // save state
140                suspended();
141                return;
142            }
143
144            if (WorkStateHelper.isCanceled(getId())) {
145                durationMillis -= elapsed; // save state
146                return;
147            }
148
149            Thread.sleep(10);
150        }
151
152    }
153
154    @Override
155    public String getPartitionKey() {
156        return partitionKey;
157    }
158
159    @Override
160    public boolean isIdempotent() {
161        return idempotent;
162    }
163
164    public void setIdempotent(boolean idempotent) {
165        this.idempotent = idempotent;
166    }
167
168    @Override
169    public boolean isCoalescing() {
170        return coalescing;
171    }
172
173    public void setCoalescing(boolean coalescing) {
174        this.coalescing = coalescing;
175    }
176
177    @Override
178    public String toString() {
179        return getClass().getSimpleName() + "(" + (getId().length() > 10 ? "" : getId() + ", ") + durationMillis
180                + "ms, " + getProgress() + ")";
181    }
182
183}