Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.zxyinfo.queue.PersistentBusAutoConfiguration Maven / Gradle / Ivy
package com.zxyinfo.queue;
import com.codahale.metrics.MetricRegistry;
import com.google.common.collect.ImmutableMap;
import com.google.common.io.Resources;
import com.zxyinfo.exception.InitializeDatabaseException;
import com.zxyinfo.interceptor.RegisterInterceptor;
import com.zxyinfo.queue.PersistentQueueProperties.DDL;
import com.zxyinfo.surpport.DefaultRetryer;
import com.zxyinfo.surpport.RetryQueueDao;
import com.zxyinfo.surpport.RetryQueueSqlDao;
import com.zxyinfo.util.PropertiesUtils;
import java.io.IOException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;
import javax.sql.DataSource;
import org.killbill.bus.api.PersistentBus;
import org.killbill.bus.api.PersistentBusConfig;
import org.killbill.clock.DefaultClock;
import org.killbill.commons.jdbi.notification.DatabaseTransactionNotificationApi;
import org.killbill.queue.InTransaction;
import org.killbill.queue.OptimizePersistentBus;
import org.skife.config.ConfigurationObjectFactory;
import org.skife.jdbi.v2.DBI;
import org.skife.jdbi.v2.Handle;
import org.slf4j.Logger;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.framework.AopProxyUtils;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.AopUtils;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
import org.springframework.jdbc.datasource.init.ScriptException;
import org.springframework.lang.NonNull;
import org.springframework.util.StringUtils;
/**
* @author joewee
* @version 1.0.0
* @date 2021/9/20 17:55
*/
@EnableConfigurationProperties(PersistentBusProperties.class)
@AutoConfigureAfter({ DataSourceAutoConfiguration.class})
public class PersistentBusAutoConfiguration implements BeanPostProcessor {
private static final Logger log = org.slf4j.LoggerFactory.getLogger(
PersistentBusAutoConfiguration.class);
private final PersistentBusProperties queueProperties;
public PersistentBusAutoConfiguration(PersistentBusProperties queueProperties) {
this.queueProperties = queueProperties;
}
@Override
public Object postProcessBeforeInitialization(@NonNull Object bean,@NonNull String beanName)
throws BeansException {
return bean;
}
@Override
public Object postProcessAfterInitialization(@NonNull Object bean,@NonNull String beanName) throws BeansException {
if (!(bean instanceof PersistentBus)) {
return bean;
}
log.info("post process {} bean of {} ",bean.getClass().getName(),beanName);
ProxyFactory factory = new ProxyFactory();
factory.setTarget(bean);
factory.addAdvisor(registerAdvisor((PersistentBus)bean));
return factory.getProxy();
}
public DefaultPointcutAdvisor registerAdvisor(PersistentBus bus) {
if (AopUtils.isAopProxy(bus)) {
bus = (PersistentBus)AopProxyUtils.getSingletonTarget(bus);
}
RegisterInterceptor interceptor = new RegisterInterceptor(bus);
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
// 配置增强类advisor
pointcut.setExpression("execution(* org.killbill.bus.DefaultPersistentBus.register(*))");
return new DefaultPointcutAdvisor(pointcut, interceptor);
}
/**
* 定义持久化的eventBus
*/
@ConditionalOnMissingBean
@Bean(initMethod = "initQueue", destroyMethod = "stopQueue")
@Primary
public PersistentBus defaultPersistentBus(DataSource dataSource) {
final Properties properties = new Properties();
PropertiesUtils.put(properties, "org.killbill.persistent.bus.main.inMemory", queueProperties.getInMemory());
PropertiesUtils.put(properties, "org.killbill.persistent.bus.main.max.failure.retry", queueProperties.getFailureRetries());
PropertiesUtils.put(properties, "org.killbill.persistent.bus.main.claimed", queueProperties.getClaimed());
PropertiesUtils.put(properties, "org.killbill.persistent.bus.main.queue.mode", queueProperties.getQueueMode());
PropertiesUtils.put(properties, "org.killbill.persistent.bus.main.claim.time", queueProperties.getClaimTime());
PropertiesUtils.put(properties, "org.killbill.persistent.bus.main.sleep", queueProperties.getSleep());
PropertiesUtils.put(properties, "org.killbill.persistent.bus.main.off", queueProperties.getOff());
PropertiesUtils.put(properties, "org.killbill.persistent.bus.main.nbThreads", queueProperties.getMaxDispatchThreads());
PropertiesUtils.put(properties, "org.killbill.persistent.bus.main.lifecycle.dispatch.nbThreads", queueProperties.getLifecycleDispatchThreads());
PropertiesUtils.put(properties, "org.killbill.persistent.bus.main.lifecycle.complete.nbThreads", queueProperties.getLifecycleCompleteThreads());
PropertiesUtils.put(properties, "org.killbill.persistent.bus.main.queue.capacity", queueProperties.getQueueCapacity());
PropertiesUtils.put(properties, "org.killbill.persistent.bus.main.reapThreshold", queueProperties.getReapThreshold());
PropertiesUtils.put(properties, "org.killbill.persistent.bus.main.maxReDispatchCount", queueProperties.getMaxReDispatchCount());
PropertiesUtils.put(properties, "org.killbill.persistent.bus.main.reapSchedule", queueProperties.getReapSchedule());
PropertiesUtils.put(properties, "org.killbill.persistent.bus.main.tableName", queueProperties.getTableName());
PropertiesUtils.put(properties, "org.killbill.persistent.bus.main.historyTableName", queueProperties.getHistoryTableName());
final PersistentBusConfig busConfig = new ConfigurationObjectFactory(properties).buildWithReplacements(PersistentBusConfig.class,
ImmutableMap.of("instanceName", "main"));
final DBI dbi = InTransaction.buildDDBI(dataSource);
if ( DDL.AUTO.equals(queueProperties.getDdl())) {
initialize(dbi);
}
final DefaultClock clock = new DefaultClock();
DefaultRetryer defaultRetryer = null;
if (Boolean.TRUE.equals(queueProperties.getEnableRetry())) {
//启用重试线程
final Long retryClaimedTime = queueProperties.getRetryClaimedTime();
final Integer maxRetries = queueProperties.getMaxRetries();
final RetryQueueDao retryQueueDao = new RetryQueueDao(dbi, RetryQueueSqlDao.class,busConfig,maxRetries,retryClaimedTime);
defaultRetryer =new DefaultRetryer(retryQueueDao, busConfig, clock);
}
return new OptimizePersistentBus(dbi, clock,
busConfig, new MetricRegistry(),
new DatabaseTransactionNotificationApi(), defaultRetryer);
}
@Bean
public OptimizePersistentBus optimizePersistentBus(PersistentBus defaultPersistentBus) {
return (OptimizePersistentBus) defaultPersistentBus;
}
@Bean
public DeadEventHandler deadEventHandler(PersistentBus defaultPersistentBus){
return new DeadEventHandler(defaultPersistentBus);
}
private void initialize(final DBI dbi){
try(final Handle handle = dbi.open()) {
final Connection connection = handle.getConnection();
final String database = connection.getMetaData().getDatabaseProductName();
URL resource = loadResource(database);
if (resource==null) {
log.warn("自动创建不支持当前数据库类型:"+database);
return;
}
String tableName = StringUtils.isEmpty(queueProperties.getTableName()) ?
PersistentBusProperties.TABLE_NAME : queueProperties.getTableName();
String historyTableName = StringUtils.isEmpty(queueProperties.getHistoryTableName()) ?
PersistentBusProperties.HISTORY_TABLE_NAME : queueProperties.getHistoryTableName();
final String sql = PropertiesUtils.load(resource.openStream()).replace("${tableName}", tableName)
.replace("${historyTableName}", historyTableName);
final ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
populator.addScripts(new ByteArrayResource(sql.getBytes(StandardCharsets.UTF_8)));
populator.populate(connection);
} catch (ScriptException e){
final String message = e.getMessage();
if (message!=null&&(message.contains("Duplicate")||message.contains("already exists"))) {
//创建重复
log.warn(message);
}else{
throw new InitializeDatabaseException("初始化数据库表失败:", e);
}
}catch( IOException | SQLException e) {
throw new InitializeDatabaseException("初始化数据库表失败:", e);
}
}
private URL loadResource(String database){
try {
if(database.contains("MySQL")){
return Resources.getResource("org/killbill/queue/bus_events_mysql.sql");
}
}catch (Exception e){
log.error(e.getMessage(),e);
}
return null;
}
}