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

com.zxyinfo.surpport.RetryQueueDao Maven / Gradle / Ivy

package com.zxyinfo.surpport;

import java.sql.SQLException;
import java.sql.SQLWarning;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.killbill.CreatorName;
import org.killbill.bus.dao.BusEventModelDao;
import org.killbill.queue.api.PersistentQueueConfig;
import org.killbill.queue.api.PersistentQueueEntryLifecycleState;
import org.skife.jdbi.v2.Handle;
import org.skife.jdbi.v2.IDBI;
import org.skife.jdbi.v2.Transaction;
import org.skife.jdbi.v2.TransactionCallback;
import org.skife.jdbi.v2.TransactionStatus;
import org.springframework.util.Assert;

/**
 * @author joewee
 * @version 1.0.0
 * @date 2021/12/29 17:10
 */
@Slf4j
public class RetryQueueDao {
  protected final Class sqlDaoClass;
  protected final IDBI dbi;
  protected  PersistentQueueConfig config;
  @Getter
  private final Integer maxRetries;
  private final Long retryClaimedTime;
  private final long maxRetryTime;

  public RetryQueueDao(final IDBI dbi, Class sqlDaoClass,
      PersistentQueueConfig config, Integer maxRetries, Long retryClaimedTime) {
    this.dbi = dbi;
    this.sqlDaoClass = sqlDaoClass;
    this.config = config;
    this.maxRetries = maxRetries;
    this.retryClaimedTime = retryClaimedTime;
    this.maxRetryTime = computeMaxRetryTime(maxRetries,retryClaimedTime);
  }

  private long computeMaxRetryTime(Integer maxRetries, Long retryClaimedTime) {
    final int retries = maxRetries - config.getMaxFailureRetries();
    return  (retryClaimedTime + retries * retryClaimedTime) * retries / 2;
  }

  public void retryEntries(Date retryDate,String owner) {
    Assert.state(config!=null,"PersistentQueueConfig缺失");
    final int failureRetries = config.getMaxFailureRetries();
    final String historyTableName = config.getHistoryTableName();
    final int dispatchCount = config.getMaxReDispatchCount();
    executeTransaction(new Transaction() {
      @Override
      public Void inTransaction(RetryQueueSqlDao transactional, TransactionStatus status)
          throws Exception {
        final Date earliestDate = new Date(retryDate.getTime() - maxRetryTime * 1000);
        final List failedEntries=
            transactional.getFailedEntries(owner, dispatchCount,
            retryDate,earliestDate,maxRetries+failureRetries, failureRetries-1,retryClaimedTime,historyTableName);
        if (failedEntries.isEmpty()) {
          return null;
        }
        final Map> map = failedEntries.stream()
            .collect(Collectors.groupingBy(BusEventModelDao::getUserToken));
        final Set>> entries = map.entrySet();
        final List entriesToReInsert = new ArrayList<>(entries.size());
        final List toBeremovedRecords = new ArrayList<>(failedEntries.size());
        for (Entry> entry : entries) {
          final List list = entry.getValue();
          final Optional latest = list.stream()
              .max(Comparator.comparingLong(BusEventModelDao::getRecordId));
          final BusEventModelDao modelDao = latest.orElseThrow(IllegalStateException::new);
          modelDao.setProcessingState(PersistentQueueEntryLifecycleState.AVAILABLE);
          modelDao.setCreatingOwner(CreatorName.get());
          modelDao.setProcessingOwner(null);
          modelDao.setErrorCount(modelDao.getErrorCount()+1);
          entriesToReInsert.add(modelDao);
          final List idList = list.stream().map(BusEventModelDao::getRecordId).collect(
              Collectors.toList());
          toBeremovedRecords.addAll(idList);
        }
        transactional.removeEntries(toBeremovedRecords, historyTableName);
        transactional.insertEntries(entriesToReInsert, config.getTableName());
        return null;
      }
    });
  }
  protected  U executeTransaction(final Transaction transaction) {
    return dbi.inTransaction(new TransactionCallback() {
      @Override
      public U inTransaction(final Handle handle, final TransactionStatus status) throws Exception {
        final U result = transaction.inTransaction(handle.attach(sqlDaoClass), status);
        printSQLWarnings(handle);
        return result;
      }
    });
  }
  protected void printSQLWarnings(final Handle handle) {
    try {
      SQLWarning warning = handle.getConnection().getWarnings();
      while (warning != null) {
        log.debug("[SQL WARNING] {}", warning);
        warning = warning.getNextWarning();
      }
      handle.getConnection().clearWarnings();
    } catch (final SQLException e) {
      log.debug("Error whilst retrieving SQL warnings", e);
    }
  }
}