package cn.iocoder.yudao.server.framework.bizno;
import cn.iocoder.yudao.framework.common.util.number.BizNoUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;
import javax.sql.DataSource;
import java.util.List;
import java.util.Map;
/**
* 已用业务编码集合兜底初始化。
*
*
业务编码为「随机 16 位纯数字」,唯一性靠 Redis 集合({@link BizNoUtils#USED_SET_KEY})查重。
* 若 Redis 丢失该集合,已生成的历史编码会被"忘记",之后可能被重新随机命中而重号。
*
*
因此:启动时若发现该集合 **不存在**,则从数据库中扫描所有业务编码列里的
* 「16 位纯数字」编码,重新载入集合,恢复防重能力。
*
*
说明:
*
* - 仅在集合缺失时扫描(正常启动无额外开销);
* - best-effort,失败只告警、不影响启动;
* - 旧的带字母编码会被忽略。
*
*/
@Component
@Slf4j
public class BizCodeSetInitializer implements ApplicationRunner {
/** 集合初始化标记(非 16 位,不会与真实编码冲突),用于在库内无编码时也标记为已初始化 */
private static final String INIT_MARKER = "__initialized__";
private final StringRedisTemplate stringRedisTemplate;
private final JdbcTemplate jdbcTemplate;
public BizCodeSetInitializer(StringRedisTemplate stringRedisTemplate, DataSource dataSource) {
this.stringRedisTemplate = stringRedisTemplate;
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
@Override
public void run(ApplicationArguments args) {
if (Boolean.TRUE.equals(stringRedisTemplate.hasKey(BizNoUtils.USED_SET_KEY))) {
log.info("[run][已用编码集合兜底] 集合已存在,跳过库内扫描");
return;
}
long start = System.currentTimeMillis();
long total = 0L;
try {
String schema = jdbcTemplate.queryForObject("SELECT DATABASE()", String.class);
List