Search in sources :

Example 1 with Task

use of com.linkedin.r2.transport.http.client.RateLimiter.Task in project rest.li by linkedin.

the class TestRestLiMethodInvocation method testStreaming.

@Test
public void testStreaming() throws RestLiSyntaxException, URISyntaxException {
    Map<String, ResourceModel> resourceModelMap = buildResourceModels(StatusCollectionResource.class, AsyncStatusCollectionResource.class, PromiseStatusCollectionResource.class, TaskStatusCollectionResource.class);
    final String payload = "{\"metadata\": \"someMetadata\"}";
    ResourceModel statusResourceModel = resourceModelMap.get("/statuses");
    ResourceModel asyncStatusResourceModel = resourceModelMap.get("/asyncstatuses");
    ResourceModel promiseStatusResourceModel = resourceModelMap.get("/promisestatuses");
    ResourceModel taskStatusResourceModel = resourceModelMap.get("/taskstatuses");
    ResourceMethodDescriptor methodDescriptor;
    StatusCollectionResource statusResource;
    AsyncStatusCollectionResource asyncStatusResource;
    PromiseStatusCollectionResource promiseStatusResource;
    TaskStatusCollectionResource taskStatusResource;
    //Sync Method Execution - Successful scenario
    methodDescriptor = statusResourceModel.findActionMethod("streamingAction", ResourceLevel.COLLECTION);
    statusResource = getMockResource(StatusCollectionResource.class);
    EasyMock.expect(statusResource.streamingAction(EasyMock.<String>anyObject(), EasyMock.<RestLiAttachmentReader>anyObject())).andReturn(1234l).once();
    checkInvocation(statusResource, methodDescriptor, "POST", version, "/statuses/?action=streamingAction", payload, null, new RequestExecutionCallback<RestResponse>() {

        @Override
        public void onError(Throwable e, RequestExecutionReport executionReport, RestLiAttachmentReader requestAttachmentReader, RestLiResponseAttachments responseAttachments) {
            Assert.fail("Request failed unexpectedly.");
        }

        @Override
        public void onSuccess(RestResponse result, RequestExecutionReport executionReport, RestLiResponseAttachments responseAttachments) {
        }
    }, false, false, new RestLiAttachmentReader(null), new RestLiResponseAttachments.Builder().build());
    //Sync Method Execution - Error scenario
    statusResource = getMockResource(StatusCollectionResource.class);
    EasyMock.expect(statusResource.streamingAction(EasyMock.<String>anyObject(), EasyMock.<RestLiAttachmentReader>anyObject())).andThrow(new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR)).once();
    checkInvocation(statusResource, methodDescriptor, "POST", version, "/statuses/?action=streamingAction", payload, null, new RequestExecutionCallback<RestResponse>() {

        @Override
        public void onError(Throwable e, RequestExecutionReport executionReport, RestLiAttachmentReader requestAttachmentReader, RestLiResponseAttachments responseAttachments) {
        }

        @Override
        public void onSuccess(RestResponse result, RequestExecutionReport executionReport, RestLiResponseAttachments responseAttachments) {
            Assert.fail("Request passed unexpectedly.");
        }
    }, false, false, new RestLiAttachmentReader(null), new RestLiResponseAttachments.Builder().build());
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //Callback Method Execution - Successful scenario
    methodDescriptor = asyncStatusResourceModel.findMethod(ResourceMethod.ACTION);
    asyncStatusResource = getMockResource(AsyncStatusCollectionResource.class);
    asyncStatusResource.streamingAction(EasyMock.<String>anyObject(), EasyMock.<RestLiAttachmentReader>anyObject(), EasyMock.<Callback<Long>>anyObject());
    EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {

        @Override
        public Object answer() throws Throwable {
            @SuppressWarnings("unchecked") Callback<Long> callback = (Callback<Long>) EasyMock.getCurrentArguments()[2];
            callback.onSuccess(1234l);
            return null;
        }
    });
    checkInvocation(asyncStatusResource, methodDescriptor, "POST", version, "/asyncstatuses/?action=streamingAction", payload, null, new RequestExecutionCallback<RestResponse>() {

        @Override
        public void onError(Throwable e, RequestExecutionReport executionReport, RestLiAttachmentReader requestAttachmentReader, RestLiResponseAttachments responseAttachments) {
            Assert.fail("Request failed unexpectedly.");
        }

        @Override
        public void onSuccess(RestResponse result, RequestExecutionReport executionReport, RestLiResponseAttachments responseAttachments) {
        }
    }, false, false, new RestLiAttachmentReader(null), new RestLiResponseAttachments.Builder().build());
    //Callback Method Execution - Error scenario
    asyncStatusResource = getMockResource(AsyncStatusCollectionResource.class);
    asyncStatusResource.streamingAction(EasyMock.<String>anyObject(), EasyMock.<RestLiAttachmentReader>anyObject(), EasyMock.<Callback<Long>>anyObject());
    EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {

        @Override
        public Object answer() throws Throwable {
            @SuppressWarnings("unchecked") Callback<Long> callback = (Callback<Long>) EasyMock.getCurrentArguments()[2];
            callback.onError(new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR));
            return null;
        }
    });
    checkInvocation(asyncStatusResource, methodDescriptor, "POST", version, "/asyncstatuses/?action=streamingAction", payload, null, new RequestExecutionCallback<RestResponse>() {

        @Override
        public void onError(Throwable e, RequestExecutionReport executionReport, RestLiAttachmentReader requestAttachmentReader, RestLiResponseAttachments responseAttachments) {
        }

        @Override
        public void onSuccess(RestResponse result, RequestExecutionReport executionReport, RestLiResponseAttachments responseAttachments) {
            Assert.fail("Request passed unexpectedly.");
        }
    }, false, false, new RestLiAttachmentReader(null), new RestLiResponseAttachments.Builder().build());
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //Promise Method Execution - Successful scenario
    methodDescriptor = promiseStatusResourceModel.findActionMethod("streamingAction", ResourceLevel.COLLECTION);
    promiseStatusResource = getMockResource(PromiseStatusCollectionResource.class);
    promiseStatusResource.streamingAction(EasyMock.<String>anyObject(), EasyMock.<RestLiAttachmentReader>anyObject());
    EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {

        @Override
        public Object answer() throws Throwable {
            final SettablePromise<Long> result = Promises.settable();
            final Runnable requestHandler = new Runnable() {

                public void run() {
                    try {
                        result.done(1234l);
                    } catch (final Throwable throwable) {
                        result.fail(throwable);
                    }
                }
            };
            _scheduler.schedule(requestHandler, 0, TimeUnit.MILLISECONDS);
            return result;
        }
    });
    checkInvocation(promiseStatusResource, methodDescriptor, "POST", version, "/promisestatuses/?action=streamingAction", payload, null, new RequestExecutionCallback<RestResponse>() {

        @Override
        public void onError(Throwable e, RequestExecutionReport executionReport, RestLiAttachmentReader requestAttachmentReader, RestLiResponseAttachments responseAttachments) {
            Assert.fail("Request failed unexpectedly.");
        }

        @Override
        public void onSuccess(RestResponse result, RequestExecutionReport executionReport, RestLiResponseAttachments responseAttachments) {
        }
    }, false, false, new RestLiAttachmentReader(null), new RestLiResponseAttachments.Builder().build());
    //Promise Method Execution - Error scenario
    promiseStatusResource = getMockResource(PromiseStatusCollectionResource.class);
    promiseStatusResource.streamingAction(EasyMock.<String>anyObject(), EasyMock.<RestLiAttachmentReader>anyObject());
    EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {

        @Override
        public Object answer() throws Throwable {
            final SettablePromise<Long> result = Promises.settable();
            final Runnable requestHandler = new Runnable() {

                public void run() {
                    result.fail(new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR));
                }
            };
            _scheduler.schedule(requestHandler, 0, TimeUnit.MILLISECONDS);
            return result;
        }
    });
    checkInvocation(promiseStatusResource, methodDescriptor, "POST", version, "/promisestatuses/?action=streamingAction", payload, null, new RequestExecutionCallback<RestResponse>() {

        @Override
        public void onError(Throwable e, RequestExecutionReport executionReport, RestLiAttachmentReader requestAttachmentReader, RestLiResponseAttachments responseAttachments) {
        }

        @Override
        public void onSuccess(RestResponse result, RequestExecutionReport executionReport, RestLiResponseAttachments responseAttachments) {
            Assert.fail("Request passed unexpectedly.");
        }
    }, false, false, new RestLiAttachmentReader(null), new RestLiResponseAttachments.Builder().build());
    ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    //Task Method Execution - Successful scenario
    methodDescriptor = taskStatusResourceModel.findMethod(ResourceMethod.ACTION);
    taskStatusResource = getMockResource(TaskStatusCollectionResource.class);
    taskStatusResource.streamingAction(EasyMock.<String>anyObject(), EasyMock.<RestLiAttachmentReader>anyObject());
    EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {

        @Override
        public Object answer() throws Throwable {
            return new BaseTask<Long>() {

                protected Promise<Long> run(final Context context) throws Exception {
                    return Promises.value(1234l);
                }
            };
        }
    });
    checkInvocation(taskStatusResource, methodDescriptor, "POST", version, "/taskstatuses/?action=streamingAction", payload, null, new RequestExecutionCallback<RestResponse>() {

        @Override
        public void onError(Throwable e, RequestExecutionReport executionReport, RestLiAttachmentReader requestAttachmentReader, RestLiResponseAttachments responseAttachments) {
            Assert.fail("Request failed unexpectedly.");
        }

        @Override
        public void onSuccess(RestResponse result, RequestExecutionReport executionReport, RestLiResponseAttachments responseAttachments) {
        }
    }, false, false, new RestLiAttachmentReader(null), new RestLiResponseAttachments.Builder().build());
    //Task Method Execution - Error scenario
    taskStatusResource = getMockResource(TaskStatusCollectionResource.class);
    taskStatusResource.streamingAction(EasyMock.<String>anyObject(), EasyMock.<RestLiAttachmentReader>anyObject());
    EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {

        @Override
        public Object answer() throws Throwable {
            return new BaseTask<Long>() {

                protected Promise<Long> run(final Context context) throws Exception {
                    return Promises.error(new RestLiServiceException(HttpStatus.S_500_INTERNAL_SERVER_ERROR));
                }
            };
        }
    });
    checkInvocation(taskStatusResource, methodDescriptor, "POST", version, "/taskstatuses/?action=streamingAction", payload, null, new RequestExecutionCallback<RestResponse>() {

        @Override
        public void onError(Throwable e, RequestExecutionReport executionReport, RestLiAttachmentReader requestAttachmentReader, RestLiResponseAttachments responseAttachments) {
        }

        @Override
        public void onSuccess(RestResponse result, RequestExecutionReport executionReport, RestLiResponseAttachments responseAttachments) {
            Assert.fail("Request passed unexpectedly.");
        }
    }, false, false, new RestLiAttachmentReader(null), new RestLiResponseAttachments.Builder().build());
}
Also used : ResourceMethodDescriptor(com.linkedin.restli.internal.server.model.ResourceMethodDescriptor) RequestExecutionReportBuilder(com.linkedin.restli.server.RequestExecutionReportBuilder) EngineBuilder(com.linkedin.parseq.EngineBuilder) RestLiArgumentBuilder(com.linkedin.restli.internal.server.methods.arguments.RestLiArgumentBuilder) RestRequestBuilder(com.linkedin.r2.message.rest.RestRequestBuilder) ErrorResponseBuilder(com.linkedin.restli.internal.server.response.ErrorResponseBuilder) ByteString(com.linkedin.data.ByteString) CustomString(com.linkedin.restli.server.custom.types.CustomString) RestLiServiceException(com.linkedin.restli.server.RestLiServiceException) ResourceModel(com.linkedin.restli.internal.server.model.ResourceModel) RestLiTestHelper.buildResourceModel(com.linkedin.restli.server.test.RestLiTestHelper.buildResourceModel) TaskStatusCollectionResource(com.linkedin.restli.server.twitter.TaskStatusCollectionResource) StatusCollectionResource(com.linkedin.restli.server.twitter.StatusCollectionResource) AsyncStatusCollectionResource(com.linkedin.restli.server.twitter.AsyncStatusCollectionResource) CustomStatusCollectionResource(com.linkedin.restli.server.twitter.CustomStatusCollectionResource) PromiseStatusCollectionResource(com.linkedin.restli.server.twitter.PromiseStatusCollectionResource) RestLiResponseAttachments(com.linkedin.restli.server.RestLiResponseAttachments) PagingContext(com.linkedin.restli.server.PagingContext) ResourceContext(com.linkedin.restli.server.ResourceContext) ServerResourceContext(com.linkedin.restli.internal.server.ServerResourceContext) FilterRequestContext(com.linkedin.restli.server.filter.FilterRequestContext) Context(com.linkedin.parseq.Context) RequestContext(com.linkedin.r2.message.RequestContext) TaskStatusCollectionResource(com.linkedin.restli.server.twitter.TaskStatusCollectionResource) PromiseStatusCollectionResource(com.linkedin.restli.server.twitter.PromiseStatusCollectionResource) RestResponse(com.linkedin.r2.message.rest.RestResponse) SettablePromise(com.linkedin.parseq.promise.SettablePromise) RequestExecutionReport(com.linkedin.restli.server.RequestExecutionReport) AsyncStatusCollectionResource(com.linkedin.restli.server.twitter.AsyncStatusCollectionResource) RestException(com.linkedin.r2.message.rest.RestException) URISyntaxException(java.net.URISyntaxException) RestLiServiceException(com.linkedin.restli.server.RestLiServiceException) RoutingException(com.linkedin.restli.server.RoutingException) RestLiSyntaxException(com.linkedin.restli.internal.server.util.RestLiSyntaxException) SettablePromise(com.linkedin.parseq.promise.SettablePromise) Promise(com.linkedin.parseq.promise.Promise) Callback(com.linkedin.common.callback.Callback) RestLiCallback(com.linkedin.restli.internal.server.RestLiCallback) FilterChainCallback(com.linkedin.restli.internal.server.filter.FilterChainCallback) RequestExecutionCallback(com.linkedin.restli.server.RequestExecutionCallback) CustomLong(com.linkedin.restli.server.custom.types.CustomLong) EasyMock.anyObject(org.easymock.EasyMock.anyObject) RestLiAttachmentReader(com.linkedin.restli.common.attachments.RestLiAttachmentReader) Test(org.testng.annotations.Test) AfterTest(org.testng.annotations.AfterTest) BeforeTest(org.testng.annotations.BeforeTest)

