mirror of
https://github.com/Sagit-chu/flvx.git
synced 2026-10-08 02:36:37 +08:00
启动时迁移并回填节点双栈IP列
This commit is contained in:
@@ -10,7 +10,12 @@ import org.springframework.stereotype.Component;
|
|||||||
import javax.annotation.PreDestroy;
|
import javax.annotation.PreDestroy;
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
import java.sql.Statement;
|
import java.sql.Statement;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SQLite 数据库配置
|
* SQLite 数据库配置
|
||||||
@@ -40,6 +45,8 @@ public class SQLiteConfig implements ApplicationRunner {
|
|||||||
statement.execute("PRAGMA busy_timeout=5000;"); // 5秒超时
|
statement.execute("PRAGMA busy_timeout=5000;"); // 5秒超时
|
||||||
statement.execute("PRAGMA wal_autocheckpoint=1000;"); // 每1000页自动checkpoint
|
statement.execute("PRAGMA wal_autocheckpoint=1000;"); // 每1000页自动checkpoint
|
||||||
|
|
||||||
|
ensureNodeDualStackColumns(connection);
|
||||||
|
|
||||||
log.info("SQLite WAL mode configured successfully");
|
log.info("SQLite WAL mode configured successfully");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("Failed to configure SQLite database", e);
|
log.error("Failed to configure SQLite database", e);
|
||||||
@@ -47,6 +54,89 @@ public class SQLiteConfig implements ApplicationRunner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ensureNodeDualStackColumns(Connection connection) throws Exception {
|
||||||
|
Set<String> cols = getTableColumns(connection, "node");
|
||||||
|
if (cols.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ensureColumnIfMissing(connection, cols, "node", "server_ip_v4", "VARCHAR(100)");
|
||||||
|
ensureColumnIfMissing(connection, cols, "node", "server_ip_v6", "VARCHAR(100)");
|
||||||
|
|
||||||
|
backfillNodeDualStackColumns(connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void backfillNodeDualStackColumns(Connection connection) throws Exception {
|
||||||
|
Pattern ipv4 = Pattern.compile("^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$");
|
||||||
|
|
||||||
|
try (Statement statement = connection.createStatement();
|
||||||
|
ResultSet rs = statement.executeQuery("SELECT id, server_ip, server_ip_v4, server_ip_v6 FROM node;");
|
||||||
|
PreparedStatement updV4 = connection.prepareStatement("UPDATE node SET server_ip_v4 = ? WHERE id = ?;");
|
||||||
|
PreparedStatement updV6 = connection.prepareStatement("UPDATE node SET server_ip_v6 = ? WHERE id = ?;")
|
||||||
|
) {
|
||||||
|
while (rs.next()) {
|
||||||
|
long id = rs.getLong("id");
|
||||||
|
String serverIp = rs.getString("server_ip");
|
||||||
|
String v4 = rs.getString("server_ip_v4");
|
||||||
|
String v6 = rs.getString("server_ip_v6");
|
||||||
|
|
||||||
|
if (serverIp == null || serverIp.isBlank()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ((v4 != null && !v4.isBlank()) || (v6 != null && !v6.isBlank())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String trimmed = serverIp.trim();
|
||||||
|
|
||||||
|
if (ipv4.matcher(trimmed).matches()) {
|
||||||
|
updV4.setString(1, trimmed);
|
||||||
|
updV4.setLong(2, id);
|
||||||
|
updV4.executeUpdate();
|
||||||
|
} else {
|
||||||
|
long colonCount = trimmed.chars().filter(ch -> ch == ':').count();
|
||||||
|
if (colonCount >= 2) {
|
||||||
|
updV6.setString(1, trimmed);
|
||||||
|
updV6.setLong(2, id);
|
||||||
|
updV6.executeUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<String> getTableColumns(Connection connection, String table) throws Exception {
|
||||||
|
Set<String> cols = new HashSet<>();
|
||||||
|
try (Statement statement = connection.createStatement();
|
||||||
|
ResultSet rs = statement.executeQuery("PRAGMA table_info(" + table + ");")) {
|
||||||
|
while (rs.next()) {
|
||||||
|
String name = rs.getString("name");
|
||||||
|
if (name != null && !name.isBlank()) {
|
||||||
|
cols.add(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cols;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ensureColumnIfMissing(
|
||||||
|
Connection connection,
|
||||||
|
Set<String> existingColumns,
|
||||||
|
String table,
|
||||||
|
String column,
|
||||||
|
String type
|
||||||
|
) throws Exception {
|
||||||
|
if (existingColumns.contains(column)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try (Statement statement = connection.createStatement()) {
|
||||||
|
statement.execute("ALTER TABLE " + table + " ADD COLUMN " + column + " " + type + ";");
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("SQLite schema updated: added {}.{}", table, column);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 定期执行 checkpoint,确保 WAL 文件内容写入主数据库
|
* 定期执行 checkpoint,确保 WAL 文件内容写入主数据库
|
||||||
* 每5分钟执行一次
|
* 每5分钟执行一次
|
||||||
@@ -80,4 +170,3 @@ public class SQLiteConfig implements ApplicationRunner {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user