1   /*
2    * Copyright 2018 LINE Corporation
3    *
4    * LINE Corporation licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package com.linecorp.centraldogma.internal.api.v1;
17  
18  import static com.google.common.base.Preconditions.checkArgument;
19  
20  import java.util.concurrent.TimeUnit;
21  
22  /**
23   * A utility class which provides constants and methods related to watch timeout.
24   */
25  public final class WatchTimeout {
26      /**
27       * The maximum timeout duration, in milliseconds.
28       */
29      public static final long MAX_MILLIS = TimeUnit.DAYS.toMillis(1);
30  
31      /**
32       * Returns an available timeout duration for a watch request with limitation of max timeout.
33       *
34       * <p>For example:
35       * <pre>{@code
36       * assert WatchTimeout.availableTimeout(1000) == 1000;
37       * // Limit max timeout duration
38       * assert WatchTimeout.availableTimeout(Long.MAX_VALUE) == WatchTimeout.MAX_MILLIS;
39       * }</pre>
40       *
41       * @param expectedTimeoutMillis timeout duration that a user wants to use, in milliseconds
42       * @return timeout duration in milliseconds, between 1 and the {@link #MAX_MILLIS}.
43       */
44      public static long availableTimeout(long expectedTimeoutMillis) {
45          return availableTimeout(expectedTimeoutMillis, 0);
46      }
47  
48      /**
49       * Returns an available timeout duration for a watch request.
50       * This method subtracts {@code currentTimeoutMillis} from {@code expectedTimeoutMills}
51       * with limitation of max timeout.
52       *
53       * <p>For example:
54       * <pre>{@code
55       * assert WatchTimeout.availableTimeout(1000, 100) == 1000;
56       * assert WatchTimeout.availableTimeout(1000, 0) == 1000;
57       * // Limit max timeout duration
58       * assert WatchTimeout.availableTimeout(Long.MAX_VALUE, 1000) == WatchTimeout.MAX_MILLIS - 1000;
59       * }</pre>
60       *
61       * @param expectedTimeoutMillis timeout duration that a user wants to use, in milliseconds
62       * @param currentTimeoutMillis timeout duration that is currently used, in milliseconds
63       * @return timeout duration in milliseconds, between 1 and the {@link #MAX_MILLIS}.
64       */
65      public static long availableTimeout(long expectedTimeoutMillis, long currentTimeoutMillis) {
66          checkArgument(expectedTimeoutMillis > 0,
67                        "expectedTimeoutMillis: %s (expected: > 0)", expectedTimeoutMillis);
68          checkArgument(currentTimeoutMillis >= 0,
69                        "currentTimeoutMillis: %s (expected: >= 0)", currentTimeoutMillis);
70  
71          if (currentTimeoutMillis >= MAX_MILLIS) {
72              return 0;
73          }
74  
75          final long maxAvailableTimeoutMillis = MAX_MILLIS - currentTimeoutMillis;
76          return Math.min(expectedTimeoutMillis, maxAvailableTimeoutMillis);
77      }
78  
79      private WatchTimeout() {}
80  }