Search in sources :

Example 41 with Timeout

use of com.linkedin.r2.util.Timeout 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) {
            boolean shouldIgnore;
            synchronized (_lock) {
                // Ignore the object creation if no one is waiting for the object and the pool already has _minSize objects
                int totalObjects = _checkedOut + _idle.size();
                shouldIgnore = _waiters.size() == 0 && totalObjects >= _minSize;
                if (shouldIgnore) {
                    _statsTracker.incrementIgnoredCreation();
                    if (_poolSize >= 1) {
                        // _poolSize also include the count of creation requests pending. So we have to make sure the pool size
                        // count is updated when we ignore the creation request.
                        _poolSize--;
                    }
                }
            }
            if (shouldIgnore) {
                callback.onDone();
                return;
            }
            // Lets not trust the _lifecycle to timely return a response here.
            // Embedding the callback inside a timeout callback (ObjectCreationTimeoutCallback)
            // to force a response within creationTimeout deadline to reclaim the object slot in the pool
            _lifecycle.create(new TimeoutCallback<>(_timeoutExecutor, _creationTimeout, TimeUnit.MILLISECONDS, 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) {
                    // 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;
                        // Cancel all waiters in the rate limiter
                        if (!_waiters.isEmpty()) {
                            waitersDenied = cancelWaiters();
                        } else {
                            waitersDenied = Collections.<Callback<T>>emptyList();
                        }
                        // reclaim the slot in the pool
                        create = objectDestroyed(1 + cancelledCreate.size());
                    }
                    // lets fail all the waiters with the object creation error
                    for (Callback<T> denied : waitersDenied) {
                        try {
                            denied.onError(e);
                        } catch (Exception ex) {
                            LOG.error("Encountered error while invoking error waiter callback", ex);
                        }
                    }
                    // Now after cancelling all the pending tasks, lets make sure to back off on the creation
                    _rateLimiter.incrementPeriod();
                    // the min poolSize
                    if (create) {
                        create();
                    }
                    LOG.debug(_poolName + ": object creation failed", e);
                    callback.onDone();
                }
            }, () -> new ObjectCreationTimeoutException("Exceeded creation timeout of " + _creationTimeout + "ms: in Pool: " + _poolName)));
        }
    });
}
Also used : Task(com.linkedin.r2.transport.http.client.RateLimiter.Task) Callback(com.linkedin.common.callback.Callback) SimpleCallback(com.linkedin.common.callback.SimpleCallback) Collection(java.util.Collection) SimpleCallback(com.linkedin.common.callback.SimpleCallback) SizeLimitExceededException(com.linkedin.r2.SizeLimitExceededException)

Example 42 with Timeout

use of com.linkedin.r2.util.Timeout in project rest.li by linkedin.

the class SyncIOHandler method eventLoop.

