Browse Source

feat: 导出设置重试机制

lixuesong 5 days ago
parent
commit
dd21a94bac

+ 50 - 0
hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/config/RetryConfiguration.java

@@ -0,0 +1,50 @@
+package com.qunzhixinxi.hnqz.admin.config;
+
+import com.qunzhixinxi.hnqz.common.core.exception.BizException;
+import lombok.RequiredArgsConstructor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.retry.annotation.EnableRetry;
+import org.springframework.retry.backoff.FixedBackOffPolicy;
+import org.springframework.retry.policy.SimpleRetryPolicy;
+import org.springframework.retry.support.RetryTemplate;
+
+import java.util.Collections;
+
+/**
+ * 重试配置
+ *
+ * @author snows
+ * @date 2025/08/04
+ */
+@EnableRetry
+@Configuration
+@RequiredArgsConstructor
+public class RetryConfiguration {
+
+	private final UpmsConfig upmsConfig;
+
+	/**
+	 * 重试模板
+	 *
+	 * @return {@link RetryTemplate } 重试模板实例
+	 */
+	@Bean
+	public RetryTemplate retryTemplate() {
+		// 构建重试模板实例
+		RetryTemplate retryTemplate = new RetryTemplate();
+
+		// 设置重试回退操作策略,主要设置重试间隔时间
+		FixedBackOffPolicy backOffPolicy = new FixedBackOffPolicy();
+		backOffPolicy.setBackOffPeriod(upmsConfig.getRetryBackOffPeriod());
+
+		// 设置重试策略,主要设置重试次数
+		SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(upmsConfig.getMaxRetryTimes(), Collections
+				.<Class<? extends Throwable>, Boolean>singletonMap(BizException.class, true));
+
+		retryTemplate.setRetryPolicy(retryPolicy);
+		retryTemplate.setBackOffPolicy(backOffPolicy);
+
+		return retryTemplate;
+	}
+}

+ 10 - 0
hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/config/UpmsConfig.java

@@ -69,4 +69,14 @@ public class UpmsConfig {
 	 */
 	private Integer asyncExportLimit = 3;
 
+	/**
+	 * 异步导出重试间隔时间(固定时间的退避策略)
+	 */
+	private Long retryBackOffPeriod = 60000L;
+
+	/**
+	 * 异步最大重试次数
+	 */
+	private Integer maxRetryTimes = 3;
+
 }

+ 27 - 19
hnqz-upms/hnqz-upms-biz/src/main/java/com/qunzhixinxi/hnqz/admin/service/impl/SysUserExportServiceImpl.java

@@ -39,6 +39,7 @@ import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.RandomStringUtils;
 import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.retry.support.RetryTemplate;
 import org.springframework.stereotype.Service;
 
 import java.io.File;
@@ -77,6 +78,7 @@ public class SysUserExportServiceImpl implements SysUserExportService {
 	private final SysUserCertificateMapper userCertificateMapper;
 	private final SysFileService fileService;
 	private final UpmsConfig upmsConfig;
+	private final RetryTemplate retryTemplate;
 
 	private static final long DEF_REPORT_TTL = 7L * 24 * 60 * 60 * 1000;
 	private static final String ERROR_MSG_UNKNOWN = "ERROR_未知错误,请联系管理员";
@@ -86,6 +88,7 @@ public class SysUserExportServiceImpl implements SysUserExportService {
 
 	/**
 	 * 异步导出
+	 * 设置重试次数和重试间隔
 	 *
 	 * @param user  用户
 	 * @param roles 角色
@@ -94,29 +97,34 @@ public class SysUserExportServiceImpl implements SysUserExportService {
 	 */
 	@Override
 	public Boolean asyncExport(HnqzUser user, List<Integer> roles, SysUserDTO.OnList query) {
-		// 使用Redis原子操作实现限流,避免使用synchronized影响并发性能
-		String key = CacheConstants.ASYNC_EXPORT_LIMIT_KEY;
-		Long increment = redisTemplate.opsForValue().increment(key);
+		return retryTemplate.execute(retryContext -> {
+			log.info("人员异步导出第{}次重试", retryContext.getRetryCount());
 
-		// 设置key的过期时间,避免计数器无限增长
-		if (increment != null && increment.equals(1L)) {
-			redisTemplate.expire(key, 1, TimeUnit.MINUTES);
-		}
+			// 使用Redis原子操作实现限流
+			String key = CacheConstants.ASYNC_EXPORT_LIMIT_KEY;
+			Long increment = redisTemplate.opsForValue().increment(key);
 
-		// 检查是否超过限流阈值
-		if (increment != null && increment > upmsConfig.getAsyncExportLimit()) {
-			// 超过限流阈值时,减少计数器并抛出异常
-			redisTemplate.opsForValue().decrement(key);
-			throw new BizException("系统繁忙,请稍后再试");
-		}
+			// 设置key的过期时间,避免计数器无限增长
+			if (increment != null && increment.equals(1L)) {
+				redisTemplate.expire(key, 1, TimeUnit.MINUTES);
+			}
 
-		// 缓存key
-		String cacheKey = String.format(CacheConstants.ASYNC_EXPORT_CACHE, ExportType.USER.getType(), user.getId());
-		// 更新状态为生成中
-		redisTemplate.opsForValue().set(cacheKey, WmReportOpt.WmReportOptStatus.GENERATING.name(), DEF_REPORT_TTL, TimeUnit.MILLISECONDS);
+			// 检查是否超过限流阈值
+			if (increment != null && increment > upmsConfig.getAsyncExportLimit()) {
+				// 超过限流阈值时,减少计数器并抛出异常
+				redisTemplate.opsForValue().decrement(key);
+				throw new BizException("系统繁忙,请稍后再试");
+			}
+
+			// 缓存key
+			String cacheKey = String.format(CacheConstants.ASYNC_EXPORT_CACHE, ExportType.USER.getType(), user.getId());
+			// 更新状态为生成中
+			redisTemplate.opsForValue().set(cacheKey, WmReportOpt.WmReportOptStatus.GENERATING.name(), DEF_REPORT_TTL, TimeUnit.MILLISECONDS);
+
+			SpringContextHolder.getApplicationContext().publishEvent(new UserExportEvent(user, roles, query));
+			return Boolean.TRUE;
+		});
 
-		SpringContextHolder.getApplicationContext().publishEvent(new UserExportEvent(user, roles, query));
-		return Boolean.TRUE;
 	}
 
 	/**