Example 2 with Task

use of com.linkedin.r2.transport.http.client.RateLimiter.Task 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 + ")");
}
Also used : Task(com.linkedin.r2.transport.http.client.RateLimiter.Task) CountDownLatch(java.util.concurrent.CountDownLatch) ExponentialBackOffRateLimiter(com.linkedin.r2.transport.http.client.ExponentialBackOffRateLimiter) SimpleCallback(com.linkedin.common.callback.SimpleCallback) ExponentialBackOffRateLimiter(com.linkedin.r2.transport.http.client.ExponentialBackOffRateLimiter) RateLimiter(com.linkedin.r2.transport.http.client.RateLimiter) Test(org.testng.annotations.Test)

Example 3 with Task

use of com.linkedin.r2.transport.http.client.RateLimiter.Task in project rest.li by linkedin.

the class TestRestLiMethodInvocation method testExecutionReport.

@Test
public void testExecutionReport() throws RestLiSyntaxException, URISyntaxException {
    Map<String, ResourceModel> resourceModelMap = buildResourceModels(StatusCollectionResource.class, AsyncStatusCollectionResource.class, PromiseStatusCollectionResource.class, TaskStatusCollectionResource.class);
    ResourceModel statusResourceModel = resourceModelMap.get("/statuses");
    ResourceModel asyncStatusResourceModel = resourceModelMap.get("/asyncstatuses");
    ResourceModel promiseStatusResourceModel = resourceModelMap.get("/promisestatuses");
    ResourceModel taskStatusResourceModel = resourceModelMap.get("/taskstatuses");
    ResourceMethodDescriptor methodDescriptor;
    StatusCollectionResource statusResource;
    AsyncStatusCollectionResource asyncStatusResource;
    PromiseStatusCollectionResource promiseStatusResource;
    TaskStatusCollectionResource taskStatusResource;
    // #1: Sync Method Execution
    methodDescriptor = statusResourceModel.findMethod(ResourceMethod.GET);
    statusResource = getMockResource(StatusCollectionResource.class);
    EasyMock.expect(statusResource.get(eq(1L))).andReturn(null).once();
    checkInvocation(statusResource, methodDescriptor, "GET", version, "/statuses/1", null, buildPathKeys("statusID", 1L), new RequestExecutionCallback<RestResponse>() {

        //A 404 is considered an error by rest.li
        @Override
        public void onError(Throwable e, RequestExecutionReport executionReport, RestLiAttachmentReader requestAttachmentReader, RestLiResponseAttachments responseAttachments) {
            Assert.assertNull(executionReport.getParseqTrace(), "There should be no parseq trace!");
        }

        @Override
        public void onSuccess(RestResponse result, RequestExecutionReport executionReport, RestLiResponseAttachments responseAttachments) {
            Assert.fail("Request failed unexpectedly.");
        }
    }, true, false);
    // #2: Callback based Async Method Execution
    Capture<RequestExecutionReport> requestExecutionReportCapture = new Capture<RequestExecutionReport>();
    RestLiCallback<?> callback = getCallback(requestExecutionReportCapture);
    methodDescriptor = asyncStatusResourceModel.findMethod(ResourceMethod.GET);
    asyncStatusResource = getMockResource(AsyncStatusCollectionResource.class);
    asyncStatusResource.get(eq(1L), EasyMock.<Callback<Status>>anyObject());
    EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {

        @Override
        public Object answer() throws Throwable {
            @SuppressWarnings("unchecked") Callback<Status> callback = (Callback<Status>) EasyMock.getCurrentArguments()[1];
            callback.onSuccess(null);
            return null;
        }
    });
    EasyMock.replay(asyncStatusResource);
    checkAsyncInvocation(asyncStatusResource, callback, methodDescriptor, "GET", version, "/asyncstatuses/1", null, buildPathKeys("statusID", 1L), true);
    Assert.assertNull(requestExecutionReportCapture.getValue().getParseqTrace());
    // #3: Promise based Async Method Execution
    methodDescriptor = promiseStatusResourceModel.findMethod(ResourceMethod.GET);
    promiseStatusResource = getMockResource(PromiseStatusCollectionResource.class);
    EasyMock.expect(promiseStatusResource.get(eq(1L))).andReturn(Promises.<Status>value(null)).once();
    checkInvocation(promiseStatusResource, methodDescriptor, "GET", version, "/promisestatuses/1", null, buildPathKeys("statusID", 1L), new RequestExecutionCallback<RestResponse>() {

        //A 404 is considered an error by rest.li
        @Override
        public void onError(Throwable e, RequestExecutionReport executionReport, RestLiAttachmentReader requestAttachmentReader, RestLiResponseAttachments responseAttachments) {
            Assert.assertNotNull(executionReport.getParseqTrace(), "There should be a valid parseq trace!");
        }

        @Override
        public void onSuccess(RestResponse result, RequestExecutionReport executionReport, RestLiResponseAttachments responseAttachments) {
            Assert.fail("Request failed unexpectedly.");
        }
    }, true, false);
    // #4: Task based Async Method Execution
    methodDescriptor = taskStatusResourceModel.findMethod(ResourceMethod.GET);
    taskStatusResource = getMockResource(TaskStatusCollectionResource.class);
    EasyMock.expect(taskStatusResource.get(eq(1L))).andReturn(Task.callable("myTask", new Callable<Status>() {

        @Override
        public Status call() throws Exception {
            return new Status();
        }
    })).once();
    checkInvocation(taskStatusResource, methodDescriptor, "GET", version, "/taskstatuses/1", null, buildPathKeys("statusID", 1L), new RequestExecutionCallback<RestResponse>() {

        @Override
        public void onError(Throwable e, RequestExecutionReport executionReport, RestLiAttachmentReader requestAttachmentReader, RestLiResponseAttachments responseAttachments) {
            Assert.fail("Request failed unexpectedly.");
        }

        @Override
        public void onSuccess(RestResponse result, RequestExecutionReport executionReport, RestLiResponseAttachments responseAttachments) {
            Assert.assertNotNull(executionReport.getParseqTrace());
        }
    }, true, false);
}
Also used : Status(com.linkedin.restli.server.twitter.TwitterTestDataModels.Status) HttpStatus(com.linkedin.restli.common.HttpStatus) TaskStatusCollectionResource(com.linkedin.restli.server.twitter.TaskStatusCollectionResource) PromiseStatusCollectionResource(com.linkedin.restli.server.twitter.PromiseStatusCollectionResource) RestResponse(com.linkedin.r2.message.rest.RestResponse) ResourceMethodDescriptor(com.linkedin.restli.internal.server.model.ResourceMethodDescriptor) ByteString(com.linkedin.data.ByteString) CustomString(com.linkedin.restli.server.custom.types.CustomString) RequestExecutionReport(com.linkedin.restli.server.RequestExecutionReport) AsyncStatusCollectionResource(com.linkedin.restli.server.twitter.AsyncStatusCollectionResource) Capture(org.easymock.Capture) RestException(com.linkedin.r2.message.rest.RestException) URISyntaxException(java.net.URISyntaxException) RestLiServiceException(com.linkedin.restli.server.RestLiServiceException) RoutingException(com.linkedin.restli.server.RoutingException) RestLiSyntaxException(com.linkedin.restli.internal.server.util.RestLiSyntaxException) Callback(com.linkedin.common.callback.Callback) RestLiCallback(com.linkedin.restli.internal.server.RestLiCallback) FilterChainCallback(com.linkedin.restli.internal.server.filter.FilterChainCallback) RequestExecutionCallback(com.linkedin.restli.server.RequestExecutionCallback) ResourceModel(com.linkedin.restli.internal.server.model.ResourceModel) RestLiTestHelper.buildResourceModel(com.linkedin.restli.server.test.RestLiTestHelper.buildResourceModel) TaskStatusCollectionResource(com.linkedin.restli.server.twitter.TaskStatusCollectionResource) StatusCollectionResource(com.linkedin.restli.server.twitter.StatusCollectionResource) AsyncStatusCollectionResource(com.linkedin.restli.server.twitter.AsyncStatusCollectionResource) CustomStatusCollectionResource(com.linkedin.restli.server.twitter.CustomStatusCollectionResource) PromiseStatusCollectionResource(com.linkedin.restli.server.twitter.PromiseStatusCollectionResource) EasyMock.anyObject(org.easymock.EasyMock.anyObject) RestLiAttachmentReader(com.linkedin.restli.common.attachments.RestLiAttachmentReader) RestLiResponseAttachments(com.linkedin.restli.server.RestLiResponseAttachments) Test(org.testng.annotations.Test) AfterTest(org.testng.annotations.AfterTest) BeforeTest(org.testng.annotations.BeforeTest)

