All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.yandex.ydb.table.impl.SessionPool Maven / Gradle / Ivy

There is a newer version: 1.45.6
Show newest version
package com.yandex.ydb.table.impl;

import java.time.Duration;
import java.time.Instant;
import java.util.concurrent.CompletableFuture;

import com.yandex.ydb.core.Result;
import com.yandex.ydb.table.SessionStatus;
import com.yandex.ydb.table.impl.SessionImpl.State;
import com.yandex.ydb.table.impl.pool.FixedAsyncPool;
import com.yandex.ydb.table.impl.pool.PooledObjectHandler;
import com.yandex.ydb.table.impl.pool.SettlersPool;
import com.yandex.ydb.table.settings.CloseSessionSettings;
import com.yandex.ydb.table.settings.CreateSessionSettings;
import com.yandex.ydb.table.stats.SessionPoolStats;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author Sergey Polovko
 */
final class SessionPool implements PooledObjectHandler {
    private static final Logger logger = LoggerFactory.getLogger(SessionPool.class);

    private final TableClientImpl tableClient;

    /**
     * Pool to store sessions which are ready but idle right now
     */
    private final FixedAsyncPool idlePool;

    /**
     * Pool to store sessions with unknown status due to some transport errors.
     */
    private final SettlersPool settlersPool;

    private final int minSize;
    private final int maxSize;

    SessionPool(TableClientImpl tableClient, SessionPoolOptions options) {
        this.tableClient = tableClient;
        this.minSize = options.getMinSize();
        this.maxSize = options.getMaxSize();
        this.idlePool = new FixedAsyncPool<>(
            this,
            minSize,
            maxSize,
            maxSize * 2,
            options.getKeepAliveTimeMillis(),
            options.getMaxIdleTimeMillis());
        this.settlersPool = new SettlersPool<>(this, idlePool, 10, 5_000);
    }

    @Override
    public CompletableFuture create(long deadlineAfter) {
        return tableClient.createSessionImpl(new CreateSessionSettings().setDeadlineAfter(deadlineAfter), this)
            .thenApply(r -> {
                SessionImpl session = (SessionImpl) r.expect("cannot create session");
                session.setState(State.IDLE);
                return session;
            });
    }

    @Override
    public CompletableFuture destroy(SessionImpl s) {
        return s.delete(new CloseSessionSettings())
            .thenAccept(r -> r.expect("cannot close session: " + s.getId()));
    }

    @Override
    public boolean isValid(SessionImpl s) {
        return s.switchState(State.ACTIVE, State.IDLE);
    }

    @Override
    public CompletableFuture> keepAlive(SessionImpl s) {
        return s.keepAlive();
    }

    CompletableFuture acquire(Duration timeout) {
        final Instant startTime = Instant.now();
        return idlePool.acquire(timeout)
            .thenCompose(s -> {
                if (s.switchState(State.IDLE, State.ACTIVE)) {
                    logger.debug("session `{}' acquired", s);
                    return CompletableFuture.completedFuture(s);
                } else {
                    release(s);
                    Duration duration = Duration.between(startTime, Instant.now());
                    return acquire(timeout.minus(Duration.ZERO.compareTo(duration) < 0
                        ? duration
                        : Duration.ZERO));
                }
            });
    }

    void release(SessionImpl session) {
        if (session.switchState(State.DISCONNECTED, State.IDLE)) {
            if (!settlersPool.offerIfHaveSpace(session)) {
                logger.debug("Destroy {} because settlers pool overflow", session);
                session.close(); // do not await session to be closed
                idlePool.release(session);
            }
        } else {
            idlePool.release(session);
            logger.debug("session `{}' released", session);
        }
    }

    void delete(SessionImpl session) {
        idlePool.delete(session);
    }

    void close() {
        idlePool.close();
        settlersPool.close();
    }

    public SessionPoolStats getStats() {
        return new SessionPoolStats(
            minSize,
            maxSize,
            idlePool.getIdleCount(),
            settlersPool.size(),
            idlePool.getAcquiredCount(),
            idlePool.getPendingAcquireCount());
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy