Search in sources :

Example 46 with Callback

use of com.linkedin.common.callback.Callback in project rest.li by linkedin.

the class TestHttpNettyStreamClient method testStreamRequests.

/**
   * Tests implementations of {@link AbstractNettyStreamClient} with different request dimensions.
   *
   * @param client Client implementation of {@link AbstractNettyStreamClient}
   * @param method HTTP request method
   * @param requestSize Request content size
   * @param responseSize Response content size
   * @param isFullRequest Whether to buffer a full request before stream
   * @throws Exception
   */
@Test(dataProvider = "requestResponseParameters")
public void testStreamRequests(AbstractNettyStreamClient client, String method, int requestSize, int responseSize, boolean isFullRequest) throws Exception {
    AtomicInteger succeeded = new AtomicInteger(0);
    AtomicInteger failed = new AtomicInteger(0);
    Server server = new HttpServerBuilder().responseSize(responseSize).build();
    try {
        server.start();
        CountDownLatch latch = new CountDownLatch(REQUEST_COUNT);
        for (int i = 0; i < REQUEST_COUNT; i++) {
            StreamRequest request = new StreamRequestBuilder(new URI(URL)).setMethod(method).setHeader(HttpHeaderNames.HOST.toString(), HOST_NAME.toString()).build(EntityStreams.newEntityStream(new ByteStringWriter(ByteString.copy(new byte[requestSize]))));
            RequestContext context = new RequestContext();
            context.putLocalAttr(R2Constants.IS_FULL_REQUEST, isFullRequest);
            client.streamRequest(request, context, new HashMap<>(), new TransportCallbackAdapter<>(new Callback<StreamResponse>() {

                @Override
                public void onSuccess(StreamResponse response) {
                    response.getEntityStream().setReader(new Reader() {

                        ReadHandle _rh;

                        int _consumed = 0;

                        @Override
                        public void onDataAvailable(ByteString data) {
                            _consumed += data.length();
                            _rh.request(1);
                        }

                        @Override
                        public void onDone() {
                            succeeded.incrementAndGet();
                            latch.countDown();
                        }

                        @Override
                        public void onError(Throwable e) {
                            failed.incrementAndGet();
                            latch.countDown();
                        }

                        @Override
                        public void onInit(ReadHandle rh) {
                            _rh = rh;
                            _rh.request(1);
                        }
                    });
                }

                @Override
                public void onError(Throwable e) {
                    failed.incrementAndGet();
                    latch.countDown();
                }
            }));
        }
        if (!latch.await(30, TimeUnit.SECONDS)) {
            Assert.fail("Timeout waiting for responses. " + succeeded + " requests succeeded and " + failed + " requests failed out of total " + REQUEST_COUNT + " requests");
        }
        Assert.assertEquals(latch.getCount(), 0);
        Assert.assertEquals(failed.get(), 0);
        Assert.assertEquals(succeeded.get(), REQUEST_COUNT);
        FutureCallback<None> shutdownCallback = new FutureCallback<>();
        client.shutdown(shutdownCallback);
        shutdownCallback.get(30, TimeUnit.SECONDS);
    } finally {
        server.stop();
    }
}
Also used : Server(org.eclipse.jetty.server.Server) ByteString(com.linkedin.data.ByteString) StreamResponse(com.linkedin.r2.message.stream.StreamResponse) Reader(com.linkedin.r2.message.stream.entitystream.Reader) CountDownLatch(java.util.concurrent.CountDownLatch) StreamRequestBuilder(com.linkedin.r2.message.stream.StreamRequestBuilder) URI(java.net.URI) StreamRequest(com.linkedin.r2.message.stream.StreamRequest) ReadHandle(com.linkedin.r2.message.stream.entitystream.ReadHandle) TransportCallback(com.linkedin.r2.transport.common.bridge.common.TransportCallback) FutureCallback(com.linkedin.common.callback.FutureCallback) Callback(com.linkedin.common.callback.Callback) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) RequestContext(com.linkedin.r2.message.RequestContext) ByteStringWriter(com.linkedin.r2.message.stream.entitystream.ByteStringWriter) None(com.linkedin.common.util.None) FutureCallback(com.linkedin.common.callback.FutureCallback) Test(org.testng.annotations.Test)

Example 47 with Callback

use of com.linkedin.common.callback.Callback in project rest.li by linkedin.

the class RetryClient method decorateCallback.

