/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.facebook.presto.server.remotetask; import io.airlift.testing.TestingTicker; import io.airlift.units.Duration; import org.testng.annotations.Test; import static java.util.concurrent.TimeUnit.MICROSECONDS; import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.NANOSECONDS; import static java.util.concurrent.TimeUnit.SECONDS; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; public class TestBackoff { @Test public void testFailureInterval() { TestingTicker ticker = new TestingTicker(); Backoff backoff = new Backoff(new Duration(15, SECONDS), new Duration(15, SECONDS), ticker, new Duration(10, MILLISECONDS)); ticker.increment(10, MICROSECONDS); assertEquals(backoff.getFailureCount(), 0); assertEquals(backoff.getTimeSinceLastSuccess().roundTo(SECONDS), 0); ticker.increment(14, SECONDS); assertFalse(backoff.failure()); assertEquals(backoff.getFailureCount(), 1); assertEquals(backoff.getTimeSinceLastSuccess().roundTo(SECONDS), 14); ticker.increment(1, SECONDS); assertTrue(backoff.failure()); assertEquals(backoff.getFailureCount(), 2); assertEquals(backoff.getTimeSinceLastSuccess().roundTo(SECONDS), 15); } @Test public void testStartRequest() { TestingTicker ticker = new TestingTicker(); Backoff backoff = new Backoff(new Duration(15, SECONDS), new Duration(15, SECONDS), ticker, new Duration(10, MILLISECONDS)); ticker.increment(10, MICROSECONDS); assertEquals(backoff.getFailureCount(), 0); assertEquals(backoff.getTimeSinceLastSuccess().roundTo(SECONDS), 0); ticker.increment(14, SECONDS); backoff.startRequest(); ticker.increment(14, SECONDS); assertFalse(backoff.failure()); assertEquals(backoff.getFailureCount(), 1); assertEquals(backoff.getTimeSinceLastSuccess().roundTo(SECONDS), 28); ticker.increment(1, SECONDS); assertTrue(backoff.failure()); assertEquals(backoff.getFailureCount(), 2); assertEquals(backoff.getTimeSinceLastSuccess().roundTo(SECONDS), 29); } @Test public void testMaxFailureInterval() { TestingTicker ticker = new TestingTicker(); Backoff backoff = new Backoff(new Duration(5, SECONDS), new Duration(15, SECONDS), ticker, new Duration(10, MILLISECONDS)); ticker.increment(10, MICROSECONDS); ticker.increment(6, SECONDS); assertTrue(backoff.failure()); assertEquals(backoff.getFailureCount(), 1); assertEquals(backoff.getTimeSinceLastSuccess().roundTo(SECONDS), 6); backoff.success(); // Check that we will tolerate failures for longer than the min, if the query has been running that long ticker.increment(6, SECONDS); assertFalse(backoff.failure()); assertEquals(backoff.getFailureCount(), 1); assertEquals(backoff.getTimeSinceLastSuccess().roundTo(SECONDS), 6); ticker.increment(1, SECONDS); // Check that we won't tolerate failures for longer than the query has been running assertTrue(backoff.failure()); assertEquals(backoff.getFailureCount(), 2); assertEquals(backoff.getTimeSinceLastSuccess().roundTo(SECONDS), 7); ticker.increment(20, SECONDS); backoff.success(); ticker.increment(20, SECONDS); // Check that we won't tolerate failures for longer than the max, even if the query has been running for a long time assertTrue(backoff.failure()); assertEquals(backoff.getFailureCount(), 1); assertEquals(backoff.getTimeSinceLastSuccess().roundTo(SECONDS), 20); } @Test public void testDelay() { // 1, 2, 4, 8 TestingTicker ticker = new TestingTicker(); Backoff backoff = new Backoff(new Duration(15, SECONDS), new Duration(15, SECONDS), ticker, new Duration(0, SECONDS), new Duration(1, SECONDS), new Duration(2, SECONDS), new Duration(4, SECONDS), new Duration(8, SECONDS)); assertEquals(backoff.getFailureCount(), 0); assertEquals(backoff.getTimeSinceLastSuccess().roundTo(SECONDS), 0); assertFalse(backoff.failure()); assertEquals(backoff.getFailureCount(), 1); assertEquals(backoff.getTimeSinceLastSuccess().roundTo(SECONDS), 0); long backoffDelay = backoff.getBackoffDelayNanos(); assertEquals(NANOSECONDS.toSeconds(backoffDelay), 0); ticker.increment(backoffDelay, NANOSECONDS); assertFalse(backoff.failure()); assertEquals(backoff.getFailureCount(), 2); assertEquals(backoff.getTimeSinceLastSuccess().roundTo(SECONDS), 0); backoffDelay = backoff.getBackoffDelayNanos(); assertEquals(NANOSECONDS.toSeconds(backoffDelay), 1); ticker.increment(backoffDelay, NANOSECONDS); assertFalse(backoff.failure()); assertEquals(backoff.getFailureCount(), 3); assertEquals(backoff.getTimeSinceLastSuccess().roundTo(SECONDS), 1); backoffDelay = backoff.getBackoffDelayNanos(); assertEquals(NANOSECONDS.toSeconds(backoffDelay), 2); ticker.increment(backoffDelay, NANOSECONDS); assertFalse(backoff.failure()); assertEquals(backoff.getFailureCount(), 4); assertEquals(backoff.getTimeSinceLastSuccess().roundTo(SECONDS), 3); backoffDelay = backoff.getBackoffDelayNanos(); assertEquals(NANOSECONDS.toSeconds(backoffDelay), 4); ticker.increment(backoffDelay, NANOSECONDS); assertFalse(backoff.failure()); assertEquals(backoff.getFailureCount(), 5); assertEquals(backoff.getTimeSinceLastSuccess().roundTo(SECONDS), 7); backoffDelay = backoff.getBackoffDelayNanos(); assertEquals(NANOSECONDS.toSeconds(backoffDelay), 8); ticker.increment(backoffDelay, NANOSECONDS); assertTrue(backoff.failure()); assertEquals(backoff.getFailureCount(), 6); assertEquals(backoff.getTimeSinceLastSuccess().roundTo(SECONDS), 15); backoffDelay = backoff.getBackoffDelayNanos(); assertEquals(NANOSECONDS.toSeconds(backoffDelay), 8); } }