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 extends RetryQueueSqlDao> 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 extends RetryQueueSqlDao> 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);
}
}
}