private <R, T> Callback<T> decorateCallback(R request, RequestContext requestContext, DecoratorClient<R, T> client, Callback<T> callback) {
    return new Callback<T>() {

        @Override
        public void onError(Throwable e) {
            // Retry will be triggered if and only if:
            // 1. A RetriableRequestException is thrown
            // 2. There is no target host hint
            boolean retry = false;
            if (e instanceof RetriableRequestException) {
                URI targetHostUri = KeyMapper.TargetHostHints.getRequestContextTargetHost(requestContext);
                if (targetHostUri == null) {
                    Set<URI> exclusionSet = ExcludedHostHints.getRequestContextExcludedHosts(requestContext);
                    int attempts = exclusionSet.size();
                    if (attempts <= _limit) {
                        LOG.warn("A retriable exception happens. Going to retry. This is attempt {}. Current exclusion set: ", attempts, ". Current exclusion set: " + exclusionSet);
                        retry = true;
                        client.doRequest(request, requestContext, this);
                    } else {
                        LOG.warn("Retry limit exceeded. This request will fail.");
                    }
                }
            }
            if (!retry) {
                ExcludedHostHints.clearRequestContextExcludedHosts(requestContext);
                callback.onError(e);
            }
        }

        @Override
        public void onSuccess(T result) {
            ExcludedHostHints.clearRequestContextExcludedHosts(requestContext);
            callback.onSuccess(result);
        }
    };
}
Also used : RetriableRequestException(com.linkedin.r2.RetriableRequestException) FutureCallback(com.linkedin.common.callback.FutureCallback) Callback(com.linkedin.common.callback.Callback) URI(java.net.URI)

Example 48 with Callback

use of com.linkedin.common.callback.Callback in project rest.li by linkedin.

the class Messages method toRestRequest.

/**
   * Converts a StreamRequest to RestRequest
   * @param streamRequest the stream request to be converted
   * @param callback the callback to be invoked when the rest request is constructed
   */
public static void toRestRequest(StreamRequest streamRequest, final Callback<RestRequest> callback) {
    final RestRequestBuilder builder = new RestRequestBuilder(streamRequest);
    Callback<ByteString> assemblyCallback = new Callback<ByteString>() {

        @Override
        public void onError(Throwable e) {
            callback.onError(e);
        }

        @Override
        public void onSuccess(ByteString result) {
            RestRequest restRequest = builder.setEntity(result).build();
            callback.onSuccess(restRequest);
        }
    };
    streamRequest.getEntityStream().setReader(new FullEntityReader(assemblyCallback));
}
Also used : FullEntityReader(com.linkedin.r2.message.stream.entitystream.FullEntityReader) Callback(com.linkedin.common.callback.Callback) TransportCallback(com.linkedin.r2.transport.common.bridge.common.TransportCallback) RestRequest(com.linkedin.r2.message.rest.RestRequest) ByteString(com.linkedin.data.ByteString) RestRequestBuilder(com.linkedin.r2.message.rest.RestRequestBuilder)

Example 49 with Callback

use of com.linkedin.common.callback.Callback in project rest.li by linkedin.

the class Messages method toRestResponse.

/**
   * Converts a StreamResponse to RestResponse
   * @param streamResponse the stream request to be converted
   * @param callback the callback to be invoked when the rest response is constructed
   * @param addContentLengthHeader whether the rest response should have content-length header
   */
public static void toRestResponse(StreamResponse streamResponse, final Callback<RestResponse> callback, final boolean addContentLengthHeader) {
    final RestResponseBuilder builder = new RestResponseBuilder(streamResponse);
    Callback<ByteString> assemblyCallback = new Callback<ByteString>() {

        @Override
        public void onError(Throwable e) {
            callback.onError(e);
        }

        @Override
        public void onSuccess(ByteString result) {
            if (addContentLengthHeader) {
                builder.setHeader(HttpConstants.CONTENT_LENGTH, String.valueOf(result.length()));
            }
            RestResponse restResponse = builder.setEntity(result).build();
            callback.onSuccess(restResponse);
        }
    };
    streamResponse.getEntityStream().setReader(new FullEntityReader(assemblyCallback));
}
Also used : FullEntityReader(com.linkedin.r2.message.stream.entitystream.FullEntityReader) Callback(com.linkedin.common.callback.Callback) TransportCallback(com.linkedin.r2.transport.common.bridge.common.TransportCallback) ByteString(com.linkedin.data.ByteString) RestResponse(com.linkedin.r2.message.rest.RestResponse) RestResponseBuilder(com.linkedin.r2.message.rest.RestResponseBuilder)

Example 50 with Callback

use of com.linkedin.common.callback.Callback in project rest.li by linkedin.

the class AsyncPoolImpl method get.

@Override
public Cancellable get(final Callback<T> callback) {
    // getter needs to add to wait queue atomically with check for empty pool
    // putter needs to add to pool atomically with check for empty wait queue
    boolean create = false;
    boolean reject = false;
    final LinkedDeque.Node<Callback<T>> node;
    final Callback<T> callbackWithTracking = new TimeTrackingCallback<T>(callback);
    for (; ; ) {
        TimedObject<T> obj = null;
        final State state;
        synchronized (_lock) {
            state = _state;
            if (state == State.RUNNING) {
                if (_strategy == Strategy.LRU) {
                    obj = _idle.pollFirst();
                } else {
                    obj = _idle.pollLast();
                }
                if (obj == null) {
                    if (_waiters.size() < _maxWaiters) {
                        // No objects available and the waiter list is not full; add to waiter list and break out of loop
                        node = _waiters.addLastNode(callbackWithTracking);
                        create = shouldCreate();
                    } else {
                        reject = true;
                        node = null;
                    }
                    break;
                }
            }
        }
        if (state != State.RUNNING) {
            // Defer execution of the callback until we are out of the synchronized block
            callbackWithTracking.onError(new IllegalStateException(_poolName + " is " + _state));
            return () -> false;
        }
        T rawObj = obj.get();
        if (_lifecycle.validateGet(rawObj)) {
            trc("dequeued an idle object");
            // Valid object; done
            synchronized (_lock) {
                _checkedOut++;
                _statsTracker.sampleMaxCheckedOut();
            }
            callbackWithTracking.onSuccess(rawObj);
            return () -> false;
        }
        // Invalid object, discard it and keep trying
        destroy(rawObj, true);
        trc("dequeued and disposed an invalid idle object");
    }
    if (reject) {
        // This is a recoverable exception. User can simply retry the failed get() operation.
        callbackWithTracking.onError(new SizeLimitExceededException("AsyncPool " + _poolName + " reached maximum waiter size: " + _maxWaiters));
        return null;
    }
    trc("enqueued a waiter");
    if (create) {
        create();
    }
    return new Cancellable() {

        @Override
        public boolean cancel() {
            synchronized (_lock) {
                return _waiters.removeNode(node) != null;
            }
        }
    };
}
Also used : SizeLimitExceededException(com.linkedin.r2.SizeLimitExceededException) SimpleCallback(com.linkedin.common.callback.SimpleCallback) Callback(com.linkedin.common.callback.Callback) LinkedDeque(com.linkedin.r2.util.LinkedDeque) Cancellable(com.linkedin.r2.util.Cancellable)

Aggregations

Callback (com.linkedin.common.callback.Callback)95 Test (org.testng.annotations.Test)64 AfterTest (org.testng.annotations.AfterTest)43 BeforeTest (org.testng.annotations.BeforeTest)43 RequestContext (com.linkedin.r2.message.RequestContext)37 RestResponse (com.linkedin.r2.message.rest.RestResponse)34 ByteString (com.linkedin.data.ByteString)29 RestRequest (com.linkedin.r2.message.rest.RestRequest)28 StreamResponse (com.linkedin.r2.message.stream.StreamResponse)28 AsyncStatusCollectionResource (com.linkedin.restli.server.twitter.AsyncStatusCollectionResource)28 URI (java.net.URI)28 RestLiCallback (com.linkedin.restli.internal.server.RestLiCallback)26 FilterChainCallback (com.linkedin.restli.internal.server.filter.FilterChainCallback)26 ResourceMethodDescriptor (com.linkedin.restli.internal.server.model.ResourceMethodDescriptor)26 ResourceModel (com.linkedin.restli.internal.server.model.ResourceModel)26 RequestExecutionCallback (com.linkedin.restli.server.RequestExecutionCallback)26 RestLiTestHelper.buildResourceModel (com.linkedin.restli.server.test.RestLiTestHelper.buildResourceModel)26 EasyMock.anyObject (org.easymock.EasyMock.anyObject)26 StreamRequest (com.linkedin.r2.message.stream.StreamRequest)25 RestRequestBuilder (com.linkedin.r2.message.rest.RestRequestBuilder)22