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

com.redis.spring.batch.AbstractRedisItemStreamSupport Maven / Gradle / Ivy

There is a newer version: 4.0.7
Show newest version
package com.redis.spring.batch;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.item.ItemStreamSupport;
import org.springframework.util.ClassUtils;

import com.redis.spring.batch.util.ConnectionUtils;

import io.lettuce.core.AbstractRedisClient;
import io.lettuce.core.RedisFuture;
import io.lettuce.core.api.StatefulConnection;
import io.lettuce.core.api.async.BaseRedisAsyncCommands;
import io.lettuce.core.codec.RedisCodec;
import io.lettuce.core.support.ConnectionPoolSupport;

public abstract class AbstractRedisItemStreamSupport extends ItemStreamSupport {

    public static final int DEFAULT_POOL_SIZE = GenericObjectPoolConfig.DEFAULT_MAX_TOTAL;

    protected final AbstractRedisClient client;

    protected final RedisCodec codec;

    private int poolSize = DEFAULT_POOL_SIZE;

    private GenericObjectPool> pool;

    protected AbstractRedisItemStreamSupport(AbstractRedisClient client, RedisCodec codec) {
        setName(ClassUtils.getShortName(getClass()));
        this.client = client;
        this.codec = codec;
    }

    public int getPoolSize() {
        return poolSize;
    }

    public void setPoolSize(int poolSize) {
        this.poolSize = poolSize;
    }

    @Override
    public synchronized void open(ExecutionContext executionContext) {
        if (!isOpen()) {
            doOpen();
        }
        super.open(executionContext);
    }

    protected void doOpen() {
        GenericObjectPoolConfig> config = new GenericObjectPoolConfig<>();
        config.setMaxTotal(poolSize);
        pool = ConnectionPoolSupport.createGenericObjectPool(connectionSupplier(), config);
    }

    protected Supplier> connectionSupplier() {
        return ConnectionUtils.supplier(client, codec);
    }

    public boolean isOpen() {
        return pool != null;
    }

    @Override
    public synchronized void close() {
        super.close();
        if (isOpen()) {
            doClose();
        }
    }

    protected void doClose() {
        pool.close();
        pool = null;
    }

    protected List execute(Collection items) throws Exception {
        try (StatefulConnection connection = pool.borrowObject()) {
            long timeout = connection.getTimeout().toMillis();
            BaseRedisAsyncCommands commands = ConnectionUtils.async(connection);
            List> futures = new ArrayList<>();
            try {
                connection.setAutoFlushCommands(false);
                execute(commands, items, futures);
                connection.flushCommands();
                List results = new ArrayList<>(futures.size());
                for (RedisFuture future : futures) {
                    results.add(future.get(timeout, TimeUnit.MILLISECONDS));
                }
                return results;
            } finally {
                connection.setAutoFlushCommands(true);
            }
        }
    }

    protected void execute(BaseRedisAsyncCommands commands, Collection items, List> futures) {
        for (I item : items) {
            execute(commands, item, futures);
        }
    }

    protected abstract void execute(BaseRedisAsyncCommands commands, I item, List> futures);

}