use of com.linkedin.common.callback.SimpleCallback in project rest.li by linkedin.
the class SimpleLoadBalancerState method shutdown.
@Override
public void shutdown(final PropertyEventShutdownCallback shutdown) {
trace(_log, "shutdown");
// shutdown all three registries, all tracker clients, and the event thread
_executor.execute(new PropertyEvent("shutdown load balancer state") {
@Override
public void innerRun() {
// Need to shutdown loadBalancerStrategies before the transportClients are shutdown
for (Map<String, LoadBalancerStrategy> strategyEntry : _serviceStrategies.values()) {
strategyEntry.values().forEach(LoadBalancerStrategy::shutdown);
}
// put all tracker clients into a single set for convenience
Set<TransportClient> transportClients = new HashSet<TransportClient>();
for (Map<String, TransportClient> clientsByScheme : _serviceClients.values()) {
transportClients.addAll(clientsByScheme.values());
}
Callback<None> trackerCallback = Callbacks.countDown(Callbacks.<None>adaptSimple(new SimpleCallback() {
@Override
public void onDone() {
shutdown.done();
}
}), transportClients.size());
info(_log, "shutting down cluster clients");
for (TransportClient transportClient : transportClients) {
transportClient.shutdown(trackerCallback);
}
// so it is needed to notify all the listeners
for (SimpleLoadBalancerStateListener listener : _listeners) {
// Notify the strategy removal
for (Map.Entry<String, Map<String, LoadBalancerStrategy>> serviceStrategy : _serviceStrategies.entrySet()) {
for (Map.Entry<String, LoadBalancerStrategy> strategyEntry : serviceStrategy.getValue().entrySet()) {
listener.onStrategyRemoved(serviceStrategy.getKey(), strategyEntry.getKey(), strategyEntry.getValue());
}
// Also notify the client removal
Map<URI, TrackerClient> trackerClients = _trackerClients.get(serviceStrategy.getKey());
if (trackerClients != null) {
for (TrackerClient client : trackerClients.values()) {
listener.onClientRemoved(serviceStrategy.getKey(), client);
}
}
}
}
}
});
}
use of com.linkedin.common.callback.SimpleCallback in project rest.li by linkedin.
the class AsyncPoolImpl method create.
/**
* DO NOT call this method while holding the lock! It invokes user code.
*/
private void create() {
trc("initiating object creation");
_rateLimiter.submit(new Task() {
@Override
public void run(final SimpleCallback callback) {
_lifecycle.create(new Callback<T>() {
@Override
public void onSuccess(T t) {
synchronized (_lock) {
_statsTracker.incrementCreated();
_lastCreateError = null;
}
add(t);
callback.onDone();
}
@Override
public void onError(final Throwable e) {
_rateLimiter.incrementPeriod();
// Note we drain all waiters and cancel all pending creates if a create fails.
// When a create fails, rate-limiting logic will be applied. In this case,
// we may be initiating creations at a lower rate than incoming requests. While
// creations are suppressed, it is better to deny all waiters and let them see
// the real reason (this exception) rather than keep them around to eventually
// get an unhelpful timeout error
final Collection<Callback<T>> waitersDenied;
final Collection<Task> cancelledCreate = _rateLimiter.cancelPendingTasks();
boolean create;
synchronized (_lock) {
_statsTracker.incrementCreateErrors();
_lastCreateError = e;
create = objectDestroyed(1 + cancelledCreate.size());
if (!_waiters.isEmpty()) {
waitersDenied = cancelWaiters();
} else {
waitersDenied = Collections.<Callback<T>>emptyList();
}
}
for (Callback<T> denied : waitersDenied) {
try {
denied.onError(e);
} catch (Exception ex) {
LOG.error("Encountered error while invoking error waiter callback", ex);
}
}
if (create) {
create();
}
LOG.error(_poolName + ": object creation failed", e);
callback.onDone();
}
});
}
});
}
use of com.linkedin.common.callback.SimpleCallback in project rest.li by linkedin.
the class TestRateLimiter method testSimple.
@Test
public void testSimple() throws Exception {
final int total = 10;
// NB on Solaris x86 there seems to be an extra 10ms that gets added to the period; need
// to figure this out. For now set the period high enough that period + 10 will be within
// the tolerance.
final int period = 100;
final CountDownLatch latch = new CountDownLatch(total);
final Task incr = new Task() {
@Override
public void run(SimpleCallback doneCallback) {
latch.countDown();
doneCallback.onDone();
}
};
RateLimiter limiter = new ExponentialBackOffRateLimiter(period, period, period, _executor);
limiter.setPeriod(period);
long start = System.currentTimeMillis();
long lowTolerance = (total * period) * 4 / 5;
long highTolerance = (total * period) * 5 / 4;
for (int i = 0; i < total * period; i++) {
limiter.submit(incr);
}
Assert.assertTrue(latch.await(highTolerance, TimeUnit.MILLISECONDS), "Should have finished within " + highTolerance + "ms");
long t = System.currentTimeMillis() - start;
Assert.assertTrue(t > lowTolerance, "Should have finished after " + lowTolerance + "ms (took " + t + ")");
}
use of com.linkedin.common.callback.SimpleCallback in project rest.li by linkedin.
the class TestRateLimiter method testMaxRunningTasks.
@Test
public void testMaxRunningTasks() throws Exception {
final int total = 20;
final int maxRunning = 5;
final int period = 100;
final Random rand = new Random();
final CountDownLatch latch = new CountDownLatch(total);
final AtomicInteger totalStarted = new AtomicInteger();
final AtomicInteger totalFinished = new AtomicInteger();
final Task r = new Task() {
@Override
public void run(final SimpleCallback callback) {
totalStarted.incrementAndGet();
int delay = period + rand.nextInt(period);
_executor.schedule(new Runnable() {
@Override
public void run() {
totalFinished.incrementAndGet();
callback.onDone();
}
}, delay, TimeUnit.MILLISECONDS);
latch.countDown();
}
};
RateLimiter limiter = new ExponentialBackOffRateLimiter(period, period, period, _executor, maxRunning);
limiter.setPeriod(period);
for (int i = 0; i < total; ++i) {
limiter.submit(r);
}
// check the current number of concurrent tasks every 100ms.
for (int i = 0; i < total * 2; ++i) {
int currentRunning = totalStarted.get() - totalFinished.get();
Assert.assertTrue(currentRunning <= maxRunning, "Should have less than " + maxRunning + " concurrent tasks");
Thread.sleep(period);
}
Assert.assertTrue(latch.await(30, TimeUnit.SECONDS));
Assert.assertEquals(total, totalStarted.get());
}
Aggregations