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

com.github.lontime.extcosid.container.SegmentIdContainer Maven / Gradle / Ivy

package com.github.lontime.extcosid.container;

import java.time.Duration;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;

import javax.sql.DataSource;

import com.github.lontime.base.commonj.components.AbstractLifecycle;
import com.github.lontime.base.commonj.utils.StringHelper;
import com.github.lontime.extcosid.configuration.IdConverterDefinition;
import com.github.lontime.extcosid.configuration.SegmentIdOptions;
import com.github.lontime.extcosid.jdbi.JdbiIdSegmentDistributorFactory;
import com.github.lontime.extcosid.jdbi.JdbiIdSegmentInitializer;
import com.github.lontime.extcosid.redisson.RedissonIdSegmentDistributorFactory;
import com.github.lontime.extdatasource.DatasourceInstance;
import com.github.lontime.extjdbi.JdbiInstance;
import com.github.lontime.extredisson.RedissonInstance;
import com.github.lontime.shaded.com.google.common.base.MoreObjects;
import com.github.lontime.shaded.com.google.common.base.Strings;
import com.github.lontime.shaded.org.redisson.api.RedissonClient;
import me.ahoo.cosid.IdConverter;
import me.ahoo.cosid.converter.PrefixIdConverter;
import me.ahoo.cosid.converter.Radix62IdConverter;
import me.ahoo.cosid.converter.SuffixIdConverter;
import me.ahoo.cosid.converter.ToStringIdConverter;
import me.ahoo.cosid.jdbc.JdbcIdSegmentDistributorFactory;
import me.ahoo.cosid.jdbc.JdbcIdSegmentInitializer;
import me.ahoo.cosid.provider.DefaultIdGeneratorProvider;
import me.ahoo.cosid.provider.IdGeneratorProvider;
import me.ahoo.cosid.segment.DefaultSegmentId;
import me.ahoo.cosid.segment.IdSegmentDistributor;
import me.ahoo.cosid.segment.IdSegmentDistributorDefinition;
import me.ahoo.cosid.segment.IdSegmentDistributorFactory;
import me.ahoo.cosid.segment.SegmentChainId;
import me.ahoo.cosid.segment.SegmentId;
import me.ahoo.cosid.segment.StringSegmentId;
import me.ahoo.cosid.segment.concurrent.PrefetchWorkerExecutorService;
import org.jdbi.v3.core.Jdbi;

/**
 * SegmentIdExt.
 * @author lontime
 * @since 1.0
 */
public class SegmentIdContainer extends AbstractLifecycle {

    private final SegmentIdOptions options;

    private final String namespace;

    private final Map segmentIds = new ConcurrentHashMap<>();

    private volatile PrefetchWorkerExecutorService prefetchWorkerExecutorService;

    private IdSegmentDistributorFactory distributorFactory;

    public SegmentIdContainer(String namespace, SegmentIdOptions options) {
        this.options = options;
        this.namespace = namespace;
    }

    private PrefetchWorkerExecutorService buildPrefetchWorkerExecutorService() {
        final Duration prefetchPeriod = options.getChain().getPrefetchWorker().getPrefetchPeriod();
        final Integer corePoolSize = options.getChain().getPrefetchWorker().getCorePoolSize();
        final PrefetchWorkerExecutorService executorService =
                new PrefetchWorkerExecutorService(prefetchPeriod, corePoolSize, false);
        //默认创建的线程 关闭调用
        PrefetchWorkerExecutorService.DEFAULT.shutdown();
        return executorService;
    }

    public SegmentId getSegmentId() {
        return segmentIds.computeIfAbsent(IdGeneratorProvider.SHARE, k -> {
            final SegmentId segmentId = loadShareSegmentId();
            DefaultIdGeneratorProvider.INSTANCE.set(k, segmentId);
            return segmentId;
        });
    }

    public SegmentId getSegmentId(String name) {
        if (StringHelper.isEmpty(name)) {
            return getSegmentId();
        }
        final SegmentId segmentId = segmentIds.computeIfAbsent(name, k -> {
            final SegmentId segmentIdInner = loadSegmentId(k);
            if (segmentIdInner == null) {
                return null;
            }
            DefaultIdGeneratorProvider.INSTANCE.set(name, segmentIdInner);
            return segmentIdInner;
        });
        if (Objects.nonNull(segmentId)) {
            return segmentId;
        }
        return getSegmentId();
    }

    private SegmentId loadShareSegmentId() {
        return loadSegmentId(options.getShare());
    }

    private SegmentId loadSegmentId(String name) {
        if (StringHelper.isEmpty(name)) {
            return loadSegmentId(options.getShare());
        }
        final Optional definitionOptional
                = options.getProvider().stream().filter(s -> name.equals(s.getName())).findFirst();
        if (definitionOptional.isPresent()) {
            final SegmentIdOptions.IdDefinition definition = definitionOptional.get();
            return loadSegmentId(definition);
        }
        return null;
    }

