38c1238cc82528f95af483b2ad90545aceb8bae3
[appc.git] / appc-adapters / appc-rest-adapter / appc-rest-adapter-bundle / src / main / java / org / openecomp / appc / adapter / rest / impl / RequestContext.java
1 /*-
2  * ============LICENSE_START=======================================================
3  * ONAP : APPC
4  * ================================================================================
5  * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6  * ================================================================================
7  * Copyright (C) 2017 Amdocs
8  * =============================================================================
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  * 
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  * 
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  * 
21  * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22  * ============LICENSE_END=========================================================
23  */
24
25
26
27 package org.openecomp.appc.adapter.rest.impl;
28
29 import org.openecomp.appc.Constants;
30 import org.openecomp.appc.configuration.Configuration;
31 import org.openecomp.appc.configuration.ConfigurationFactory;
32 import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
33
34 /**
35  * This class is used to track and maintain recovery and time-to-live information for a request as it is being
36  * processed.
37  */
38 public class RequestContext {
39     /**
40      * The number of seconds of wait time between successive attempts to connect to the provider. This is used to
41      * recover from provider outages or failures. It is not used to recover from logical errors, such as an invalid
42      * request, server not found, etc.
43      */
44     private Integer retryDelay;
45
46     /**
47      * The number of times we will attempt to connect to the provider. This is used to recover from provider outages or
48      * failures. It is not used to recover from logical errors, such as an invalid request, server not found, etc.
49      */
50     private Integer retryLimit;
51
52     /**
53      * The total time, in milliseconds, that the provider can have to process this request. If the accumulated time
54      * exceeds the time to live, then the request is failed with a timeout exception, regardless of the state of the
55      * provider. Note that the caller may supply this as a value in seconds, in which case it must be converted to
56      * milliseconds for the request context.
57      */
58     private Long timeToLive;
59
60     /**
61      * The accumulated time, in milliseconds, that has been used so far to process the request. This is compared to the
62      * time to live each time it is updated. If the accumulated time exceeds the time to live, then the request is
63      * failed with a timeout exception, regardless of the state of the provider.
64      */
65     private long accumulatedTime;
66
67     /**
68      * The total number of retries attempted so far
69      */
70     private int attempt;
71
72     /**
73      * The time when the stopwatch was started
74      */
75     private long startTime = -1;
76
77     /**
78      * The service logic (DG) context from the SLI
79      */
80     private SvcLogicContext svcLogicContext;
81
82     /**
83      * The configuration
84      */
85     private Configuration configuration = ConfigurationFactory.getConfiguration();
86
87     /**
88      * Set to true whenever the retry limit has been exceeded, reset to false when reset() is called.
89      */
90     private boolean retryFailed;
91
92     /**
93      * Creates the request context
94      * 
95      * @param context
96      *            The service logic (SLI) context associated with the current DG
97      */
98     public RequestContext(SvcLogicContext context) {
99         setSvcLogicContext(context);
100     }
101
102     /**
103      * @return The retry delay, in seconds. If zero, then no retry is to be performed
104      */
105     public int getRetryDelay() {
106         if (retryDelay == null) {
107             int value = configuration.getIntegerProperty(Constants.PROPERTY_RETRY_DELAY);
108             retryDelay = Integer.valueOf(value);
109         }
110
111         return retryDelay.intValue();
112     }
113
114     /**
115      * This method is a helper that allows the caller to delay for the retry interval time and not have to handle the
116      * thread interruption, timer handling, etc.
117      */
118     public void delay() {
119         long time = getRetryDelay() * 1000L;
120         long future = System.currentTimeMillis() + time;
121         if (time != 0) {
122             while (System.currentTimeMillis() < future && time > 0) {
123                 try {
124                     Thread.sleep(time);
125                 } catch (InterruptedException e) {
126                     /*
127                      * This is rare, but it can happen if another thread interrupts us while we are sleeping. In that
128                      * case, the thread is resumed before the delay time has actually expired, so re-calculate the
129                      * amount of delay time needed and reenter the sleep until we get to the future time.
130                      */
131                     time = future - System.currentTimeMillis();
132                 }
133             }
134         }
135     }
136
137     /**
138      * @return The number of retries that are allowed per connection
139      */
140     public int getRetryLimit() {
141         if (retryLimit == null) {
142             int value = configuration.getIntegerProperty(Constants.PROPERTY_RETRY_LIMIT);
143             retryLimit = Integer.valueOf(value);
144         }
145
146         return retryLimit.intValue();
147     }
148
149     /**
150      * Check and count the connection attempt.
151      * 
152      * @return True if the connection should be attempted. False indicates that the number of retries has been exhausted
153      *         and it should NOT be attempted.
154      */
155     public boolean attempt() {
156         if (retryFailed || attempt >= getRetryLimit()) {
157             retryFailed = true;
158             return false;
159         }
160         attempt++;
161
162         return true;
163     }
164
165     /**
166      * @return The number of retry attempts so far
167      */
168     public int getAttempts() {
169         return attempt;
170     }
171
172     /**
173      * @return True if the retry limit has been exceeded, false otherwise
174      */
175     public boolean isFailed() {
176         return retryFailed;
177     }
178
179     /**
180      * This method both checks the time to live to see if it has been exceeded and accumulates the total time used so
181      * far.
182      * <p>
183      * Each time this method is called it accumulates the total duration since the last time it was called to the total
184      * time accumulator. It then checks the total time to the time to live and if greater, it returns false. As long as
185      * the total time used is less than or equal to the time to live limit, the method returns true. It is important to
186      * call this method at the very beginning of the process so that all parts of the process are tracked.
187      * </p>
188      * 
189      * @return True if the total time to live has not been exceeded. False indicates that the total time to live has
190      *         been exceeded and no further processing should be performed.
191      */
192     public boolean isAlive() {
193         long now = System.currentTimeMillis();
194         if (startTime == -1) {
195             startTime = now;
196             return true;
197         }
198         accumulatedTime += (now - startTime);
199         startTime = now;
200         if (accumulatedTime > timeToLive) {
201             return false;
202         }
203         return true;
204     }
205
206     /**
207      * @return The total amount of time used, in milliseconds.
208      */
209     public long getTotalDuration() {
210         return accumulatedTime;
211     }
212
213     /**
214      * This method is called to reset the retry counters. It has no effect on the time to live accumulator.
215      */
216     public void reset() {
217         attempt = 0;
218     }
219
220     /**
221      * Sets the time to live to the value, expressed in seconds
222      * 
223      * @param time
224      *            The time to live, in seconds
225      */
226     public void setTimeToLiveSeconds(int time) {
227         setTimeToLiveMS(time * 1000L);
228     }
229
230     /**
231      * Sets the time to live to the value, expressed in milliseconds
232      * 
233      * @param time
234      *            The time to live, in milliseconds
235      */
236     public void setTimeToLiveMS(long time) {
237         this.timeToLive = time;
238     }
239
240     /**
241      * @return The service logic context associated with this request
242      */
243     public SvcLogicContext getSvcLogicContext() {
244         return svcLogicContext;
245     }
246
247     /**
248      * @param svcLogicContext
249      *            The service logic context to be associated with this request
250      */
251     public void setSvcLogicContext(SvcLogicContext svcLogicContext) {
252         this.svcLogicContext = svcLogicContext;
253     }
254 }