feat: 每站点独立版本号+总版本=SUM+规则变更同步所有同类型站点

This commit is contained in:
mediabot-pt
2026-07-05 22:06:11 +08:00
parent 8a2f6144a7
commit f493d52b5f
8 changed files with 23 additions and 16 deletions

View File

@@ -37,10 +37,7 @@ public class FlywayConfig {
"rules_json LONGTEXT NOT NULL, deleted TINYINT NOT NULL DEFAULT 0, " + "rules_json LONGTEXT NOT NULL, deleted TINYINT NOT NULL DEFAULT 0, " +
"created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, " + "created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, " +
"INDEX idx_site_type (site_type, deleted)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4"); "INDEX idx_site_type (site_type, deleted)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
stmt.execute("CREATE TABLE IF NOT EXISTS manifest_version (" + try { stmt.execute("ALTER TABLE sites ADD COLUMN version INT NOT NULL DEFAULT 1"); } catch (Exception ex) { log.debug("version may exist"); }
"id INT PRIMARY KEY DEFAULT 1, version INT NOT NULL DEFAULT 1, updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP," +
"CHECK (id = 1)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
stmt.execute("INSERT IGNORE INTO manifest_version (id, version) VALUES (1, 1)");
log.info("V15 tables initialized"); log.info("V15 tables initialized");
} catch (Exception e) { } catch (Exception e) {
log.error("V15 migration failed: {}", e.getMessage()); log.error("V15 migration failed: {}", e.getMessage());

View File

@@ -61,6 +61,7 @@ public class ManifestController {
entry.put("siteType", site.getSiteType() != null ? site.getSiteType().getValue() : null); entry.put("siteType", site.getSiteType() != null ? site.getSiteType().getValue() : null);
entry.put("schemaVersion", site.getSchemaVersion()); entry.put("schemaVersion", site.getSchemaVersion());
entry.put("status", site.getStatus() != null ? site.getStatus().getValue() : null); entry.put("status", site.getStatus() != null ? site.getStatus().getValue() : null);
entry.put("version", site.getVersion() != null ? site.getVersion() : 1);
SiteConfig latest = siteConfigMapper.selectLatestBySiteId(site.getSiteId()); SiteConfig latest = siteConfigMapper.selectLatestBySiteId(site.getSiteId());
if (latest != null) { if (latest != null) {

View File

@@ -55,6 +55,9 @@ public class Site {
@TableField("current_config_id") @TableField("current_config_id")
private Long currentConfigId; private Long currentConfigId;
@TableField("version")
private Integer version;
@TableField("status") @TableField("status")
private SiteStatus status; private SiteStatus status;

View File

@@ -6,8 +6,8 @@ import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
/** /**
* Manifest 全局版本号管理 * Manifest 版本管理:每个站点独立版本,总版本 = 所有站点版本之和
* 任何站点/页面/规则/脚本变更时递增,mediabot 据此判断是否需要拉取最新数据 * 站点/页面/脚本变更时递增对应站点版本,规则变更时递增同类型所有站点版本
*/ */
@Slf4j @Slf4j
@Service @Service
@@ -16,15 +16,21 @@ public class ManifestVersionService {
private final JdbcTemplate jdbc; private final JdbcTemplate jdbc;
/** 获取当前版本号 */ /** 全局总版本 = 所有站点版本之和 */
public int current() { public int current() {
Integer v = jdbc.queryForObject("SELECT version FROM manifest_version WHERE id=1", Integer.class); Integer v = jdbc.queryForObject("SELECT COALESCE(SUM(version), 0) FROM sites WHERE deleted=0", Integer.class);
return v != null ? v : 1; return v != null ? v : 0;
} }
/** 递增版本号并返回新值 */ /** 递增指定站点的版本号 */
public int increment() { public int increment(String siteId) {
jdbc.update("UPDATE manifest_version SET version = version + 1, updated_at = NOW() WHERE id=1"); jdbc.update("UPDATE sites SET version = version + 1 WHERE site_id = ? AND deleted=0", siteId);
return current(); return current();
} }
/** 递增指定类型下所有站点的版本号(用于风险规则变更) */
public void incrementByType(String siteType) {
jdbc.update("UPDATE sites SET version = version + 1 WHERE site_type = ? AND deleted=0",
siteType);
}
} }

View File

@@ -72,7 +72,7 @@ public class ConfigServiceImpl implements ConfigService {
config.setIsLatest(false); config.setIsLatest(false);
siteConfigMapper.insert(config); siteConfigMapper.insert(config);
versionService.increment(); versionService.increment(siteId);
log.info("Config submitted: siteId={}, version={}, id={}, scriptPath={}", siteId, version, config.getId(), scriptPath); log.info("Config submitted: siteId={}, version={}, id={}, scriptPath={}", siteId, version, config.getId(), scriptPath);
return config; return config;
} }

View File

@@ -63,7 +63,7 @@ public class RiskRuleServiceImpl implements RiskRuleService {
// 存七牛云 + 本地缓存 // 存七牛云 + 本地缓存
String storagePath = String.format("rules/%s/v%d.json", siteType, nextVer); String storagePath = String.format("rules/%s/v%d.json", siteType, nextVer);
storageService.store(storagePath, json); storageService.store(storagePath, json);
versionService.increment(); versionService.incrementByType(siteType);
log.info("风险规则已保存: siteType={}, version={}, path={}", siteType, nextVer, storagePath); log.info("风险规则已保存: siteType={}, version={}, path={}", siteType, nextVer, storagePath);
} catch (Exception e) { } catch (Exception e) {
log.error("保存风险规则失败 siteType={}", siteType, e); log.error("保存风险规则失败 siteType={}", siteType, e);

View File

@@ -70,7 +70,7 @@ public class SitePagesServiceImpl implements SitePagesService {
// 存七牛云 + 本地缓存 // 存七牛云 + 本地缓存
String storagePath = String.format("pages/%s/v%s.json", siteId, version); String storagePath = String.format("pages/%s/v%s.json", siteId, version);
storageService.store(storagePath, json); storageService.store(storagePath, json);
versionService.increment(); versionService.increment(siteId);
log.info("页面配置已保存: siteId={}, version={}, path={}", siteId, version, storagePath); log.info("页面配置已保存: siteId={}, version={}, path={}", siteId, version, storagePath);
} catch (Exception e) { } catch (Exception e) {
log.error("保存页面配置失败 siteId={}", siteId, e); log.error("保存页面配置失败 siteId={}", siteId, e);

View File

@@ -232,7 +232,7 @@ public class SiteServiceImpl implements SiteService {
try { site.setStatus(SiteStatus.fromValue(status)); } catch (Exception ignored) {} try { site.setStatus(SiteStatus.fromValue(status)); } catch (Exception ignored) {}
} }
siteMapper.updateById(site); siteMapper.updateById(site);
versionService.increment(); versionService.increment(siteId);
log.info("站点编辑: siteId={}", siteId); log.info("站点编辑: siteId={}", siteId);
return site; return site;
} }