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

no.ssb.rawdata.provider.state.h2.H2StatePersistence Maven / Gradle / Ivy

The newest version!
package no.ssb.rawdata.provider.state.h2;

import io.reactivex.Flowable;
import io.reactivex.Maybe;
import io.reactivex.Single;
import no.ssb.rawdata.api.persistence.CompletedPositionPublisher;
import no.ssb.rawdata.api.persistence.PersistenceException;
import no.ssb.rawdata.api.state.CompletedPosition;
import no.ssb.rawdata.api.state.StatePersistence;
import no.ssb.rawdata.api.util.FileAndClasspathReaderUtils;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.time.Instant;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Set;

public class H2StatePersistence implements StatePersistence {

    private final H2TransactionFactory transactionFactory;

    public H2StatePersistence(H2TransactionFactory transactionFactory) {
        this.transactionFactory = transactionFactory;
    }

    H2TransactionFactory getTransactionFactory() {
        return transactionFactory;
    }

    @Override
    public void close() throws IOException {
        transactionFactory.close();
    }

    @Override
    public Single expectedPagePositions(String namespace, Set pagePositions) {
        return Single.fromCallable(() -> {
            try (H2Transaction tx = transactionFactory.createTransaction(false)) {
                try {
                    PreparedStatement insert = tx.connection.prepareStatement("INSERT INTO expected_positions (namespace, opaque_id, synthetic_id, batch_ts) VALUES (?, ?, ?, ?)");
                    Timestamp version = new Timestamp(Instant.now().toEpochMilli());
                    int n = 1;
                    for (String pagePosition : pagePositions) {
                        PreparedStatement select = tx.connection.prepareStatement("SELECT count(*) FROM expected_positions WHERE namespace=? AND opaque_id=?");
                        select.setString(1, namespace);
                        select.setString(2, pagePosition);
                        ResultSet selectResultSet = select.executeQuery();
                        if (selectResultSet.next() && selectResultSet.getInt(1) > 0) {
                            continue;
                        }
                        insert.setString(1, namespace);
                        insert.setString(2, pagePosition);
                        insert.setInt(3, n);
                        insert.setTimestamp(4, version);
                        insert.addBatch();
                        n++;
                    }
                    return insert.executeBatch().length == n - 1;
                } catch (SQLException e) {
                    throw new PersistenceException(e);
                }
            }
        });
    }

    @Override
    public Single trackCompletedPositions(String namespace, Set completedPositions) {
        return Single.fromCallable(() -> {
            try (H2Transaction tx = transactionFactory.createTransaction(false)) {
                try {
                    PreparedStatement ps = tx.connection.prepareStatement("INSERT INTO completed_positions (namespace, opaque_id) VALUES (?, ?)");
                    int n = 1;
                    for (String completedPosition : completedPositions) {
                        ps.setString(1, namespace);
                        ps.setString(2, completedPosition);
                        ps.addBatch();
                        n++;
                    }
                    return ps.executeBatch().length == n - 1;
                } catch (SQLException e) {
                    throw new PersistenceException(e);
                }
            }
        });
    }

    @Override
    public Maybe getFirstPosition(String namespace) {
        return Maybe.fromCallable(() -> {
            try (H2Transaction tx = transactionFactory.createTransaction(true)) {
                try {
                    String sql = FileAndClasspathReaderUtils.getResourceAsString("h2/first-position.sql", StandardCharsets.UTF_8);
                    PreparedStatement ps = tx.connection.prepareStatement(sql);
                    ps.setString(1, namespace);
                    ps.setString(2, namespace);
                    ps.setString(3, namespace);
                    ps.setString(4, namespace);
                    ps.setString(5, namespace);
                    ResultSet rs = ps.executeQuery();
                    if (rs.next()) {
                        return rs.getString(2);
                    }
                    return null;
                } catch (SQLException e) {
                    throw new PersistenceException(e);
                }
            }
        });
    }

    @Override
    public Maybe getLastPosition(String namespace) {
        return Maybe.fromCallable(() -> {
            try (H2Transaction tx = transactionFactory.createTransaction(true)) {
                try {
                    String sql = FileAndClasspathReaderUtils.getResourceAsString("h2/last-position.sql", StandardCharsets.UTF_8);
                    PreparedStatement ps = tx.connection.prepareStatement(sql);
                    ps.setString(1, namespace);
                    ps.setString(2, namespace);
                    ps.setString(3, namespace);
                    ps.setString(4, namespace);
                    ps.setString(5, namespace);
                    ps.setString(6, namespace);
                    ResultSet rs = ps.executeQuery();
                    if (rs.next()) {
                        return rs.getString(1);
                    }
                    return null;
                } catch (SQLException e) {
                    throw new PersistenceException(e);
                }
            }
        });    }

    @Override
    public Maybe getNextPosition(String namespace) {
        return Maybe.fromCallable(() -> {
            try (H2Transaction tx = transactionFactory.createTransaction(true)) {
                try {
                    String sql = FileAndClasspathReaderUtils.getResourceAsString("h2/next-position.sql", StandardCharsets.UTF_8);
                    PreparedStatement ps = tx.connection.prepareStatement(sql);
                    ps.setString(1, namespace);
                    ps.setString(2, namespace);
                    ps.setString(3, namespace);
                    ResultSet rs = ps.executeQuery();
                    if (rs.next()) {
                        return rs.getString(2);
                    }
                    return null;
                } catch (SQLException e) {
                    throw new PersistenceException(e);
                }
            }
        });
    }


    @Override
    public Flowable readPositions(String namespace, String fromPosition, String toPosition) {
        final H2Transaction transaction = transactionFactory.createTransaction(true);
        return Single.fromCallable(() -> {
            try {
                String sql = FileAndClasspathReaderUtils.getResourceAsString("h2/find-positions.sql", StandardCharsets.UTF_8);
                PreparedStatement ps = transaction.connection.prepareStatement(sql);
                ps.setString(1, namespace);
                ps.setString(2, namespace);
                ps.setString(3, namespace);
                ps.setString(4, namespace);
                ps.setString(5, namespace);
                ps.setString(6, fromPosition);
                ps.setString(7, namespace);
                ps.setString(8, toPosition);
                ps.setString(9, namespace);
                ps.setString(10, namespace);
                ps.setString(11, namespace);
                ps.setString(12, fromPosition);
                ps.setString(13, namespace);
                ps.setString(14, toPosition);
                ps.setString(15, namespace);
                ps.setString(16, namespace);
                ResultSet resultSet = ps.executeQuery();
                Deque result = new LinkedList<>();
                while (resultSet.next()) {
                    String position = resultSet.getString(2);
                    result.add(new CompletedPosition(namespace, position));
                }
                return result;
            } catch (SQLException e) {
                throw new PersistenceException(e);
            }
        }).flatMapPublisher(result -> Flowable.fromPublisher(new CompletedPositionPublisher(result))
        );
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy