use of com.linkedin.util.clock.SettableClock in project rest.li by linkedin.
the class TestCallTracker method setUp.
@BeforeMethod
protected void setUp() throws Exception {
_clock = new SettableClock();
_callTracker = new CallTrackerImpl(_interval, _clock);
}
use of com.linkedin.util.clock.SettableClock in project rest.li by linkedin.
the class TestAsyncPool method testGetStats.
@Test(retryAnalyzer = SingleRetry.class)
public void testGetStats() throws Exception {
final int POOL_SIZE = 25;
final int MIN_SIZE = 0;
final int MAX_WAITER_SIZE = Integer.MAX_VALUE;
final SettableClock clock = new SettableClock();
final LongTracking waitTimeTracker = new LongTracking();
final int GET = 20;
final int PUT_GOOD = 2;
final int PUT_BAD = 3;
final int DISPOSE = 4;
final int TIMEOUT = 100;
final int WAITER_TIMEOUT = 200;
final int DELAY = 1200;
final UnreliableLifecycle lifecycle = new UnreliableLifecycle();
final AsyncPool<AtomicBoolean> pool = new AsyncPoolImpl<>("object pool", lifecycle, POOL_SIZE, TIMEOUT, WAITER_TIMEOUT, _executor, MAX_WAITER_SIZE, AsyncPoolImpl.Strategy.MRU, MIN_SIZE, new NoopRateLimiter(), clock, waitTimeTracker);
PoolStats stats;
final List<AtomicBoolean> objects = new ArrayList<>();
pool.start();
// test values at initialization
stats = pool.getStats();
Assert.assertEquals(stats.getTotalCreated(), 0);
Assert.assertEquals(stats.getTotalDestroyed(), 0);
Assert.assertEquals(stats.getTotalCreateErrors(), 0);
Assert.assertEquals(stats.getTotalDestroyErrors(), 0);
Assert.assertEquals(stats.getCheckedOut(), 0);
Assert.assertEquals(stats.getTotalTimedOut(), 0);
Assert.assertEquals(stats.getTotalWaiterTimedOut(), 0);
Assert.assertEquals(stats.getTotalBadDestroyed(), 0);
Assert.assertEquals(stats.getMaxPoolSize(), POOL_SIZE);
Assert.assertEquals(stats.getMinPoolSize(), 0);
Assert.assertEquals(stats.getPoolSize(), 0);
Assert.assertEquals(stats.getSampleMaxCheckedOut(), 0);
Assert.assertEquals(stats.getSampleMaxPoolSize(), 0);
// do a few gets
for (int i = 0; i < GET; i++) {
FutureCallback<AtomicBoolean> cb = new FutureCallback<>();
pool.get(cb);
AtomicBoolean obj = cb.get();
objects.add(obj);
}
clock.addDuration(SAMPLING_DURATION_INCREMENT);
stats = pool.getStats();
Assert.assertEquals(stats.getTotalCreated(), GET);
Assert.assertEquals(stats.getTotalDestroyed(), 0);
Assert.assertEquals(stats.getTotalCreateErrors(), 0);
Assert.assertEquals(stats.getTotalDestroyErrors(), 0);
Assert.assertEquals(stats.getCheckedOut(), GET);
Assert.assertEquals(stats.getTotalTimedOut(), 0);
Assert.assertEquals(stats.getTotalBadDestroyed(), 0);
Assert.assertEquals(stats.getMaxPoolSize(), POOL_SIZE);
Assert.assertEquals(stats.getMinPoolSize(), 0);
Assert.assertEquals(stats.getPoolSize(), GET);
Assert.assertEquals(stats.getSampleMaxCheckedOut(), GET);
Assert.assertEquals(stats.getSampleMaxPoolSize(), GET);
// do some puts with good objects
for (int i = 0; i < PUT_GOOD; i++) {
AtomicBoolean obj = objects.remove(objects.size() - 1);
pool.put(obj);
}
clock.addDuration(SAMPLING_DURATION_INCREMENT);
stats = pool.getStats();
Assert.assertEquals(stats.getTotalCreated(), GET);
Assert.assertEquals(stats.getTotalDestroyed(), 0);
Assert.assertEquals(stats.getTotalCreateErrors(), 0);
Assert.assertEquals(stats.getTotalDestroyErrors(), 0);
Assert.assertEquals(stats.getCheckedOut(), GET - PUT_GOOD);
Assert.assertEquals(stats.getTotalTimedOut(), 0);
Assert.assertEquals(stats.getTotalBadDestroyed(), 0);
Assert.assertEquals(stats.getMaxPoolSize(), POOL_SIZE);
Assert.assertEquals(stats.getMinPoolSize(), 0);
Assert.assertEquals(stats.getPoolSize(), GET);
Assert.assertEquals(stats.getSampleMaxCheckedOut(), GET);
Assert.assertEquals(stats.getSampleMaxPoolSize(), GET);
// do some puts with bad objects
for (int i = 0; i < PUT_BAD; i++) {
AtomicBoolean obj = objects.remove(objects.size() - 1);
// invalidate the object
obj.set(false);
pool.put(obj);
}
clock.addDuration(SAMPLING_DURATION_INCREMENT);
stats = pool.getStats();
Assert.assertEquals(stats.getTotalCreated(), GET);
Assert.assertEquals(stats.getTotalDestroyed(), PUT_BAD);
Assert.assertEquals(stats.getTotalCreateErrors(), 0);
Assert.assertEquals(stats.getTotalDestroyErrors(), 0);
Assert.assertEquals(stats.getCheckedOut(), GET - PUT_GOOD - PUT_BAD);
Assert.assertEquals(stats.getTotalTimedOut(), 0);
Assert.assertEquals(stats.getTotalBadDestroyed(), PUT_BAD);
Assert.assertEquals(stats.getMaxPoolSize(), POOL_SIZE);
Assert.assertEquals(stats.getMinPoolSize(), 0);
Assert.assertEquals(stats.getPoolSize(), GET - PUT_BAD);
Assert.assertEquals(stats.getSampleMaxCheckedOut(), GET - PUT_GOOD);
Assert.assertEquals(stats.getSampleMaxPoolSize(), GET);
// do some disposes
for (int i = 0; i < DISPOSE; i++) {
AtomicBoolean obj = objects.remove(objects.size() - 1);
pool.dispose(obj);
}
clock.addDuration(SAMPLING_DURATION_INCREMENT);
stats = pool.getStats();
Assert.assertEquals(stats.getTotalCreated(), GET);
Assert.assertEquals(stats.getTotalDestroyed(), PUT_BAD + DISPOSE);
Assert.assertEquals(stats.getTotalCreateErrors(), 0);
Assert.assertEquals(stats.getTotalDestroyErrors(), 0);
Assert.assertEquals(stats.getCheckedOut(), GET - PUT_GOOD - PUT_BAD - DISPOSE);
Assert.assertEquals(stats.getTotalTimedOut(), 0);
Assert.assertEquals(stats.getTotalBadDestroyed(), PUT_BAD + DISPOSE);
Assert.assertEquals(stats.getMaxPoolSize(), POOL_SIZE);
Assert.assertEquals(stats.getMinPoolSize(), 0);
Assert.assertEquals(stats.getPoolSize(), GET - PUT_BAD - DISPOSE);
Assert.assertEquals(stats.getSampleMaxCheckedOut(), GET - PUT_GOOD - PUT_BAD);
Assert.assertEquals(stats.getSampleMaxPoolSize(), GET - PUT_BAD);
// wait for a reap -- should destroy the PUT_GOOD objects
Thread.sleep(DELAY);
clock.addDuration(SAMPLING_DURATION_INCREMENT);
stats = pool.getStats();
Assert.assertEquals(stats.getTotalCreated(), GET);
Assert.assertEquals(stats.getTotalDestroyed(), PUT_GOOD + PUT_BAD + DISPOSE);
Assert.assertEquals(stats.getTotalCreateErrors(), 0);
Assert.assertEquals(stats.getTotalDestroyErrors(), 0);
Assert.assertEquals(stats.getCheckedOut(), GET - PUT_GOOD - PUT_BAD - DISPOSE);
Assert.assertEquals(stats.getTotalTimedOut(), PUT_GOOD);
Assert.assertEquals(stats.getTotalBadDestroyed(), PUT_BAD + DISPOSE);
Assert.assertEquals(stats.getMaxPoolSize(), POOL_SIZE);
Assert.assertEquals(stats.getMinPoolSize(), 0);
Assert.assertEquals(stats.getPoolSize(), GET - PUT_GOOD - PUT_BAD - DISPOSE);
Assert.assertEquals(stats.getSampleMaxCheckedOut(), GET - PUT_GOOD - PUT_BAD - DISPOSE);
Assert.assertEquals(stats.getSampleMaxPoolSize(), GET - PUT_BAD - DISPOSE);
}
use of com.linkedin.util.clock.SettableClock in project rest.li by linkedin.
the class TestHttpNettyClient method testFailBackoff.
@Test
public void testFailBackoff() throws Exception {
final int WARM_UP = 10;
final int N = 5;
final int MAX_RATE_LIMITING_PERIOD = 500;
final CountDownLatch warmUpLatch = new CountDownLatch(WARM_UP);
final CountDownLatch latch = new CountDownLatch(N);
final AtomicReference<Boolean> isShutdown = new AtomicReference<>(false);
AsyncPool<Channel> testPool = new AsyncPoolImpl<>("test pool", new AsyncPool.Lifecycle<Channel>() {
@Override
public void create(Callback<Channel> callback) {
if (warmUpLatch.getCount() > 0) {
warmUpLatch.countDown();
} else {
latch.countDown();
}
callback.onError(new Throwable("Oops..."));
}
@Override
public boolean validateGet(Channel obj) {
return false;
}
@Override
public boolean validatePut(Channel obj) {
return false;
}
@Override
public void destroy(Channel obj, boolean error, Callback<Channel> callback) {
}
@Override
public PoolStats.LifecycleStats getStats() {
return null;
}
}, 200, 30000, _scheduler, Integer.MAX_VALUE, AsyncPoolImpl.Strategy.MRU, 0, new ExponentialBackOffRateLimiter(0, MAX_RATE_LIMITING_PERIOD, Math.max(10, MAX_RATE_LIMITING_PERIOD / 32), _scheduler), new SettableClock(), new LongTracking());
HttpNettyClient client = new HttpNettyClient(address -> testPool, _scheduler, MAX_RATE_LIMITING_PERIOD * 2, 500);
final RestRequest r = new RestRequestBuilder(URI.create("http://localhost:8080/")).setMethod("GET").build();
final ExecutorService executor = Executors.newSingleThreadExecutor();
executor.execute(() -> {
while (!isShutdown.get()) {
try {
FutureCallback<RestResponse> callback = new FutureCallback<>();
client.restRequest(r, new RequestContext(), new HashMap<>(), new TransportCallbackAdapter<>(callback));
callback.get();
} catch (Exception e) {
// ignore
}
}
});
// First ensure a bunch fail to get the rate limiting going
warmUpLatch.await(120, TimeUnit.SECONDS);
// Now we should be rate limited
long start = System.currentTimeMillis();
System.err.println("Starting at " + start);
long lowTolerance = N * MAX_RATE_LIMITING_PERIOD * 4 / 5;
long highTolerance = N * MAX_RATE_LIMITING_PERIOD * 5 / 4;
Assert.assertTrue(latch.await(highTolerance, TimeUnit.MILLISECONDS), "Should have finished within " + highTolerance + "ms");
long elapsed = System.currentTimeMillis() - start;
Assert.assertTrue(elapsed > lowTolerance, "Should have finished after " + lowTolerance + "ms (took " + elapsed + ")");
// shutdown everything
isShutdown.set(true);
executor.shutdown();
}
use of com.linkedin.util.clock.SettableClock in project rest.li by linkedin.
the class DegraderTrackerClientTest method testClientStreamRequest.
@Test(groups = { "small", "back-end" })
public void testClientStreamRequest() throws URISyntaxException {
URI uri = URI.create("http://test.qa.com:1234/foo");
double weight = 3d;
TestClient wrappedClient = new TestClient(true);
Clock clock = new SettableClock();
Map<Integer, PartitionData> partitionDataMap = createDefaultPartitionData(3d);
DegraderTrackerClient client = new DegraderTrackerClientImpl(uri, partitionDataMap, wrappedClient, clock, null);
Assert.assertEquals(client.getUri(), uri);
Double clientWeight = client.getPartitionWeight(DefaultPartitionAccessor.DEFAULT_PARTITION_ID);
Assert.assertEquals(clientWeight, weight);
Assert.assertEquals(client.getTransportClient(), wrappedClient);
StreamRequest streamRequest = new StreamRequestBuilder(uri).build(EntityStreams.emptyStream());
Map<String, String> restWireAttrs = new HashMap<>();
TestTransportCallback<StreamResponse> restCallback = new TestTransportCallback<>();
client.streamRequest(streamRequest, new RequestContext(), restWireAttrs, restCallback);
Assert.assertFalse(restCallback.response.hasError());
Assert.assertSame(wrappedClient.streamRequest, streamRequest);
Assert.assertEquals(wrappedClient.restWireAttrs, restWireAttrs);
}
use of com.linkedin.util.clock.SettableClock in project rest.li by linkedin.
the class DegraderTrackerClientTest method testDoNotSlowStartWhenTrue.
@Test
public void testDoNotSlowStartWhenTrue() {
Map<Integer, PartitionData> partitionDataMap = createDefaultPartitionData(1d);
DegraderImpl.Config config = new DegraderImpl.Config();
double initialDropRate = 0.99d;
config.setInitialDropRate(initialDropRate);
DegraderTrackerClient client = new DegraderTrackerClientImpl(URI.create("http://test.qa.com:1234/foo"), partitionDataMap, new TestClient(), new SettableClock(), config, DegraderLoadBalancerStrategyConfig.DEFAULT_UPDATE_INTERVAL_MS, TrackerClientImpl.DEFAULT_ERROR_STATUS_PATTERN, true);
DegraderControl degraderControl = client.getDegraderControl(DefaultPartitionAccessor.DEFAULT_PARTITION_ID);
Assert.assertEquals(degraderControl.getInitialDropRate(), DegraderImpl.DEFAULT_DO_NOT_SLOW_START_INITIAL_DROP_RATE, "Initial drop rate in config should have been overridden by doNotSlowStart uri property.");
}
Aggregations