    private SegmentId loadSegmentId(SegmentIdOptions.IdDefinition definition) {
        final IdSegmentDistributorDefinition distributorDefinition = asDistributorDefinition(definition.getName(), definition);
        final IdSegmentDistributor idSegmentDistributor = distributorFactory.create(distributorDefinition);
        return createSegment(definition, idSegmentDistributor);
    }

    private IdSegmentDistributorFactory buildIdSegmentDistributorFactory() {
        final SegmentIdOptions.DistributorType type = options.getDistributor().getType();
        if (type == SegmentIdOptions.DistributorType.JDBI) {
            final SegmentIdOptions.DistributorJdbi jdbiOptions = options.getDistributor().getJdbi();
            final Jdbi jdbi = JdbiInstance.get().getJdbi(jdbiOptions.getDataSourceName());
            final JdbiIdSegmentInitializer jdbiIdSegmentInitializer =
                    new JdbiIdSegmentInitializer(jdbiOptions.getInitCosidTableSql(),
                            jdbiOptions.getInitIdSegmentSql(), jdbi);
            return new JdbiIdSegmentDistributorFactory(jdbi, jdbiOptions.getEnableAutoInitIdSegment(),
                    jdbiIdSegmentInitializer, jdbiOptions.getIncrementMaxIdSql(), jdbiOptions.getFetchMaxIdSql());
        }

        if (type == SegmentIdOptions.DistributorType.JDBC) {
            final SegmentIdOptions.DistributorJdbc jdbcOptions = options.getDistributor().getJdbc();
            final DataSource dataSource = DatasourceInstance.get().getDataSource(jdbcOptions.getDataSourceName());
            final JdbcIdSegmentInitializer jdbcIdSegmentInitializer =
                    new JdbcIdSegmentInitializer(jdbcOptions.getInitCosidTableSql(), jdbcOptions.getInitIdSegmentSql(),
                            dataSource);
            return new JdbcIdSegmentDistributorFactory(dataSource, jdbcOptions.getEnableAutoInitIdSegment(),
                    jdbcIdSegmentInitializer, jdbcOptions.getInitIdSegmentSql(), jdbcOptions.getFetchMaxIdSql());
        }
        if (type == SegmentIdOptions.DistributorType.REDISSON) {
            final SegmentIdOptions.DistributorRedisson redissonOptions = options.getDistributor().getRedisson();
            final RedissonClient redissonClient = RedissonInstance.get().client(redissonOptions.getClientName());
            return new RedissonIdSegmentDistributorFactory(redissonClient, redissonOptions.getTimeout());
        }
        throw new IllegalStateException("Unexpected value: " + type.name());
    }

    private IdSegmentDistributorDefinition asDistributorDefinition(String name, SegmentIdOptions.IdDefinition idDefinition) {
        return new IdSegmentDistributorDefinition(namespace, name, idDefinition.getOffset(), idDefinition.getStep());
    }

    private SegmentId createSegment(SegmentIdOptions.IdDefinition idDefinition, IdSegmentDistributor idSegmentDistributor) {
        final Long ttl = MoreObjects.firstNonNull(idDefinition.getTtl(), options.getTtl());
        final SegmentIdOptions.Mode mode = MoreObjects.firstNonNull(idDefinition.getMode(), options.getMode());
        final SegmentId segmentId;
        if (SegmentIdOptions.Mode.DEFAULT == mode) {
            segmentId = new DefaultSegmentId(ttl, idSegmentDistributor);
        } else {
            this.prefetchWorkerExecutorService = buildPrefetchWorkerExecutorService();
            SegmentIdOptions.Chain chain = MoreObjects.firstNonNull(idDefinition.getChain(), options.getChain());
            segmentId = new SegmentChainId(ttl, chain.getSafeDistance(), idSegmentDistributor, prefetchWorkerExecutorService);
        }
        final IdConverterDefinition converterDefinition = idDefinition.getConverter();
        if (Objects.isNull(converterDefinition)) {
            return segmentId;
        }
        IdConverter idConverter = ToStringIdConverter.INSTANCE;
        switch (converterDefinition.getType()) {
            case TO_STRING: {
                break;
            }
            case RADIX: {
                IdConverterDefinition.Radix radix = converterDefinition.getRadix();
                idConverter = new Radix62IdConverter(radix.getPadStart(), radix.getCharSize());
                break;
            }
            default:
                throw new IllegalStateException("Unexpected value: " + converterDefinition.getType());
        }

        if (!Strings.isNullOrEmpty(converterDefinition.getPrefix())) {
            idConverter = new PrefixIdConverter(converterDefinition.getPrefix(), idConverter);
        }
        if (!Strings.isNullOrEmpty(converterDefinition.getSuffix())) {
            idConverter = new SuffixIdConverter(converterDefinition.getSuffix(), idConverter);
        }

        return new StringSegmentId(segmentId, idConverter);
    }

    @Override
    public void initialize() {
        this.distributorFactory = buildIdSegmentDistributorFactory();
    }


    @Override
    public void destroy() {
        if (prefetchWorkerExecutorService != null) {
            prefetchWorkerExecutorService.shutdown();
        }
    }

    public boolean enabled() {
        return options.getEnabled();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy