Search in sources :

Example 26 with Endpoint

use of com.palantir.dialogue.Endpoint in project dialogue by palantir.

the class UserAgentEndpointChannelTest method testServiceNameIsNotValidConjureAgent.

@Test
public void testServiceNameIsNotValidConjureAgent() {
    EndpointChannel channel = UserAgentEndpointChannel.create(delegate, new Endpoint() {

        @Override
        public void renderPath(Map<String, String> _params, UrlBuilder _url) {
        }

        @Override
        public HttpMethod httpMethod() {
            return HttpMethod.GET;
        }

        @Override
        public String serviceName() {
            return "Service_Name";
        }

        @Override
        public String endpointName() {
            return "endpoint";
        }

        @Override
        public String version() {
            return "4.5.6";
        }
    }, baseAgent);
    // Special case: In IDEs, tests are run against classes (not JARs) and thus don't carry versions.
    String dialogueVersion = Optional.ofNullable(Channel.class.getPackage().getImplementationVersion()).orElse("0.0.0");
    channel.execute(request);
    verify(delegate).execute(requestCaptor.capture());
    assertThat(requestCaptor.getValue().headerParams().get("user-agent")).containsExactly("test-class/1.2.3 dialogue/" + dialogueVersion);
}
Also used : TestEndpoint(com.palantir.dialogue.TestEndpoint) Endpoint(com.palantir.dialogue.Endpoint) Channel(com.palantir.dialogue.Channel) EndpointChannel(com.palantir.dialogue.EndpointChannel) EndpointChannel(com.palantir.dialogue.EndpointChannel) UrlBuilder(com.palantir.dialogue.UrlBuilder) HttpMethod(com.palantir.dialogue.HttpMethod) Test(org.junit.jupiter.api.Test)

Example 27 with Endpoint

use of com.palantir.dialogue.Endpoint in project dialogue by palantir.

the class PinUntilErrorNodeSelectionStrategyChannel method maybeExecute.

@Override
public Optional<ListenableFuture<Response>> maybeExecute(Endpoint endpoint, Request request, LimitEnforcement limitEnforcement) {
    int pin = currentPin.get();
    PinChannel channel = nodeList.get(pin);
    // n.b. StickyAttachments.maybeExecute uses the delegate PinChannel, which bypasses the FutureCallback
    // instrumentation below on subsequent "sticky" requests.
    Optional<ListenableFuture<Response>> maybeResponse = StickyAttachments.maybeAddStickyToken(channel, endpoint, request, limitEnforcement);
    if (!maybeResponse.isPresent()) {
        return Optional.empty();
    }
    DialogueFutures.addDirectCallback(maybeResponse.get(), new FutureCallback<>() {

        @Override
        public void onSuccess(Response response) {
            // even if a couple of them get rate limited in the middle.
            if (Responses.isServerErrorRange(response) || (Responses.isQosStatus(response) && !Responses.isTooManyRequests(response))) {
                OptionalInt next = incrementHostIfNecessary(pin);
                instrumentation.receivedErrorStatus(pin, channel, response, next);
            } else {
                instrumentation.successfulResponse(channel.stableIndex());
            }
        }

        @Override
        public void onFailure(Throwable throwable) {
            OptionalInt next = incrementHostIfNecessary(pin);
            instrumentation.receivedThrowable(pin, channel, throwable, next);
        }
    });
    return maybeResponse;
}
Also used : Response(com.palantir.dialogue.Response) ListenableFuture(com.google.common.util.concurrent.ListenableFuture) OptionalInt(java.util.OptionalInt) Endpoint(com.palantir.dialogue.Endpoint)

Example 28 with Endpoint

use of com.palantir.dialogue.Endpoint in project dialogue by palantir.

the class QueuedChannel method scheduleNextTask.

/**
 * Get the next call and attempt to execute it. If it is runnable, wire up the underlying future to the one
 * previously returned to the caller. If it is not runnable, add it back into the queue. Returns true if more
 * tasks may be able to be scheduled, and false otherwise.
 */
private boolean scheduleNextTask() {
    DeferredCall queueHead = queuedCalls.poll();
    if (queueHead == null) {
        return false;
    }
    SettableFuture<Response> queuedResponse = queueHead.response();
    // request will be quickly cancelled in that case.
    if (queuedResponse.isDone()) {
        decrementQueueSize();
        queueHead.span().complete();
        queueHead.timer().stop();
        return true;
    }
    try (CloseableSpan ignored = queueHead.span().attach()) {
        Endpoint endpoint = queueHead.endpoint();
        Optional<ListenableFuture<Response>> maybeResponse = delegate.maybeExecute(endpoint, queueHead.request(), DO_NOT_SKIP_LIMITS);
        if (maybeResponse.isPresent()) {
            decrementQueueSize();
            ListenableFuture<Response> response = maybeResponse.get();
            queueHead.span().complete();
            queueHead.timer().stop();
            DialogueFutures.addDirectCallback(response, new ForwardAndSchedule(queuedResponse));
            DialogueFutures.addDirectListener(queuedResponse, () -> {
                if (queuedResponse.isCancelled()) {
                    // Currently cancel(false) will be converted to cancel(true)
                    if (!response.cancel(true) && log.isDebugEnabled()) {
                        log.debug("Failed to cancel delegate response, it should be reported by ForwardAndSchedule " + "logging", SafeArg.of("channel", channelName), SafeArg.of("service", endpoint.serviceName()), SafeArg.of("endpoint", endpoint.endpointName()));
                    }
                }
            });
            return true;
        } else {
            if (!queuedCalls.offerFirst(queueHead)) {
                // Should never happen, ConcurrentLinkedDeque has no maximum size
                log.error("Failed to add an attempted call back to the deque", SafeArg.of("channel", channelName), SafeArg.of("service", endpoint.serviceName()), SafeArg.of("endpoint", endpoint.endpointName()));
                decrementQueueSize();
                queueHead.timer().stop();
                if (!queuedResponse.setException(new SafeRuntimeException("Failed to req-queue request", SafeArg.of("channel", channelName), SafeArg.of("service", endpoint.serviceName()), SafeArg.of("endpoint", endpoint.endpointName())))) {
                    if (log.isDebugEnabled()) {
                        log.debug("Queued response has already been completed", SafeArg.of("channel", channelName), SafeArg.of("service", endpoint.serviceName()), SafeArg.of("endpoint", endpoint.endpointName()));
                    }
                }
            }
            return false;
        }
    }
}
Also used : Response(com.palantir.dialogue.Response) Endpoint(com.palantir.dialogue.Endpoint) SafeRuntimeException(com.palantir.logsafe.exceptions.SafeRuntimeException) CloseableSpan(com.palantir.tracing.CloseableSpan) ListenableFuture(com.google.common.util.concurrent.ListenableFuture)

Example 29 with Endpoint

use of com.palantir.dialogue.Endpoint in project dialogue by palantir.

the class QueuedChannel method maybeExecute.

/**
 * Enqueues and tries to schedule as many queued tasks as possible.
 */
@VisibleForTesting
@SuppressWarnings("PreferJavaTimeOverload")
Optional<ListenableFuture<Response>> maybeExecute(Endpoint endpoint, Request request) {
    // Queuing adds contention between threads and should be avoided unless we need to shed load.
    if (queueSizeEstimate.get() <= 0) {
        Optional<ListenableFuture<Response>> maybeResult = delegate.maybeExecute(endpoint, request, DO_NOT_SKIP_LIMITS);
        if (maybeResult.isPresent()) {
            ListenableFuture<Response> result = maybeResult.get();
            DialogueFutures.addDirectListener(result, this::onCompletion);
            // While the queue was avoid, this is equivalent to spending zero time on the queue.
            if (shouldRecordQueueMetrics) {
                queuedTime.update(0, TimeUnit.NANOSECONDS);
            }
            return maybeResult;
        }
    }
    // maybeExecute may take sufficiently long that other requests could be queued.
    if (queueSizeEstimate.get() >= maxQueueSize) {
        return Optional.empty();
    }
    shouldRecordQueueMetrics = true;
    DeferredCall components = DeferredCall.builder().endpoint(endpoint).request(request).response(SettableFuture.create()).span(DetachedSpan.start("Dialogue-request-enqueued")).timer(queuedTime.time()).build();
    if (!queuedCalls.offer(components)) {
        // Should never happen, ConcurrentLinkedDeque has no maximum size
        return Optional.empty();
    }
    int newSize = incrementQueueSize();
    if (log.isDebugEnabled()) {
        log.debug("Request queued {} on channel {}", SafeArg.of("queueSize", newSize), SafeArg.of("channelName", channelName));
    }
    schedule();
    return Optional.of(components.response());
}
Also used : Response(com.palantir.dialogue.Response) ListenableFuture(com.google.common.util.concurrent.ListenableFuture) Endpoint(com.palantir.dialogue.Endpoint) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Example 30 with Endpoint

use of com.palantir.dialogue.Endpoint in project dialogue by palantir.

the class SimulationTest method slowdown_and_error_thresholds.

@SimulationCase
public void slowdown_and_error_thresholds(Strategy strategy) {
    Endpoint getEndpoint = SimulationUtils.endpoint("endpoint", HttpMethod.GET);
    int errorThreshold = 40;
    int slowdownThreshold = 30;
    servers = servers(SimulationServer.builder().serverName("fast").simulation(simulation).handler(getEndpoint, h -> h.respond200UntilCapacity(500, errorThreshold).linearResponseTime(Duration.ofMillis(600), slowdownThreshold)).build(), SimulationServer.builder().serverName("medium").simulation(simulation).handler(getEndpoint, h -> h.respond200UntilCapacity(500, errorThreshold).linearResponseTime(Duration.ofMillis(800), slowdownThreshold)).build(), SimulationServer.builder().serverName("slightly_slow").simulation(simulation).handler(getEndpoint, h -> h.respond200UntilCapacity(500, errorThreshold).linearResponseTime(Duration.ofMillis(1000), slowdownThreshold)).build());
    st = strategy;
    result = Benchmark.builder().simulation(simulation).requestsPerSecond(500).sendUntil(Duration.ofSeconds(20)).clients(10, _i -> strategy.getChannel(simulation, servers)).endpoints(getEndpoint).abortAfter(Duration.ofMinutes(10)).run();
}
Also used : BeforeEach(org.junit.jupiter.api.BeforeEach) Arrays(java.util.Arrays) Assertions.assertThat(org.assertj.core.api.Assertions.assertThat) Inherited(java.lang.annotation.Inherited) LoggerFactory(org.slf4j.LoggerFactory) Random(java.util.Random) AfterAll(org.junit.jupiter.api.AfterAll) Duration(java.time.Duration) Map(java.util.Map) Tracers(com.palantir.tracing.Tracers) Path(java.nio.file.Path) ExecutionMode(org.junit.jupiter.api.parallel.ExecutionMode) StandardOpenOption(java.nio.file.StandardOpenOption) Channel(com.palantir.dialogue.Channel) Collectors(java.util.stream.Collectors) StandardCharsets(java.nio.charset.StandardCharsets) TestInfo(org.junit.jupiter.api.TestInfo) TestResponse(com.palantir.dialogue.TestResponse) List(java.util.List) Stream(java.util.stream.Stream) Optional(java.util.Optional) Response(com.palantir.dialogue.Response) IntStream(java.util.stream.IntStream) Tracer(com.palantir.tracing.Tracer) Stopwatch(com.google.common.base.Stopwatch) EnumSource(org.junit.jupiter.params.provider.EnumSource) Function(java.util.function.Function) Supplier(java.util.function.Supplier) Retention(java.lang.annotation.Retention) ArrayList(java.util.ArrayList) Meter(com.codahale.metrics.Meter) ScheduledRequest(com.palantir.dialogue.core.Benchmark.ScheduledRequest) Suppliers(com.google.common.base.Suppliers) Endpoint(com.palantir.dialogue.Endpoint) DEFAULT_ENDPOINT(com.palantir.dialogue.core.Benchmark.DEFAULT_ENDPOINT) Logger(org.slf4j.Logger) Files(java.nio.file.Files) XYChart(org.knowm.xchart.XYChart) Observability(com.palantir.tracing.Observability) IOException(java.io.IOException) HttpMethod(com.palantir.dialogue.HttpMethod) TimeUnit(java.util.concurrent.TimeUnit) EndpointChannel(com.palantir.dialogue.EndpointChannel) AfterEach(org.junit.jupiter.api.AfterEach) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) ChronoUnit(java.time.temporal.ChronoUnit) Paths(java.nio.file.Paths) Comparator(java.util.Comparator) Execution(org.junit.jupiter.api.parallel.Execution) RetentionPolicy(java.lang.annotation.RetentionPolicy) Endpoint(com.palantir.dialogue.Endpoint) Endpoint(com.palantir.dialogue.Endpoint)

Aggregations

Endpoint (com.palantir.dialogue.Endpoint)30 Channel (com.palantir.dialogue.Channel)17 Request (com.palantir.dialogue.Request)15 Response (com.palantir.dialogue.Response)14 Test (org.junit.jupiter.api.Test)11 TestEndpoint (com.palantir.dialogue.TestEndpoint)10 TestResponse (com.palantir.dialogue.TestResponse)9 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)9 ListenableFuture (com.google.common.util.concurrent.ListenableFuture)8 Test (org.junit.Test)8 EndpointChannel (com.palantir.dialogue.EndpointChannel)6 UrlBuilder (com.palantir.dialogue.UrlBuilder)6 Optional (java.util.Optional)6 Random (java.util.Random)6 Futures (com.google.common.util.concurrent.Futures)5 HttpMethod (com.palantir.dialogue.HttpMethod)5 IOException (java.io.IOException)5 BeforeEach (org.junit.jupiter.api.BeforeEach)5 Meter (com.codahale.metrics.Meter)4 SafeRuntimeException (com.palantir.logsafe.exceptions.SafeRuntimeException)4