Search in sources :

Example 1 with EndpointConnectionAbortedEvent

use of com.couchbase.client.core.cnc.events.endpoint.EndpointConnectionAbortedEvent in project couchbase-jvm-clients by couchbase.

the class BaseEndpoint method reconnect.

/**
 * This method performs the actual connecting logic.
 *
 * <p>It is called reconnect since it works both in the case where an initial attempt is made
 * but also when the underlying channel is closed or the previous connect attempt was
 * unsuccessful.</p>
 */
private void reconnect() {
    if (disconnect.get()) {
        return;
    }
    state.transition(EndpointState.CONNECTING);
    final EndpointContext endpointContext = this.endpointContext.get();
    final AtomicLong attemptStart = new AtomicLong();
    Mono.defer((Supplier<Mono<Channel>>) () -> {
        CoreEnvironment env = endpointContext.environment();
        long connectTimeoutMs = env.timeoutConfig().connectTimeout().toMillis();
        if (eventLoopGroup.isShutdown()) {
            throw new IllegalStateException("Event Loop is already shut down, not pursuing connect attempt!");
        }
        final Bootstrap channelBootstrap = new Bootstrap().remoteAddress(remoteAddress()).group(eventLoopGroup).channel(channelFrom(eventLoopGroup)).option(ChannelOption.CONNECT_TIMEOUT_MILLIS, (int) connectTimeoutMs).handler(new ChannelInitializer<Channel>() {

            @Override
            protected void initChannel(final Channel ch) {
                ChannelPipeline pipeline = ch.pipeline();
                SecurityConfig config = env.securityConfig();
                if (config.tlsEnabled()) {
                    try {
                        pipeline.addFirst(SslHandlerFactory.get(ch.alloc(), config, endpointContext));
                    } catch (Exception e) {
                        throw new SecurityException("Could not instantiate SSL Handler", e);
                    }
                }
                if (env.ioConfig().servicesToCapture().contains(serviceType)) {
                    pipeline.addLast(new TrafficCaptureHandler(endpointContext));
                }
                pipelineInitializer().init(BaseEndpoint.this, pipeline);
                pipeline.addLast(new PipelineErrorHandler(BaseEndpoint.this));
            }
        });
        if (env.ioConfig().tcpKeepAlivesEnabled() && !(eventLoopGroup instanceof DefaultEventLoopGroup)) {
            channelBootstrap.option(ChannelOption.SO_KEEPALIVE, true);
            if (eventLoopGroup instanceof EpollEventLoopGroup) {
                channelBootstrap.option(EpollChannelOption.TCP_KEEPIDLE, (int) TimeUnit.MILLISECONDS.toSeconds(env.ioConfig().tcpKeepAliveTime().toMillis()));
            }
        }
        state.transition(EndpointState.CONNECTING);
        attemptStart.set(System.nanoTime());
        return channelFutureIntoMono(channelBootstrap.connect());
    }).timeout(endpointContext.environment().timeoutConfig().connectTimeout()).onErrorResume(throwable -> {
        state.transition(EndpointState.DISCONNECTED);
        if (disconnect.get()) {
            endpointContext.environment().eventBus().publish(new EndpointConnectionAbortedEvent(Duration.ofNanos(System.nanoTime() - attemptStart.get()), endpointContext, ConnectTimings.toMap(channel)));
            return Mono.empty();
        } else {
            return Mono.error(throwable);
        }
    }).retryWhen(Retry.any().exponentialBackoff(Duration.ofMillis(32), Duration.ofMillis(4096)).retryMax(Long.MAX_VALUE).doOnRetry(retryContext -> {
        Throwable ex = retryContext.exception();
        // We drop the severity for the BucketNotFoundException because it shows up when
        // bootstrapping against MDS clusters and nodes with no kv service enabled on it
        // that is bucket aware. If a bucket really does not exist we'll get an auth
        // exception instead.
        Event.Severity severity = ex instanceof BucketNotFoundException ? Event.Severity.DEBUG : Event.Severity.WARN;
        Duration duration = ex instanceof TimeoutException ? endpointContext.environment().timeoutConfig().connectTimeout() : Duration.ofNanos(System.nanoTime() - attemptStart.get());
        ex = annotateConnectException(ex);
        endpointContext.environment().eventBus().publish(new EndpointConnectionFailedEvent(severity, duration, endpointContext, retryContext.iteration(), trimNettyFromStackTrace(ex)));
    }).toReactorRetry()).subscribe(channel -> {
        long now = System.nanoTime();
        if (disconnect.get()) {
            this.channel = null;
            endpointContext.environment().eventBus().publish(new EndpointConnectionIgnoredEvent(Duration.ofNanos(now - attemptStart.get()), endpointContext, ConnectTimings.toMap(channel)));
            closeChannel(channel);
        } else {
            this.channel = channel;
            Optional<HostAndPort> localSocket = Optional.empty();
            if (channel.localAddress() instanceof InetSocketAddress) {
                // it will always be an inet socket address, but to safeguard for testing mocks...
                InetSocketAddress so = (InetSocketAddress) channel.localAddress();
                localSocket = Optional.of(new HostAndPort(so.getHostString(), so.getPort()));
            }
            EndpointContext newContext = new EndpointContext(endpointContext, endpointContext.remoteSocket(), endpointContext.circuitBreaker(), endpointContext.serviceType(), localSocket, endpointContext.bucket(), Optional.ofNullable(channel.attr(ChannelAttributes.CHANNEL_ID_KEY).get()));
            this.endpointContext.get().environment().eventBus().publish(new EndpointConnectedEvent(Duration.ofNanos(now - attemptStart.get()), newContext, ConnectTimings.toMap(channel)));
            this.endpointContext.set(newContext);
            this.circuitBreaker.reset();
            lastConnectedAt = now;
            state.transition(EndpointState.CONNECTED);
        }
    }, error -> endpointContext.environment().eventBus().publish(new UnexpectedEndpointConnectionFailedEvent(Duration.ofNanos(System.nanoTime() - attemptStart.get()), endpointContext, error)));
}
Also used : ChannelFutureListener(com.couchbase.client.core.deps.io.netty.channel.ChannelFutureListener) Arrays(java.util.Arrays) SocketAddress(java.net.SocketAddress) EndpointDisconnectionFailedEvent(com.couchbase.client.core.cnc.events.endpoint.EndpointDisconnectionFailedEvent) TimeoutException(java.util.concurrent.TimeoutException) Request(com.couchbase.client.core.msg.Request) EndpointConnectionAbortedEvent(com.couchbase.client.core.cnc.events.endpoint.EndpointConnectionAbortedEvent) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ServiceType(com.couchbase.client.core.service.ServiceType) Duration(java.time.Duration) Map(java.util.Map) Context(com.couchbase.client.core.cnc.Context) AbstractContext(com.couchbase.client.core.cnc.AbstractContext) SecurityConfig(com.couchbase.client.core.env.SecurityConfig) EndpointConnectedEvent(com.couchbase.client.core.cnc.events.endpoint.EndpointConnectedEvent) UnexpectedEndpointDisconnectedEvent(com.couchbase.client.core.cnc.events.endpoint.UnexpectedEndpointDisconnectedEvent) EpollChannelOption(com.couchbase.client.core.deps.io.netty.channel.epoll.EpollChannelOption) Channel(com.couchbase.client.core.deps.io.netty.channel.Channel) BucketNotFoundException(com.couchbase.client.core.error.BucketNotFoundException) ChannelPipeline(com.couchbase.client.core.deps.io.netty.channel.ChannelPipeline) EpollSocketChannel(com.couchbase.client.core.deps.io.netty.channel.epoll.EpollSocketChannel) RetryOrchestrator(com.couchbase.client.core.retry.RetryOrchestrator) SslHandlerFactory(com.couchbase.client.core.io.netty.SslHandlerFactory) CoreEnvironment(com.couchbase.client.core.env.CoreEnvironment) InvalidArgumentException(com.couchbase.client.core.error.InvalidArgumentException) SignalType(reactor.core.publisher.SignalType) InetSocketAddress(java.net.InetSocketAddress) RetryReason(com.couchbase.client.core.retry.RetryReason) DefaultEventLoopGroup(com.couchbase.client.core.deps.io.netty.channel.DefaultEventLoopGroup) KQueueSocketChannel(com.couchbase.client.core.deps.io.netty.channel.kqueue.KQueueSocketChannel) ChannelAttributes(com.couchbase.client.core.io.netty.kv.ChannelAttributes) List(java.util.List) RedactableArgument.redactMeta(com.couchbase.client.core.logging.RedactableArgument.redactMeta) NioSocketChannel(com.couchbase.client.core.deps.io.netty.channel.socket.nio.NioSocketChannel) ChannelFuture(com.couchbase.client.core.deps.io.netty.channel.ChannelFuture) SecurityException(com.couchbase.client.core.error.SecurityException) Optional(java.util.Optional) EpollEventLoopGroup(com.couchbase.client.core.deps.io.netty.channel.epoll.EpollEventLoopGroup) EndpointWriteFailedEvent(com.couchbase.client.core.cnc.events.endpoint.EndpointWriteFailedEvent) Response(com.couchbase.client.core.msg.Response) HostAndPort(com.couchbase.client.core.util.HostAndPort) Retry(com.couchbase.client.core.retry.reactor.Retry) TrafficCaptureHandler(com.couchbase.client.core.io.netty.TrafficCaptureHandler) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) CompletableFuture(java.util.concurrent.CompletableFuture) EndpointConnectionFailedEvent(com.couchbase.client.core.cnc.events.endpoint.EndpointConnectionFailedEvent) AtomicReference(java.util.concurrent.atomic.AtomicReference) Supplier(java.util.function.Supplier) KQueueEventLoopGroup(com.couchbase.client.core.deps.io.netty.channel.kqueue.KQueueEventLoopGroup) PipelineErrorHandler(com.couchbase.client.core.io.netty.PipelineErrorHandler) SingleStateful(com.couchbase.client.core.util.SingleStateful) ConnectTimings(com.couchbase.client.core.io.netty.kv.ConnectTimings) LocalChannel(com.couchbase.client.core.deps.io.netty.channel.local.LocalChannel) Stability(com.couchbase.client.core.annotation.Stability) EndpointDiagnostics(com.couchbase.client.core.diagnostics.EndpointDiagnostics) ConnectException(java.net.ConnectException) UnexpectedEndpointConnectionFailedEvent(com.couchbase.client.core.cnc.events.endpoint.UnexpectedEndpointConnectionFailedEvent) NioEventLoopGroup(com.couchbase.client.core.deps.io.netty.channel.nio.NioEventLoopGroup) CancellationReason(com.couchbase.client.core.msg.CancellationReason) LinkedList(java.util.LinkedList) ServiceContext(com.couchbase.client.core.service.ServiceContext) ChannelInitializer(com.couchbase.client.core.deps.io.netty.channel.ChannelInitializer) ChannelOption(com.couchbase.client.core.deps.io.netty.channel.ChannelOption) EndpointConnectionIgnoredEvent(com.couchbase.client.core.cnc.events.endpoint.EndpointConnectionIgnoredEvent) Mono(reactor.core.publisher.Mono) Event(com.couchbase.client.core.cnc.Event) EndpointStateChangedEvent(com.couchbase.client.core.cnc.events.endpoint.EndpointStateChangedEvent) EventLoopGroup(com.couchbase.client.core.deps.io.netty.channel.EventLoopGroup) TimeUnit(java.util.concurrent.TimeUnit) Flux(reactor.core.publisher.Flux) AtomicLong(java.util.concurrent.atomic.AtomicLong) EndpointDisconnectedEvent(com.couchbase.client.core.cnc.events.endpoint.EndpointDisconnectedEvent) Bootstrap(com.couchbase.client.core.deps.io.netty.bootstrap.Bootstrap) CoreEnvironment(com.couchbase.client.core.env.CoreEnvironment) InetSocketAddress(java.net.InetSocketAddress) DefaultEventLoopGroup(com.couchbase.client.core.deps.io.netty.channel.DefaultEventLoopGroup) EndpointConnectionIgnoredEvent(com.couchbase.client.core.cnc.events.endpoint.EndpointConnectionIgnoredEvent) HostAndPort(com.couchbase.client.core.util.HostAndPort) EndpointConnectionAbortedEvent(com.couchbase.client.core.cnc.events.endpoint.EndpointConnectionAbortedEvent) SecurityConfig(com.couchbase.client.core.env.SecurityConfig) Bootstrap(com.couchbase.client.core.deps.io.netty.bootstrap.Bootstrap) ChannelInitializer(com.couchbase.client.core.deps.io.netty.channel.ChannelInitializer) TrafficCaptureHandler(com.couchbase.client.core.io.netty.TrafficCaptureHandler) TimeoutException(java.util.concurrent.TimeoutException) EndpointConnectedEvent(com.couchbase.client.core.cnc.events.endpoint.EndpointConnectedEvent) Mono(reactor.core.publisher.Mono) Channel(com.couchbase.client.core.deps.io.netty.channel.Channel) EpollSocketChannel(com.couchbase.client.core.deps.io.netty.channel.epoll.EpollSocketChannel) KQueueSocketChannel(com.couchbase.client.core.deps.io.netty.channel.kqueue.KQueueSocketChannel) NioSocketChannel(com.couchbase.client.core.deps.io.netty.channel.socket.nio.NioSocketChannel) LocalChannel(com.couchbase.client.core.deps.io.netty.channel.local.LocalChannel) SecurityException(com.couchbase.client.core.error.SecurityException) Duration(java.time.Duration) ChannelPipeline(com.couchbase.client.core.deps.io.netty.channel.ChannelPipeline) TimeoutException(java.util.concurrent.TimeoutException) BucketNotFoundException(com.couchbase.client.core.error.BucketNotFoundException) InvalidArgumentException(com.couchbase.client.core.error.InvalidArgumentException) SecurityException(com.couchbase.client.core.error.SecurityException) ConnectException(java.net.ConnectException) AtomicLong(java.util.concurrent.atomic.AtomicLong) PipelineErrorHandler(com.couchbase.client.core.io.netty.PipelineErrorHandler) UnexpectedEndpointConnectionFailedEvent(com.couchbase.client.core.cnc.events.endpoint.UnexpectedEndpointConnectionFailedEvent) EpollEventLoopGroup(com.couchbase.client.core.deps.io.netty.channel.epoll.EpollEventLoopGroup) BucketNotFoundException(com.couchbase.client.core.error.BucketNotFoundException) EndpointConnectionFailedEvent(com.couchbase.client.core.cnc.events.endpoint.EndpointConnectionFailedEvent) UnexpectedEndpointConnectionFailedEvent(com.couchbase.client.core.cnc.events.endpoint.UnexpectedEndpointConnectionFailedEvent)

Example 2 with EndpointConnectionAbortedEvent

use of com.couchbase.client.core.cnc.events.endpoint.EndpointConnectionAbortedEvent in project couchbase-jvm-clients by couchbase.

the class BaseEndpointTest method disconnectDuringRetry.

/**
 * Make sure that while we are retrying and a disconnect event comes along, we stop
 * retrying and end up in the disconnected state right away.
 */
@Test
void disconnectDuringRetry() {
    SimpleEventBus eventBus = new SimpleEventBus(true, Collections.singletonList(EndpointStateChangedEvent.class));
    CoreEnvironment env = CoreEnvironment.builder().eventBus(eventBus).timeoutConfig(TimeoutConfig.connectTimeout(Duration.ofMillis(10))).build();
    CoreContext coreContext = new CoreContext(mock(Core.class), 1, env, authenticator);
    ServiceContext ctx = new ServiceContext(coreContext, LOCALHOST, 1234, ServiceType.KV, Optional.empty());
    try {
        final CompletableFuture<Channel> cf = new CompletableFuture<>();
        InstrumentedEndpoint endpoint = InstrumentedEndpoint.create(eventLoopGroup, ctx, () -> Mono.fromFuture(cf));
        endpoint.connect();
        waitUntilCondition(() -> eventBus.publishedEvents().size() >= 3);
        endpoint.disconnect();
        waitUntilCondition(() -> endpoint.state() == EndpointState.DISCONNECTED);
        waitUntilCondition(() -> eventBus.publishedEvents().size() >= 4);
        int warn = 0;
        int debug = 0;
        for (Event event : eventBus.publishedEvents()) {
            if (event.severity() == Event.Severity.WARN) {
                warn++;
                assertTrue(event instanceof EndpointConnectionFailedEvent);
            } else if (event.severity() == Event.Severity.DEBUG) {
                debug++;
                assertTrue(event instanceof EndpointConnectionAbortedEvent);
            } else {
                throw new RuntimeException("Unexpected Event: " + event);
            }
        }
        assertEquals(3, warn);
        assertEquals(1, debug);
    } finally {
        environment.shutdown();
    }
}
Also used : CoreContext(com.couchbase.client.core.CoreContext) ServiceContext(com.couchbase.client.core.service.ServiceContext) EmbeddedChannel(com.couchbase.client.core.deps.io.netty.channel.embedded.EmbeddedChannel) Channel(com.couchbase.client.core.deps.io.netty.channel.Channel) EndpointStateChangedEvent(com.couchbase.client.core.cnc.events.endpoint.EndpointStateChangedEvent) CompletableFuture(java.util.concurrent.CompletableFuture) EndpointConnectionAbortedEvent(com.couchbase.client.core.cnc.events.endpoint.EndpointConnectionAbortedEvent) SimpleEventBus(com.couchbase.client.core.cnc.SimpleEventBus) EndpointDisconnectionFailedEvent(com.couchbase.client.core.cnc.events.endpoint.EndpointDisconnectionFailedEvent) EndpointConnectionFailedEvent(com.couchbase.client.core.cnc.events.endpoint.EndpointConnectionFailedEvent) EndpointConnectionAbortedEvent(com.couchbase.client.core.cnc.events.endpoint.EndpointConnectionAbortedEvent) EndpointConnectedEvent(com.couchbase.client.core.cnc.events.endpoint.EndpointConnectedEvent) EndpointConnectionIgnoredEvent(com.couchbase.client.core.cnc.events.endpoint.EndpointConnectionIgnoredEvent) Event(com.couchbase.client.core.cnc.Event) EndpointStateChangedEvent(com.couchbase.client.core.cnc.events.endpoint.EndpointStateChangedEvent) EndpointDisconnectedEvent(com.couchbase.client.core.cnc.events.endpoint.EndpointDisconnectedEvent) EndpointConnectionFailedEvent(com.couchbase.client.core.cnc.events.endpoint.EndpointConnectionFailedEvent) Core(com.couchbase.client.core.Core) Test(org.junit.jupiter.api.Test)

Aggregations

Event (com.couchbase.client.core.cnc.Event)2 EndpointConnectedEvent (com.couchbase.client.core.cnc.events.endpoint.EndpointConnectedEvent)2 EndpointConnectionAbortedEvent (com.couchbase.client.core.cnc.events.endpoint.EndpointConnectionAbortedEvent)2 EndpointConnectionFailedEvent (com.couchbase.client.core.cnc.events.endpoint.EndpointConnectionFailedEvent)2 EndpointConnectionIgnoredEvent (com.couchbase.client.core.cnc.events.endpoint.EndpointConnectionIgnoredEvent)2 EndpointDisconnectedEvent (com.couchbase.client.core.cnc.events.endpoint.EndpointDisconnectedEvent)2 EndpointDisconnectionFailedEvent (com.couchbase.client.core.cnc.events.endpoint.EndpointDisconnectionFailedEvent)2 EndpointStateChangedEvent (com.couchbase.client.core.cnc.events.endpoint.EndpointStateChangedEvent)2 Channel (com.couchbase.client.core.deps.io.netty.channel.Channel)2 ServiceContext (com.couchbase.client.core.service.ServiceContext)2 CompletableFuture (java.util.concurrent.CompletableFuture)2 Core (com.couchbase.client.core.Core)1 CoreContext (com.couchbase.client.core.CoreContext)1 Stability (com.couchbase.client.core.annotation.Stability)1 AbstractContext (com.couchbase.client.core.cnc.AbstractContext)1 Context (com.couchbase.client.core.cnc.Context)1 SimpleEventBus (com.couchbase.client.core.cnc.SimpleEventBus)1 EndpointWriteFailedEvent (com.couchbase.client.core.cnc.events.endpoint.EndpointWriteFailedEvent)1 UnexpectedEndpointConnectionFailedEvent (com.couchbase.client.core.cnc.events.endpoint.UnexpectedEndpointConnectionFailedEvent)1 UnexpectedEndpointDisconnectedEvent (com.couchbase.client.core.cnc.events.endpoint.UnexpectedEndpointDisconnectedEvent)1