001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.client.backoff;
019
020import static org.junit.jupiter.api.Assertions.assertEquals;
021import static org.junit.jupiter.api.Assertions.assertFalse;
022import static org.junit.jupiter.api.Assertions.assertTrue;
023
024import java.util.OptionalLong;
025import java.util.concurrent.TimeUnit;
026import org.apache.hadoop.hbase.HBaseServerException;
027import org.apache.hadoop.hbase.quotas.RpcThrottlingException;
028import org.apache.hadoop.hbase.testclassification.ClientTests;
029import org.apache.hadoop.hbase.testclassification.SmallTests;
030import org.junit.jupiter.api.Tag;
031import org.junit.jupiter.api.Test;
032
033@Tag(ClientTests.TAG)
034@Tag(SmallTests.TAG)
035public class TestHBaseServerExceptionPauseManager {
036
037  private static final long WAIT_INTERVAL_MILLIS = 1L;
038  private static final long WAIT_INTERVAL_NANOS =
039    TimeUnit.MILLISECONDS.toNanos(WAIT_INTERVAL_MILLIS);
040  private static final long PAUSE_NANOS_FOR_SERVER_OVERLOADED = WAIT_INTERVAL_NANOS * 3;
041
042  private static final long PAUSE_NANOS = WAIT_INTERVAL_NANOS * 2;
043
044  private final RpcThrottlingException RPC_THROTTLING_EXCEPTION = new RpcThrottlingException(
045    RpcThrottlingException.Type.NumRequestsExceeded, WAIT_INTERVAL_MILLIS, "doot");
046  private final Throwable OTHER_EXCEPTION = new RuntimeException("");
047  private final HBaseServerException SERVER_OVERLOADED_EXCEPTION = new HBaseServerException(true);
048
049  @Test
050  public void itSupportsRpcThrottlingNanosNoTimeout() {
051    HBaseServerExceptionPauseManager pauseManager =
052      new HBaseServerExceptionPauseManager(PAUSE_NANOS, PAUSE_NANOS_FOR_SERVER_OVERLOADED, 0);
053
054    OptionalLong pauseNanos =
055      pauseManager.getPauseNsFromException(RPC_THROTTLING_EXCEPTION, 1, System.nanoTime());
056
057    assertTrue(pauseNanos.isPresent());
058    assertEquals(pauseNanos.getAsLong(), WAIT_INTERVAL_NANOS);
059  }
060
061  @Test
062  public void itSupportsRpcThrottlingNanosLenientTimeout() {
063    HBaseServerExceptionPauseManager pauseManager = new HBaseServerExceptionPauseManager(
064      PAUSE_NANOS, PAUSE_NANOS_FOR_SERVER_OVERLOADED, System.nanoTime() * 2);
065
066    OptionalLong pauseNanos =
067      pauseManager.getPauseNsFromException(RPC_THROTTLING_EXCEPTION, 1, System.nanoTime());
068
069    assertTrue(pauseNanos.isPresent());
070    assertEquals(pauseNanos.getAsLong(), WAIT_INTERVAL_NANOS);
071  }
072
073  @Test
074  public void itSupportsServerOverloadedExceptionNanos() {
075    HBaseServerExceptionPauseManager pauseManager =
076      new HBaseServerExceptionPauseManager(PAUSE_NANOS, PAUSE_NANOS_FOR_SERVER_OVERLOADED, 0);
077
078    OptionalLong pauseNanos =
079      pauseManager.getPauseNsFromException(SERVER_OVERLOADED_EXCEPTION, 1, System.nanoTime());
080
081    assertTrue(pauseNanos.isPresent());
082    // account for 1% jitter in pause time
083    assertTrue(pauseNanos.getAsLong() >= PAUSE_NANOS_FOR_SERVER_OVERLOADED * 0.99);
084    assertTrue(pauseNanos.getAsLong() <= PAUSE_NANOS_FOR_SERVER_OVERLOADED * 1.01);
085  }
086
087  @Test
088  public void itSupportsOtherExceptionNanos() {
089    HBaseServerExceptionPauseManager pauseManager =
090      new HBaseServerExceptionPauseManager(PAUSE_NANOS, PAUSE_NANOS_FOR_SERVER_OVERLOADED, 0);
091
092    OptionalLong pauseNanos =
093      pauseManager.getPauseNsFromException(OTHER_EXCEPTION, 1, System.nanoTime());
094
095    assertTrue(pauseNanos.isPresent());
096    // account for 1% jitter in pause time
097    assertTrue(pauseNanos.getAsLong() >= PAUSE_NANOS * 0.99);
098    assertTrue(pauseNanos.getAsLong() <= PAUSE_NANOS * 1.01);
099  }
100
101  @Test
102  public void itTimesOutRpcThrottlingException() {
103    HBaseServerExceptionPauseManager pauseManager =
104      new HBaseServerExceptionPauseManager(PAUSE_NANOS, PAUSE_NANOS_FOR_SERVER_OVERLOADED, 1);
105
106    OptionalLong pauseNanos =
107      pauseManager.getPauseNsFromException(RPC_THROTTLING_EXCEPTION, 1, System.nanoTime());
108
109    assertFalse(pauseNanos.isPresent());
110  }
111
112  @Test
113  public void itTimesOutRpcOtherException() {
114    HBaseServerExceptionPauseManager pauseManager =
115      new HBaseServerExceptionPauseManager(PAUSE_NANOS, PAUSE_NANOS_FOR_SERVER_OVERLOADED, 1);
116
117    OptionalLong pauseNanos =
118      pauseManager.getPauseNsFromException(OTHER_EXCEPTION, 1, System.nanoTime());
119
120    assertFalse(pauseNanos.isPresent());
121  }
122
123  @Test
124  public void itDoesNotTimeOutIfDisabled() {
125    HBaseServerExceptionPauseManager pauseManager =
126      new HBaseServerExceptionPauseManager(PAUSE_NANOS, PAUSE_NANOS_FOR_SERVER_OVERLOADED, 0);
127
128    OptionalLong pauseNanos =
129      pauseManager.getPauseNsFromException(OTHER_EXCEPTION, 1, System.nanoTime());
130
131    assertTrue(pauseNanos.isPresent());
132  }
133
134}