diff options
author | Jon Bratseth <bratseth@yahoo-inc.com> | 2017-01-24 15:19:59 +0100 |
---|---|---|
committer | Jon Bratseth <bratseth@yahoo-inc.com> | 2017-01-24 15:19:59 +0100 |
commit | 827b409663ae7a0137d2e1f4c8659fcb3b15a1e5 (patch) | |
tree | 7804a1e593e433c547d46d46cd0867ba579d9d46 /container-search/src/test/java/com/yahoo/search/federation | |
parent | 6329a23f586f3a418702e6b2ca683957bc0ca554 (diff) |
Adaptive federation timeout
Diffstat (limited to 'container-search/src/test/java/com/yahoo/search/federation')
4 files changed, 148 insertions, 110 deletions
diff --git a/container-search/src/test/java/com/yahoo/search/federation/FederationResultTest.java b/container-search/src/test/java/com/yahoo/search/federation/FederationResultTest.java new file mode 100644 index 00000000000..eb17cf27db9 --- /dev/null +++ b/container-search/src/test/java/com/yahoo/search/federation/FederationResultTest.java @@ -0,0 +1,146 @@ +package com.yahoo.search.federation; + +import com.google.common.collect.ImmutableSet; +import com.yahoo.component.chain.Chain; +import com.yahoo.search.Query; +import com.yahoo.search.Result; +import com.yahoo.search.Searcher; +import com.yahoo.search.result.ErrorMessage; +import com.yahoo.search.searchchain.Execution; +import com.yahoo.search.searchchain.FutureResult; +import com.yahoo.search.searchchain.model.federation.FederationOptions; +import org.junit.Test; + +import java.time.Clock; +import java.util.Optional; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import static junit.framework.TestCase.assertTrue; +import static org.junit.Assert.assertEquals; + +/** + * @author bratseth + */ +public class FederationResultTest { + + private static final FederationSearcher.Target organic = new MockTarget("organic", 250); + private static final FederationSearcher.Target dsp1 = new MockTarget("dsp1", 120); + private static final FederationSearcher.Target dsp2 = new MockTarget("dsp2", 100); + + private final Clock clock = Clock.systemUTC(); + + @Test + public void testFederationResult() { + assertTimeout(ImmutableSet.of(), 50, 100, 90); + assertTimeout(ImmutableSet.of(), 240, 200, 200); + assertTimeout(ImmutableSet.of("dsp1"), 130, 140, 110); + assertTimeout(ImmutableSet.of("organic"), 260, 80, 80); + assertTimeout(ImmutableSet.of("dsp2"), 100, 110, 115); + assertTimeout(ImmutableSet.of(), 100, 110, 105); + assertTimeout(ImmutableSet.of("dsp1", "dsp2"), 100, 130, 130); + assertTimeout(ImmutableSet.of("organic"), 260, 130, 130); + } + + private void assertTimeout(Set<String> expectedTimeoutNames, int ... responseTimes) { + FederationResult.Builder builder = new FederationResult.Builder(); + builder.add(organic, resultAfter(responseTimes[0])); + builder.add(dsp1, resultAfter(responseTimes[1])); + builder.add(dsp2, resultAfter(responseTimes[2])); + FederationResult federationResult = builder.build(); + federationResult.waitForAll(50, clock); + assertEquals(3, federationResult.all().size()); + for (FederationResult.TargetResult targetResult : federationResult.all()) { + Result result = targetResult.getOrTimeoutError(); + if (expectedTimeoutNames.contains(targetResult.target.getId().toString())) + assertTrue(targetResult.target.getId() + " timed out", timedOut(result)); + else + assertTrue(targetResult.target.getId() + " did not time out", ! timedOut(result)); + } + } + + private MockFutureResult resultAfter(int time) { + return new MockFutureResult(new Query(), time); + } + + private boolean timedOut(Result result) { + ErrorMessage error = result.hits().getError(); + if (error == null) return false; + return error.getCode() == ErrorMessage.timeoutCode; + } + + private class MockFutureResult extends FutureResult { + + private final int responseTime; + private final Query query; + private final long startTime; + + MockFutureResult(Query query, int responseTime) { + super(() -> new Result(query), new Execution(Execution.Context.createContextStub()), query); + this.responseTime = responseTime; + this.query = query; + startTime = clock.millis(); + } + + @Override + public Result get() { throw new RuntimeException(); } + + @Override + public Optional<Result> getIfAvailable(long timeout, TimeUnit timeunit) { + if (timeunit != TimeUnit.MILLISECONDS) throw new RuntimeException(); + + long elapsedTime = clock.millis() - startTime; + long leftUntilResponse = responseTime - elapsedTime; + if (leftUntilResponse > timeout) { + sleepUntil(timeout); + return Optional.empty(); + } + else { + sleepUntil(leftUntilResponse); + return Optional.of(new Result(query)); + } + } + + private void sleepUntil(long time) { + if (time <= 0) return; + try { + Thread.sleep(time); + } + catch (InterruptedException e) { + } + } + + @Override + public Query getQuery() { + return query; + } + + } + + private static class MockTarget extends FederationSearcher.Target { + + private final Chain<Searcher> chain; + private final int timeout; + + MockTarget(String id, int timeout) { + this.chain = new Chain<>(id); + this.timeout = timeout; + } + + @Override + Chain<Searcher> getChain() { return chain; } + + @Override + void modifyTargetQuery(Query query) { } + + @Override + void modifyTargetResult(Result result) { } + + @Override + public FederationOptions federationOptions() { + return new FederationOptions(false, timeout, true); + } + + } + +} diff --git a/container-search/src/test/java/com/yahoo/search/federation/FutureWaiterTest.java b/container-search/src/test/java/com/yahoo/search/federation/FutureWaiterTest.java deleted file mode 100644 index 37969e12399..00000000000 --- a/container-search/src/test/java/com/yahoo/search/federation/FutureWaiterTest.java +++ /dev/null @@ -1,109 +0,0 @@ -// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. -package com.yahoo.search.federation; - - -/** - * @author tonytv - */ -// TODO: Fix or remove! -public class FutureWaiterTest { - -/* - - @MockClass(realClass = System.class) - public static class MockSystem { - - private static long currentTime; - private static boolean firstTime; - - private static final long startTime = 123; - - @Mock - public static synchronized long currentTimeMillis() { - if (firstTime) { - firstTime = false; - return startTime; - } - return currentTime; - } - - static synchronized void setElapsedTime(long elapsedTime) { - firstTime = true; - currentTime = elapsedTime + startTime; - } - } - - @Mocked() - FutureResult result1; - - @Mocked() - FutureResult result2; - - @Mocked() - FutureResult result3; - - @Mocked() - FutureResult result4; - - @Before - public void before() { - Mockit.setUpMock(FutureWaiterTest.MockSystem.class); - } - - @After - public void after() { - Mockit.tearDownMocks(); - } - - @Test - public void require_time_to_wait_is_adjusted_for_elapsed_time() { - MockSystem.setElapsedTime(300); - - FutureWaiter futureWaiter = new FutureWaiter(); - futureWaiter.add(result1, 350); - futureWaiter.waitForFutures(); - - new FullVerifications() { - { - result1.get(350 - 300, TimeUnit.MILLISECONDS); - } - }; - } - - @Test - public void require_do_not_wait_for_expired_timeouts() { - MockSystem.setElapsedTime(300); - - FutureWaiter futureWaiter = new FutureWaiter(); - futureWaiter.add(result1, 300); - futureWaiter.add(result2, 290); - - futureWaiter.waitForFutures(); - - new FullVerifications() { - {} - }; - } - - @Test - public void require_wait_for_largest_timeout_first() throws InterruptedException { - MockSystem.setElapsedTime(600); - - FutureWaiter futureWaiter = new FutureWaiter(); - futureWaiter.add(result1, 500); - futureWaiter.add(result4, 800); - futureWaiter.add(result2, 600); - futureWaiter.add(result3, 700); - - futureWaiter.waitForFutures(); - - new FullVerifications() { - { - result4.get(800 - 600, TimeUnit.MILLISECONDS); - result3.get(700 - 600, TimeUnit.MILLISECONDS); - } - }; - } - - */ -} diff --git a/container-search/src/test/java/com/yahoo/search/federation/test/FederationSearcherTestCase.java b/container-search/src/test/java/com/yahoo/search/federation/test/FederationSearcherTestCase.java index e4176bb6679..11fae387739 100644 --- a/container-search/src/test/java/com/yahoo/search/federation/test/FederationSearcherTestCase.java +++ b/container-search/src/test/java/com/yahoo/search/federation/test/FederationSearcherTestCase.java @@ -38,7 +38,7 @@ import static com.yahoo.search.federation.StrictContractsConfig.PropagateSourceP * Test for federation searcher. The searcher is also tested in * com.yahoo.prelude.searcher.test.BlendingSearcherTestCase. * - * @author <a href="mailto:arnebef@yahoo-inc.com">Arne Bergene Fossaa</a> + * @author Arne Bergene Fossaa */ @SuppressWarnings("deprecation") public class FederationSearcherTestCase { diff --git a/container-search/src/test/java/com/yahoo/search/federation/test/FederationTester.java b/container-search/src/test/java/com/yahoo/search/federation/test/FederationTester.java index 7b0451a01ba..7aa73c64d3a 100644 --- a/container-search/src/test/java/com/yahoo/search/federation/test/FederationTester.java +++ b/container-search/src/test/java/com/yahoo/search/federation/test/FederationTester.java @@ -18,6 +18,7 @@ import java.util.Collections; * @author tonytv */ class FederationTester { + SearchChainResolver.Builder builder = new SearchChainResolver.Builder(); SearchChainRegistry registry = new SearchChainRegistry(); |