Example 4 with Task

use of com.linkedin.r2.transport.http.client.RateLimiter.Task 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();
                }
            });
        }
    });
}
Also used : Task(com.linkedin.r2.transport.http.client.RateLimiter.Task) SimpleCallback(com.linkedin.common.callback.SimpleCallback) Callback(com.linkedin.common.callback.Callback) SimpleCallback(com.linkedin.common.callback.SimpleCallback) SizeLimitExceededException(com.linkedin.r2.SizeLimitExceededException)

Example 5 with Task

use of com.linkedin.r2.transport.http.client.RateLimiter.Task in project rest.li by linkedin.

the class HttpNettyClient method writeRequest.

private void writeRequest(RestRequest request, RequestContext requestContext, Map<String, String> wireAttrs, final TimeoutTransportCallback<RestResponse> callback) {
    State state = _state.get();
    if (state != State.RUNNING) {
        errorResponse(callback, new IllegalStateException("Client is " + state));
        return;
    }
    URI uri = request.getURI();
    String scheme = uri.getScheme();
    if (!"http".equalsIgnoreCase(scheme) && !"https".equalsIgnoreCase(scheme)) {
        errorResponse(callback, new IllegalArgumentException("Unknown scheme: " + scheme + " (only http/https is supported)"));
        return;
    }
    String host = uri.getHost();
    int port = uri.getPort();
    if (port == -1) {
        port = "http".equalsIgnoreCase(scheme) ? HTTP_DEFAULT_PORT : HTTPS_DEFAULT_PORT;
    }
    final RestRequest newRequest = new RestRequestBuilder(request).overwriteHeaders(WireAttributeHelper.toWireAttributes(wireAttrs)).build();
    final SocketAddress address;
    try {
        // TODO investigate DNS resolution and timing
        InetAddress inetAddress = InetAddress.getByName(host);
        address = new InetSocketAddress(inetAddress, port);
        requestContext.putLocalAttr(R2Constants.REMOTE_SERVER_ADDR, inetAddress.getHostAddress());
    } catch (UnknownHostException e) {
        errorResponse(callback, e);
        return;
    }
    requestContext.putLocalAttr(R2Constants.HTTP_PROTOCOL_VERSION, HttpProtocolVersion.HTTP_1_1);
    final AsyncPool<Channel> pool;
    try {
        pool = _channelPoolManager.getPoolForAddress(address);
    } catch (IllegalStateException e) {
        errorResponse(callback, e);
        return;
    }
    final Cancellable pendingGet = pool.get(new Callback<Channel>() {

        @Override
        public void onSuccess(final Channel channel) {
            // This handler ensures the channel is returned to the pool at the end of the
            // Netty pipeline.
            channel.attr(ChannelPoolHandler.CHANNEL_POOL_ATTR_KEY).set(pool);
            callback.addTimeoutTask(new Runnable() {

                @Override
                public void run() {
                    AsyncPool<Channel> pool = channel.attr(ChannelPoolHandler.CHANNEL_POOL_ATTR_KEY).getAndRemove();
                    if (pool != null) {
                        pool.dispose(channel);
                    }
                }
            });
            // This handler invokes the callback with the response once it arrives.
            channel.attr(RAPResponseHandler.CALLBACK_ATTR_KEY).set(callback);
            final State state = _state.get();
            if (state == State.REQUESTS_STOPPING || state == State.SHUTDOWN) {
                // In this case, we acquired a channel from the pool as request processing is halting.
                // The shutdown task might not timeout this callback, since it may already have scanned
                // all the channels for pending requests before we set the callback as the channel
                // attachment.  The TimeoutTransportCallback ensures the user callback in never
                // invoked more than once, so it is safe to invoke it unconditionally.
                errorResponse(callback, new TimeoutException("Operation did not complete before shutdown"));
                return;
            }
            // here we want the exception in outbound operations to be passed back through pipeline so that
            // the user callback would be invoked with the exception and the channel can be put back into the pool
            channel.writeAndFlush(newRequest).addListener(ChannelFutureListener.FIRE_EXCEPTION_ON_FAILURE);
        }

        @Override
        public void onError(Throwable e) {
            errorResponse(callback, e);
        }
    });
    if (pendingGet != null) {
        callback.addTimeoutTask(new Runnable() {

            @Override
            public void run() {
                pendingGet.cancel();
            }
        });
    }
}
Also used : UnknownHostException(java.net.UnknownHostException) InetSocketAddress(java.net.InetSocketAddress) Cancellable(com.linkedin.r2.util.Cancellable) NioSocketChannel(io.netty.channel.socket.nio.NioSocketChannel) Channel(io.netty.channel.Channel) URI(java.net.URI) RestRequest(com.linkedin.r2.message.rest.RestRequest) TimeoutRunnable(com.linkedin.r2.util.TimeoutRunnable) RestRequestBuilder(com.linkedin.r2.message.rest.RestRequestBuilder) SocketAddress(java.net.SocketAddress) InetSocketAddress(java.net.InetSocketAddress) InetAddress(java.net.InetAddress) TimeoutException(java.util.concurrent.TimeoutException)