private void eventLoop() throws ServletException, IOException, InterruptedException, TimeoutException {
    final long startTime = System.currentTimeMillis();
    byte[] buf = new byte[DEFAULT_DATA_CHUNK_SIZE];
    while (shouldContinue() && !_forceExit) {
        long timeSpent = System.currentTimeMillis() - startTime;
        long maxWaitTime = timeSpent < _timeout ? _timeout - timeSpent : 0;
        Event event = _eventQueue.poll(maxWaitTime, TimeUnit.MILLISECONDS);
        if (event == null) {
            throw new TimeoutException("Timeout after " + _timeout + " milliseconds.");
        }
        switch(event.getEventType()) {
            case ResponseDataAvailable:
                {
                    ByteString data = (ByteString) event.getData();
                    data.write(_os);
                    _rh.request(1);
                    break;
                }
            case WriteRequestPossible:
                {
                    while (_wh.remaining() > 0) {
                        final int actualLen = _is.read(buf);
                        if (actualLen < 0) {
                            _wh.done();
                            _requestReadFinished = true;
                            break;
                        }
                        _wh.write(ByteString.copy(buf, 0, actualLen));
                    }
                    break;
                }
            case FullResponseReceived:
                {
                    _os.close();
                    _responseWriteFinished = true;
                    break;
                }
            case ResponseDataError:
                {
                    _os.close();
                    _responseWriteFinished = true;
                    break;
                }
            case WriteRequestAborted:
                {
                    if (event.getData() instanceof AbortedException) {
                        // reader cancels, we'll drain the stream on behalf of reader
                        // we don't directly drain it here because we'd like to give other events
                        // some opportunities to be executed; e.g. return an error response
                        _eventQueue.add(Event.DrainRequestEvent);
                    } else {
                        // TODO: do we want to be smarter and return server error response?
                        throw new ServletException((Throwable) event.getData());
                    }
                    break;
                }
            case DrainRequest:
                {
                    for (int i = 0; i < 10; i++) {
                        final int actualLen = _is.read(buf);
                        if (actualLen < 0) {
                            _requestReadFinished = true;
                            break;
                        }
                    }
                    if (!_requestReadFinished) {
                        // add self back to event queue and give others a chance to run
                        _eventQueue.add(Event.DrainRequestEvent);
                    }
                    break;
                }
            case ForceExit:
                {
                    _forceExit = true;
                    break;
                }
            default:
                throw new IllegalStateException("Unknown event type:" + event.getEventType());
        }
    }
}
Also used : ServletException(javax.servlet.ServletException) ByteString(com.linkedin.data.ByteString) AbortedException(com.linkedin.r2.message.stream.entitystream.AbortedException) TimeoutException(java.util.concurrent.TimeoutException)

Example 43 with Timeout

use of com.linkedin.r2.util.Timeout in project rest.li by linkedin.

the class TestDisruptor method testStreamErrorDisrupt.

@Test
public void testStreamErrorDisrupt() throws Exception {
    final Map<String, Object> properties = new HashMap<>();
    properties.put(HttpClientFactory.HTTP_REQUEST_TIMEOUT, String.valueOf(REQUEST_TIMEOUT));
    final Client client = _clientProvider.createClient(FilterChains.empty(), properties);
    final RequestContext requestContext = new RequestContext();
    requestContext.putLocalAttr(DISRUPT_CONTEXT_KEY, DisruptContexts.error(REQUEST_LATENCY));
    final CountDownLatch latch = new CountDownLatch(1);
    final AtomicBoolean success = new AtomicBoolean(false);
    client.streamRequest(new StreamRequestBuilder(getHttpURI()).build(EntityStreams.emptyStream()), requestContext, new Callback<StreamResponse>() {

        @Override
        public void onSuccess(StreamResponse result) {
            latch.countDown();
        }

        @Override
        public void onError(Throwable e) {
            success.set(e instanceof DisruptedException);
            latch.countDown();
        }
    });
    Assert.assertTrue(latch.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS), "Test execution timeout");
    Assert.assertTrue(success.get(), "Unexpected transport response");
}
Also used : HashMap(java.util.HashMap) StreamResponse(com.linkedin.r2.message.stream.StreamResponse) CountDownLatch(java.util.concurrent.CountDownLatch) StreamRequestBuilder(com.linkedin.r2.message.stream.StreamRequestBuilder) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) DisruptedException(com.linkedin.r2.disruptor.DisruptedException) RequestContext(com.linkedin.r2.message.RequestContext) Client(com.linkedin.r2.transport.common.Client) Test(org.testng.annotations.Test) AbstractServiceTest(test.r2.integ.clientserver.providers.AbstractServiceTest)

Example 44 with Timeout

use of com.linkedin.r2.util.Timeout in project rest.li by linkedin.

the class TestDisruptor method testStreamLatencyDisrupt.

