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

com.redis.spring.batch.util.KeyComparisonItemReader Maven / Gradle / Ivy

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

import java.time.Duration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import org.springframework.batch.item.ExecutionContext;
import org.springframework.batch.item.support.AbstractItemStreamItemReader;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;

import com.redis.spring.batch.KeyValue;
import com.redis.spring.batch.RedisItemReader;
import com.redis.spring.batch.RedisItemReader.Mode;
import com.redis.spring.batch.ValueType;
import com.redis.spring.batch.reader.KeyValueItemProcessor;
import com.redis.spring.batch.util.KeyComparison.Status;

import io.lettuce.core.AbstractRedisClient;
import io.lettuce.core.codec.StringCodec;

public class KeyComparisonItemReader extends AbstractItemStreamItemReader {

    public static final Duration DEFAULT_TTL_TOLERANCE = Duration.ofMillis(100);

    private Duration ttlTolerance = DEFAULT_TTL_TOLERANCE;

    private final RedisItemReader left;

    private final RedisItemReader right;

    private Iterator iterator = Collections.emptyIterator();

    private KeyValueItemProcessor rightKeyValueReader;

    public KeyComparisonItemReader(AbstractRedisClient left, AbstractRedisClient right) {
        this(new RedisItemReader<>(left, StringCodec.UTF8), new RedisItemReader<>(right, StringCodec.UTF8));
    }

    public KeyComparisonItemReader(RedisItemReader left, RedisItemReader right) {
        this.left = left;
        this.right = right;
        setName(ClassUtils.getShortName(getClass()));
    }

    public RedisItemReader getLeft() {
        return left;
    }

    public RedisItemReader getRight() {
        return right;
    }

    @Override
    public void setName(String name) {
        super.setName(name);
        left.setName(name + "-left");
        right.setName(name + "-right");
    }

    public void setTtlTolerance(Duration ttlTolerance) {
        Assert.notNull(ttlTolerance, "Tolerance must not be null");
        this.ttlTolerance = ttlTolerance;
    }

    @Override
    public synchronized void open(ExecutionContext executionContext) {
        super.open(executionContext);
        if (!isOpen()) {
            left.setValueType(ValueType.STRUCT);
            left.setMode(Mode.SCAN);
            right.setValueType(ValueType.STRUCT);
            right.setMode(Mode.SCAN);
            rightKeyValueReader = right.keyValueProcessor();
            rightKeyValueReader.open(executionContext);
            left.open(executionContext);
        }
    }

    public boolean isOpen() {
        return rightKeyValueReader != null && BatchUtils.isOpen(rightKeyValueReader) && left.isOpen();
    }

    @Override
    public void update(ExecutionContext executionContext) {
        super.update(executionContext);
        left.update(executionContext);
    }

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

    @Override
    public synchronized KeyComparison read() throws Exception {
        if (!isOpen()) {
            return null;
        }
        if (iterator.hasNext()) {
            return iterator.next();
        }
        List> leftItems = left.readChunk();
        List keys = leftItems.stream().map(KeyValue::getKey).collect(Collectors.toList());
        List> rightItems = rightKeyValueReader.process(keys);
        List results = new ArrayList<>();
        for (int index = 0; index < leftItems.size(); index++) {
            KeyValue leftItem = leftItems.get(index);
            KeyValue rightItem = getElement(rightItems, index);
            Status status = compare(leftItem, rightItem);
            results.add(new KeyComparison(leftItem, rightItem, status));
        }
        iterator = results.iterator();
        if (iterator.hasNext()) {
            return iterator.next();
        }
        return null;
    }

    private  T getElement(List list, int index) {
        if (list == null || index >= list.size()) {
            return null;
        }
        return list.get(index);
    }

    private Status compare(KeyValue left, KeyValue right) {
        if (right == null) {
            return Status.MISSING;
        }
        if (!Objects.equals(left.getType(), right.getType())) {
            if (KeyValue.isNone(right)) {
                return Status.MISSING;
            }
            return Status.TYPE;
        }
        if (!Objects.deepEquals(left.getValue(), right.getValue())) {
            return Status.VALUE;
        }
        Duration ttlDiff = Duration.ofMillis(Math.abs(left.getTtl() - right.getTtl()));
        if (ttlDiff.compareTo(ttlTolerance) > 0) {
            return Status.TTL;
        }
        return Status.OK;

    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy