use of com.linkedin.r2.util.Timeout in project rest.li by linkedin.
the class AbstractAsyncR2Servlet method service.
@Override
public void service(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
RequestContext requestContext = ServletHelper.readRequestContext(req);
RestRequest restRequest;
try {
restRequest = readFromServletRequest(req);
} catch (URISyntaxException e) {
writeToServletError(resp, RestStatus.BAD_REQUEST, e.toString());
return;
}
final AsyncContext ctx = req.startAsync(req, resp);
ctx.setTimeout(_timeout);
ctx.addListener(new AsyncListener() {
@Override
public void onTimeout(AsyncEvent event) throws IOException {
AsyncContext ctx = event.getAsyncContext();
writeToServletError((HttpServletResponse) ctx.getResponse(), RestStatus.INTERNAL_SERVER_ERROR, "Server Timeout");
ctx.complete();
}
@Override
public void onStartAsync(AsyncEvent event) throws IOException {
// Nothing to do here
}
@Override
public void onError(AsyncEvent event) throws IOException {
writeToServletError((HttpServletResponse) event.getSuppliedResponse(), RestStatus.INTERNAL_SERVER_ERROR, "Server Error");
ctx.complete();
}
@Override
public void onComplete(AsyncEvent event) throws IOException {
Object exception = req.getAttribute(TRANSPORT_CALLBACK_IOEXCEPTION);
if (exception != null)
throw new IOException((IOException) exception);
}
});
TransportCallback<RestResponse> callback = new TransportCallback<RestResponse>() {
@Override
public void onResponse(final TransportResponse<RestResponse> response) {
// TransportCallback is usually invoked by non-servlet threads; hence we cannot assume that it's ok to
// do blocking IO there. As a result, we should use AsyncContext.start() to do blocking IO using the
// container/servlet threads. This still maintains the advantage of Async, meaning servlet thread is not
// blocking-wait when the response is not ready.
ctx.start(new Runnable() {
@Override
public void run() {
try {
writeToServletResponse(response, (HttpServletResponse) ctx.getResponse());
} catch (IOException e) {
req.setAttribute(TRANSPORT_CALLBACK_IOEXCEPTION, e);
} finally {
ctx.complete();
}
}
});
}
};
getDispatcher().handleRequest(restRequest, requestContext, callback);
}
use of com.linkedin.r2.util.Timeout in project rest.li by linkedin.
the class AbstractR2Servlet method service.
@Override
protected void service(final HttpServletRequest req, final HttpServletResponse resp) throws ServletException, IOException {
RequestContext requestContext = ServletHelper.readRequestContext(req);
RestRequest restRequest;
try {
restRequest = readFromServletRequest(req);
} catch (URISyntaxException e) {
writeToServletError(resp, RestStatus.BAD_REQUEST, e.toString());
return;
}
final AtomicReference<TransportResponse<RestResponse>> result = new AtomicReference<>();
final CountDownLatch latch = new CountDownLatch(1);
TransportCallback<RestResponse> callback = new TransportCallback<RestResponse>() {
@Override
public void onResponse(TransportResponse<RestResponse> response) {
result.set(response);
latch.countDown();
}
};
getDispatcher().handleRequest(restRequest, requestContext, callback);
try {
if (latch.await(_timeout, TimeUnit.MILLISECONDS)) {
writeToServletResponse(result.get(), resp);
} else {
writeToServletError(resp, RestStatus.INTERNAL_SERVER_ERROR, "Server Timeout after " + _timeout + "ms.");
}
} catch (InterruptedException e) {
throw new ServletException("Interrupted!", e);
}
}
use of com.linkedin.r2.util.Timeout in project rest.li by linkedin.
the class TestConstantQpsRateLimiter method submitOnceGetMany.
@Test(timeOut = TEST_TIMEOUT)
public void submitOnceGetMany() {
ClockedExecutor executor = new ClockedExecutor();
ClockedExecutor circularBufferExecutor = new ClockedExecutor();
ConstantQpsRateLimiter rateLimiter = new ConstantQpsRateLimiter(executor, executor, executor, TestEvictingCircularBuffer.getBuffer(circularBufferExecutor));
rateLimiter.setRate(TEST_QPS, ONE_SECOND, UNLIMITED_BURST);
rateLimiter.setBufferCapacity(1);
TattlingCallback<None> tattler = new TattlingCallback<>(executor);
rateLimiter.submit(tattler);
executor.runFor(ONE_SECOND * TEST_NUM_CYCLES);
Assert.assertTrue(tattler.getInteractCount() > 1);
}
use of com.linkedin.r2.util.Timeout in project rest.li by linkedin.
the class TestConstantQpsRateLimiter method eventLoopStopsWhenTtlExpiresAllRequests.
@Test(timeOut = TEST_TIMEOUT)
public void eventLoopStopsWhenTtlExpiresAllRequests() {
ClockedExecutor executor = new ClockedExecutor();
ConstantQpsRateLimiter rateLimiter = new ConstantQpsRateLimiter(executor, executor, executor, TestEvictingCircularBuffer.getBuffer(executor));
rateLimiter.setRate(TEST_QPS, ONE_SECOND, UNLIMITED_BURST);
rateLimiter.setBufferTtl(ONE_SECOND - 1, ChronoUnit.MILLIS);
TattlingCallback<None> tattler = new TattlingCallback<>(executor);
rateLimiter.submit(tattler);
executor.runFor(ONE_SECOND * TEST_NUM_CYCLES);
Assert.assertSame(tattler.getInteractCount(), (int) TEST_QPS);
long prevTaskCount = executor.getExecutedTaskCount();
executor.runFor(ONE_SECOND * TEST_NUM_CYCLES);
// EventLoop continues by scheduling itself at the end. If executed task count remains the same,
// then EventLoop hasn't re-scheduled itself.
Assert.assertSame(executor.getExecutedTaskCount(), prevTaskCount);
}
use of com.linkedin.r2.util.Timeout in project rest.li by linkedin.
the class TestSmoothRateLimiter method testSubmitExceedsMaxBuffered.
@Test(timeOut = TEST_TIMEOUT)
public void testSubmitExceedsMaxBuffered() {
SmoothRateLimiter rateLimiter = new SmoothRateLimiter(_scheduledExecutorService, _executor, _clock, _queue, 0, SmoothRateLimiter.BufferOverflowMode.DROP, RATE_LIMITER_NAME_TEST);
rateLimiter.setRate(ONE_PERMIT_PER_PERIOD, ONE_SECOND_PERIOD, UNLIMITED_BURST);
FutureCallback<None> callback = new FutureCallback<>();
try {
rateLimiter.submit(callback);
} catch (RejectedExecutionException e) {
Assert.assertFalse("The tasks should have been rejected and not run", callback.isDone());
// success, the exception has been thrown as expected!
return;
}
Assert.fail("It should have thrown a RejectedExecutionException");
}
Aggregations