@Test
public void testStreamLatencyDisrupt() throws Exception {
    final RequestContext requestContext = new RequestContext();
    requestContext.putLocalAttr(DISRUPT_CONTEXT_KEY, DisruptContexts.delay(REQUEST_LATENCY));
    final CountDownLatch latch = new CountDownLatch(1);
    final AtomicBoolean success = new AtomicBoolean(false);
    _client.streamRequest(new StreamRequestBuilder(getHttpURI()).build(EntityStreams.emptyStream()), requestContext, new Callback<StreamResponse>() {

        @Override
        public void onSuccess(StreamResponse result) {
            success.set(true);
            latch.countDown();
        }

        @Override
        public void onError(Throwable e) {
            success.set(false);
            latch.countDown();
        }
    });
    Assert.assertTrue(latch.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS), "Test execution timeout");
    Assert.assertTrue(success.get(), "Unexpected transport response");
}
Also used : AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) StreamResponse(com.linkedin.r2.message.stream.StreamResponse) RequestContext(com.linkedin.r2.message.RequestContext) CountDownLatch(java.util.concurrent.CountDownLatch) StreamRequestBuilder(com.linkedin.r2.message.stream.StreamRequestBuilder) Test(org.testng.annotations.Test) AbstractServiceTest(test.r2.integ.clientserver.providers.AbstractServiceTest)

Example 45 with Timeout

use of com.linkedin.r2.util.Timeout in project rest.li by linkedin.

the class TestDisruptor method testRestErrorDisrupt.

@Test
public void testRestErrorDisrupt() throws Exception {
    final Map<String, Object> properties = new HashMap<>();
    properties.put(HttpClientFactory.HTTP_REQUEST_TIMEOUT, String.valueOf(REQUEST_TIMEOUT));
    final Client client = _clientProvider.createClient(FilterChains.empty(), properties);
    final RequestContext requestContext = new RequestContext();
    requestContext.putLocalAttr(DISRUPT_CONTEXT_KEY, DisruptContexts.error(REQUEST_LATENCY));
    final CountDownLatch latch = new CountDownLatch(1);
    final AtomicBoolean success = new AtomicBoolean(false);
    client.restRequest(new RestRequestBuilder(getHttpURI()).build(), requestContext, new Callback<RestResponse>() {

        @Override
        public void onSuccess(RestResponse result) {
            latch.countDown();
        }

        @Override
        public void onError(Throwable e) {
            success.set(e instanceof DisruptedException);
            latch.countDown();
        }
    });
    Assert.assertTrue(latch.await(TEST_TIMEOUT, TimeUnit.MILLISECONDS), "Test execution timeout");
    Assert.assertTrue(success.get(), "Unexpected transport response");
}
Also used : HashMap(java.util.HashMap) RestResponse(com.linkedin.r2.message.rest.RestResponse) CountDownLatch(java.util.concurrent.CountDownLatch) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) DisruptedException(com.linkedin.r2.disruptor.DisruptedException) RestRequestBuilder(com.linkedin.r2.message.rest.RestRequestBuilder) RequestContext(com.linkedin.r2.message.RequestContext) Client(com.linkedin.r2.transport.common.Client) Test(org.testng.annotations.Test) AbstractServiceTest(test.r2.integ.clientserver.providers.AbstractServiceTest)

Aggregations

Test (org.testng.annotations.Test)78 RequestContext (com.linkedin.r2.message.RequestContext)46 CountDownLatch (java.util.concurrent.CountDownLatch)40 TimeoutException (java.util.concurrent.TimeoutException)40 None (com.linkedin.common.util.None)33 FutureCallback (com.linkedin.common.callback.FutureCallback)32 RestRequestBuilder (com.linkedin.r2.message.rest.RestRequestBuilder)26 StreamResponse (com.linkedin.r2.message.stream.StreamResponse)25 URI (java.net.URI)25 RestRequest (com.linkedin.r2.message.rest.RestRequest)21 StreamRequestBuilder (com.linkedin.r2.message.stream.StreamRequestBuilder)21 ByteString (com.linkedin.data.ByteString)19 HashMap (java.util.HashMap)19 AtomicBoolean (java.util.concurrent.atomic.AtomicBoolean)19 RestResponse (com.linkedin.r2.message.rest.RestResponse)18 StreamRequest (com.linkedin.r2.message.stream.StreamRequest)17 ExecutionException (java.util.concurrent.ExecutionException)17 TransportClient (com.linkedin.r2.transport.common.bridge.client.TransportClient)15 IOException (java.io.IOException)15 TransportCallback (com.linkedin.r2.transport.common.bridge.common.TransportCallback)13