Aggregations

Test (org.testng.annotations.Test)7 CountDownLatch (java.util.concurrent.CountDownLatch)4 Callback (com.linkedin.common.callback.Callback)3 SimpleCallback (com.linkedin.common.callback.SimpleCallback)3 ByteString (com.linkedin.data.ByteString)3 RestException (com.linkedin.r2.message.rest.RestException)3 RestResponse (com.linkedin.r2.message.rest.RestResponse)3 Task (com.linkedin.r2.transport.http.client.RateLimiter.Task)3 RequestContext (com.linkedin.r2.message.RequestContext)2 RestRequest (com.linkedin.r2.message.rest.RestRequest)2 RestRequestBuilder (com.linkedin.r2.message.rest.RestRequestBuilder)2 ExponentialBackOffRateLimiter (com.linkedin.r2.transport.http.client.ExponentialBackOffRateLimiter)2 RateLimiter (com.linkedin.r2.transport.http.client.RateLimiter)2 Cancellable (com.linkedin.r2.util.Cancellable)2 RestLiAttachmentReader (com.linkedin.restli.common.attachments.RestLiAttachmentReader)2 RestLiCallback (com.linkedin.restli.internal.server.RestLiCallback)2 FilterChainCallback (com.linkedin.restli.internal.server.filter.FilterChainCallback)2 ResourceMethodDescriptor (com.linkedin.restli.internal.server.model.ResourceMethodDescriptor)2 ResourceModel (com.linkedin.restli.internal.server.model.ResourceModel)2 RestLiSyntaxException (com.linkedin.restli.internal.server.util.RestLiSyntaxException)2