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

com.mageddo.tobby.replicator.InsertIdempotenceBasedReplicator Maven / Gradle / Ivy

There is a newer version: 2.1.6-alpha
Show newest version
package com.mageddo.tobby.replicator;

import java.sql.Connection;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.concurrent.atomic.AtomicInteger;

import com.mageddo.db.ConnectionUtils;
import com.mageddo.tobby.ParameterDAO;
import com.mageddo.tobby.ProducedRecord;
import com.mageddo.tobby.RecordDAO;

import lombok.extern.slf4j.Slf4j;

import static com.mageddo.tobby.Parameter.LAST_PROCESSED_TIMESTAMP;

@Slf4j
public class InsertIdempotenceBasedReplicator implements Replicator, StreamingIterator {

  private final BufferedReplicator bufferedReplicator;
  private final Connection readConn;
  private final Connection writeConn;
  private final RecordDAO recordDAO;
  private final ParameterDAO parameterDAO;
  private final Duration maxRecordDelayToCommit;
  private final int fetchSize;
  private LocalDateTime lastRecordCreatedAt;

  public InsertIdempotenceBasedReplicator(
      Connection readConn, Connection writeConn, RecordDAO recordDAO,
      ParameterDAO parameterDAO, BufferedReplicator bufferedReplicator,
      Duration maxRecordDelayToCommit, int fetchSize
  ) {
    this.bufferedReplicator = bufferedReplicator;
    this.readConn = readConn;
    this.writeConn = writeConn;
    this.recordDAO = recordDAO;
    this.parameterDAO = parameterDAO;
    this.maxRecordDelayToCommit = maxRecordDelayToCommit;
    this.fetchSize = fetchSize;
  }

  @Override
  public boolean send(ProducedRecord record) {
    this.lastRecordCreatedAt = record.getCreatedAt();
    this.recordDAO.acquireInserting(this.writeConn, record.getId());
    if (this.bufferedReplicator.send(record)) {
      this.flush();
    }
    return false;
  }

  @Override
  public void flush() {
    ConnectionUtils.useTransaction(this.writeConn, () -> {
      this.bufferedReplicator.flush();
      this.updateLastSent();
    });
  }

  @Override
  public int iterate(Connection readConn) {
    final AtomicInteger counter = new AtomicInteger();
    this.recordDAO.iterateNotProcessedRecordsUsingInsertIdempotence(
        this.readConn, this.fetchSize, (record) -> {
          counter.incrementAndGet();
          this.send(record);
        },
        this.findLastUpdate(this.readConn)
    );
    this.flush();
    return counter.get();
  }

  private void updateLastSent() {
    this.updateLastUpdate(this.writeConn, this.lastRecordCreatedAt);
  }

  private void updateLastUpdate(Connection connection, LocalDateTime createdAt) {
    if (createdAt == null) {
      if (log.isDebugEnabled()) {
        log.debug("status=no-date-to-update");
      }
      return;
    }
    this.parameterDAO.insertOrUpdate(connection, LAST_PROCESSED_TIMESTAMP, createdAt.toString());
  }

  private LocalDateTime findLastUpdate(Connection connection) {
    return this.parameterDAO
        .findAsDateTime(
            connection, LAST_PROCESSED_TIMESTAMP, LocalDateTime.parse("2000-01-01T00:00:00")
        )
        .minusMinutes(this.maxRecordDelayToCommit.toMinutes());
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy