Search in sources :

Example 1 with Endpoint

use of com.couchbase.client.core.endpoint.Endpoint in project couchbase-jvm-clients by couchbase.

the class PooledService method connect.

@Override
public synchronized void connect() {
    if (state() == ServiceState.DISCONNECTED && !disconnected.get()) {
        serviceContext.environment().eventBus().publish(new ServiceConnectInitiatedEvent(serviceContext, serviceConfig.minEndpoints()));
        for (int i = 0; i < serviceConfig.minEndpoints(); i++) {
            Endpoint endpoint = createEndpoint();
            endpointStates.register(endpoint, endpoint);
            endpoint.connect();
            endpoints.add(endpoint);
        }
    }
}
Also used : Endpoint(com.couchbase.client.core.endpoint.Endpoint) ServiceConnectInitiatedEvent(com.couchbase.client.core.cnc.events.service.ServiceConnectInitiatedEvent) Endpoint(com.couchbase.client.core.endpoint.Endpoint)

Example 2 with Endpoint

use of com.couchbase.client.core.endpoint.Endpoint in project couchbase-jvm-clients by couchbase.

the class PooledService method cleanIdleConnections.

/**
 * Go through the connections and clean up all the idle connections.
 * <p>
 * Note that we explicitly do not make any clean up attempts on the {@link #reservedEndpoints}. They will either come
 * into our endpoint pool when connected, or fall out of the pool when they are disconnected immediately. We only need
 * to take them into account when checking how many endpoints we have flying around to clean up at max.
 */
private synchronized void cleanIdleConnections() {
    if (disconnected.get()) {
        return;
    }
    final List<Endpoint> endpoints = new ArrayList<>(this.endpoints);
    Collections.shuffle(endpoints);
    for (Endpoint endpoint : endpoints) {
        if ((this.endpoints.size() + this.reservedEndpoints.size()) == serviceConfig.minEndpoints()) {
            break;
        }
        long lastResponseReceived = endpoint.lastResponseReceived();
        long actualIdleTime;
        if (lastResponseReceived != 0) {
            actualIdleTime = System.nanoTime() - endpoint.lastResponseReceived();
        } else {
            // If we did not receive a last response timestamp, it could be the case that a socket is
            // connected but no request has been sent into it yet. If this is the case, take the timestamp
            // when the socket got last connected as a reference point to determine if it is idle.
            long lastConnected = endpoint.lastConnectedAt();
            if (lastConnected != 0) {
                actualIdleTime = System.nanoTime() - lastConnected;
            } else {
                // No last connected timestamp, so the endpoint isn't even fully connected yet
                continue;
            }
        }
        // we also check if an endpoint received a hard disconnect signal and is still lingering around
        boolean receivedDisconnect = endpoint.receivedDisconnectSignal();
        boolean idleTooLong = endpoint.outstandingRequests() == 0 && actualIdleTime >= serviceConfig.idleTime().toNanos();
        if (receivedDisconnect || idleTooLong) {
            this.endpoints.remove(endpoint);
            endpointStates.deregister(endpoint);
            if (!receivedDisconnect) {
                endpoint.disconnect();
            }
            publishIdleEndpointRemovedEvent(endpoint, actualIdleTime);
        }
    }
    scheduleCleanIdleConnections();
}
Also used : Endpoint(com.couchbase.client.core.endpoint.Endpoint) ArrayList(java.util.ArrayList) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList)

Example 3 with Endpoint

use of com.couchbase.client.core.endpoint.Endpoint in project couchbase-jvm-clients by couchbase.

the class PooledService method connectReservedEndpoint.

/**
 * Connect the reserved endpoint and dispatch the request into it if possible.
 * <p>
 * Note that there are two synchronized sections in this method, because the subscription callback works on
 * a different thread.
 *
 * @param request the request that needs to bee dispatched.
 */
private synchronized <R extends Request<? extends Response>> void connectReservedEndpoint(final R request) {
    if (!disconnected.get()) {
        Endpoint endpoint = createEndpoint();
        endpointStates.register(endpoint, endpoint);
        endpoint.states().skipUntil(s -> s == EndpointState.CONNECTING).filter(s -> s == EndpointState.CONNECTED || s == EndpointState.DISCONNECTED).takeUntil(s -> s == EndpointState.CONNECTED || s == EndpointState.DISCONNECTED).publishOn(context().environment().scheduler()).subscribe(s -> {
            synchronized (PooledService.this) {
                reservedEndpoints.remove(endpoint);
                if (disconnected.get()) {
                    endpoint.disconnect();
                    endpointStates.deregister(endpoint);
                    RetryOrchestrator.maybeRetry(serviceContext, request, RetryReason.ENDPOINT_NOT_AVAILABLE);
                } else {
                    endpoints.add(endpoint);
                    if (s == EndpointState.CONNECTED) {
                        endpoint.send(request);
                    } else if (s == EndpointState.DISCONNECTED) {
                        RetryOrchestrator.maybeRetry(serviceContext, request, RetryReason.ENDPOINT_NOT_AVAILABLE);
                    }
                }
            }
        });
        endpoint.connect();
        reservedEndpoints.add(endpoint);
    }
}
Also used : RetryOrchestrator(com.couchbase.client.core.retry.RetryOrchestrator) EndpointState(com.couchbase.client.core.endpoint.EndpointState) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Endpoint(com.couchbase.client.core.endpoint.Endpoint) Request(com.couchbase.client.core.msg.Request) CompositeStateful(com.couchbase.client.core.util.CompositeStateful) HashMap(java.util.HashMap) ServiceStateChangedEvent(com.couchbase.client.core.cnc.events.service.ServiceStateChangedEvent) RetryReason(com.couchbase.client.core.retry.RetryReason) ArrayList(java.util.ArrayList) TimeUnit(java.util.concurrent.TimeUnit) Flux(reactor.core.publisher.Flux) List(java.util.List) Stream(java.util.stream.Stream) ServiceDisconnectInitiatedEvent(com.couchbase.client.core.cnc.events.service.ServiceDisconnectInitiatedEvent) Duration(java.time.Duration) Map(java.util.Map) EndpointContext(com.couchbase.client.core.endpoint.EndpointContext) EndpointDiagnostics(com.couchbase.client.core.diagnostics.EndpointDiagnostics) ServiceConnectInitiatedEvent(com.couchbase.client.core.cnc.events.service.ServiceConnectInitiatedEvent) Collections(java.util.Collections) Response(com.couchbase.client.core.msg.Response) IdleEndpointRemovedEvent(com.couchbase.client.core.cnc.events.service.IdleEndpointRemovedEvent) CopyOnWriteArrayList(java.util.concurrent.CopyOnWriteArrayList) Endpoint(com.couchbase.client.core.endpoint.Endpoint)

Example 4 with Endpoint

use of com.couchbase.client.core.endpoint.Endpoint in project couchbase-jvm-clients by couchbase.

the class PooledServiceTest method dispatchesDirectlyIfSlotAvailable.

@Test
void dispatchesDirectlyIfSlotAvailable() {
    int minEndpoints = 0;
    Endpoint mock1 = mock(Endpoint.class);
    when(mock1.state()).thenReturn(EndpointState.CONNECTED);
    DirectProcessor<EndpointState> states = DirectProcessor.create();
    when(mock1.states()).thenReturn(states);
    when(mock1.outstandingRequests()).thenReturn(0L);
    final List<Endpoint> mocks = Collections.singletonList(mock1);
    final AtomicInteger invocation = new AtomicInteger();
    MockedService service = new MockedService(new MockedServiceConfig(minEndpoints, 2, Duration.ofMillis(500), false), () -> mocks.get(invocation.getAndIncrement()), new FirstEndpointSelectionStrategy());
    service.connect();
    assertTrue(service.trackedEndpoints().isEmpty());
    NoopRequest request = new NoopRequest(Duration.ofSeconds(1), serviceContext, BestEffortRetryStrategy.INSTANCE, CollectionIdentifier.fromDefault("bucket"));
    service.send(request);
    // Simulate the connecting and connected
    states.onNext(EndpointState.CONNECTING);
    states.onNext(EndpointState.CONNECTED);
    waitUntilCondition(() -> !service.trackedEndpoints.isEmpty());
    assertEquals(1, service.trackedEndpoints().size());
    assertEquals(0, request.context().retryAttempts());
    waitUntilCondition(() -> {
        Collection<Invocation> invocations = Mockito.mockingDetails(mock1).getInvocations();
        for (Invocation inv : invocations) {
            if (inv.getMethod().getName().equals("send")) {
                if (inv.getArgument(0) == request) {
                    return true;
                }
            }
        }
        return false;
    });
    verify(mock1, times(1)).send(request);
}
Also used : EndpointState(com.couchbase.client.core.endpoint.EndpointState) NoopRequest(com.couchbase.client.core.msg.kv.NoopRequest) Endpoint(com.couchbase.client.core.endpoint.Endpoint) Invocation(org.mockito.invocation.Invocation) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Endpoint(com.couchbase.client.core.endpoint.Endpoint) Test(org.junit.jupiter.api.Test)

Example 5 with Endpoint

use of com.couchbase.client.core.endpoint.Endpoint in project couchbase-jvm-clients by couchbase.

the class PooledServiceTest method sendsRequestIntoEndpoint.

/**
 * Most basic test to check if we can dispatch into the endpoint.
 */
@Test
@SuppressWarnings({ "unchecked" })
void sendsRequestIntoEndpoint() {
    int minEndpoints = 2;
    Endpoint mock1 = mock(Endpoint.class);
    when(mock1.state()).thenReturn(EndpointState.CONNECTED);
    when(mock1.states()).thenReturn(DirectProcessor.create());
    when(mock1.outstandingRequests()).thenReturn(0L);
    Endpoint mock2 = mock(Endpoint.class);
    when(mock2.state()).thenReturn(EndpointState.CONNECTED);
    when(mock2.states()).thenReturn(DirectProcessor.create());
    final List<Endpoint> mocks = Arrays.asList(mock1, mock2);
    final AtomicInteger invocation = new AtomicInteger();
    MockedService service = new MockedService(new MockedServiceConfig(minEndpoints, 2), () -> mocks.get(invocation.getAndIncrement()), new FirstEndpointSelectionStrategy());
    service.connect();
    Request<? extends Response> request = mock(Request.class);
    service.send(request);
    verify(mock1, times(1)).send(request);
    verify(mock2, never()).send(request);
}
Also used : Endpoint(com.couchbase.client.core.endpoint.Endpoint) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) Endpoint(com.couchbase.client.core.endpoint.Endpoint) Test(org.junit.jupiter.api.Test)

Aggregations

Endpoint (com.couchbase.client.core.endpoint.Endpoint)24 Test (org.junit.jupiter.api.Test)18 AtomicInteger (java.util.concurrent.atomic.AtomicInteger)14 NoopRequest (com.couchbase.client.core.msg.kv.NoopRequest)9 EndpointState (com.couchbase.client.core.endpoint.EndpointState)8 ServiceConnectInitiatedEvent (com.couchbase.client.core.cnc.events.service.ServiceConnectInitiatedEvent)3 ServiceDisconnectInitiatedEvent (com.couchbase.client.core.cnc.events.service.ServiceDisconnectInitiatedEvent)3 Request (com.couchbase.client.core.msg.Request)3 GetRequest (com.couchbase.client.core.msg.kv.GetRequest)3 EndpointSelectionStrategy (com.couchbase.client.core.service.EndpointSelectionStrategy)3 ArrayList (java.util.ArrayList)2 CopyOnWriteArrayList (java.util.concurrent.CopyOnWriteArrayList)2 Invocation (org.mockito.invocation.Invocation)2 IdleEndpointRemovedEvent (com.couchbase.client.core.cnc.events.service.IdleEndpointRemovedEvent)1 ServiceStateChangedEvent (com.couchbase.client.core.cnc.events.service.ServiceStateChangedEvent)1 EndpointDiagnostics (com.couchbase.client.core.diagnostics.EndpointDiagnostics)1 EndpointContext (com.couchbase.client.core.endpoint.EndpointContext)1 Response (com.couchbase.client.core.msg.Response)1 KeyValueRequest (com.couchbase.client.core.msg.kv.KeyValueRequest)1 RetryOrchestrator (com.couchbase.client.core.retry.RetryOrchestrator)1