001/*
002 * Copyright 2006-2007 the original author or authors.
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 *      https://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
017package org.springframework.batch.repeat.policy;
018
019import org.springframework.batch.repeat.RepeatContext;
020import org.springframework.batch.repeat.context.RepeatContextSupport;
021
022/**
023 * Termination policy that times out after a fixed period. Allows graceful exit
024 * from a batch if the latest result comes in after the timeout expires (i.e.
025 * does not throw a timeout exception).<br>
026 * 
027 * N.B. It may often be the case that the batch governed by this policy will be
028 * transactional, and the transaction might have its own timeout. In this case
029 * the transaction might throw a timeout exception on commit if its timeout
030 * threshold is lower than the termination policy.
031 * 
032 * @author Dave Syer
033 * 
034 */
035public class TimeoutTerminationPolicy extends CompletionPolicySupport {
036
037        /**
038         * Default timeout value in milliseconds (the value equivalent to 30 seconds).
039         */
040        public static final long DEFAULT_TIMEOUT = 30000L;
041
042        private long timeout = DEFAULT_TIMEOUT;
043
044        /**
045         * Default constructor.
046         */
047        public TimeoutTerminationPolicy() {
048                super();
049        }
050
051        /**
052         * Construct a {@link TimeoutTerminationPolicy} with the specified timeout
053         * value (in milliseconds).
054         * 
055         * @param timeout duration of the timeout.
056         */
057        public TimeoutTerminationPolicy(long timeout) {
058                super();
059                this.timeout = timeout;
060        }
061
062        /**
063         * Check the timeout and complete gracefully if it has expires.
064         * 
065         * @see org.springframework.batch.repeat.CompletionPolicy#isComplete(org.springframework.batch.repeat.RepeatContext)
066         */
067        @Override
068        public boolean isComplete(RepeatContext context) {
069                return ((TimeoutBatchContext) context).isComplete();
070        }
071
072        /**
073         * Start the clock on the timeout.
074         * 
075         * @see org.springframework.batch.repeat.CompletionPolicy#start(RepeatContext)
076         */
077        @Override
078        public RepeatContext start(RepeatContext context) {
079                return new TimeoutBatchContext(context);
080        }
081
082        protected class TimeoutBatchContext extends RepeatContextSupport {
083
084                private volatile long time = System.currentTimeMillis();
085
086                private final long timeout = TimeoutTerminationPolicy.this.timeout;
087
088                public TimeoutBatchContext(RepeatContext context) {
089                        super(context);
090                }
091
092                public boolean isComplete() {
093                        return (System.currentTimeMillis() - time) > timeout;
094                }
095
096        }
097
098}