diff --git a/public/init.html b/public/init.html
index 55bafe9..3e1bc3a 100644
--- a/public/init.html
+++ b/public/init.html
@@ -116,12 +116,35 @@
+
+
+
+
+
+
-
-
-
+
+
+
+
diff --git a/public/js/init.js b/public/js/init.js
index 46707b9..0324e45 100644
--- a/public/js/init.js
+++ b/public/js/init.js
@@ -4,8 +4,12 @@ document.addEventListener('DOMContentLoaded', () => {
const userInput = document.getElementById('user');
const passwordInput = document.getElementById('password');
const databaseInput = document.getElementById('database');
+ const vHostInput = document.getElementById('vHost');
+ const vPortInput = document.getElementById('vPort');
+ const vPasswordInput = document.getElementById('vPassword');
const btnTest = document.getElementById('btnTest');
+ const btnTestValkey = document.getElementById('btnTestValkey');
const btnInit = document.getElementById('btnInit');
const messageBox = document.getElementById('messageBox');
@@ -101,6 +105,34 @@ document.addEventListener('DOMContentLoaded', () => {
btnTest.textContent = oldText;
}
});
+
+ btnTestValkey.addEventListener('click', async () => {
+ btnTestValkey.disabled = true;
+ const oldText = btnTestValkey.textContent;
+ btnTestValkey.textContent = '测试中...';
+ try {
+ const res = await fetch('/api/setup/test-valkey', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({
+ host: vHostInput.value,
+ port: vPortInput.value,
+ password: vPasswordInput.value
+ })
+ });
+ const data = await res.json();
+ if (data.success) {
+ showMessage('Valkey 连接成功!');
+ } else {
+ showMessage('Valkey 连接失败: ' + (data.error || '未知错误'), true);
+ }
+ } catch (err) {
+ showMessage('Valkey 请求失败: ' + err.message, true);
+ } finally {
+ btnTestValkey.disabled = false;
+ btnTestValkey.textContent = oldText;
+ }
+ });
btnInit.addEventListener('click', async () => {
btnInit.disabled = true;
@@ -115,7 +147,10 @@ document.addEventListener('DOMContentLoaded', () => {
port: portInput.value,
user: userInput.value,
password: passwordInput.value,
- database: databaseInput.value
+ database: databaseInput.value,
+ vHost: vHostInput.value,
+ vPort: vPortInput.value,
+ vPassword: vPasswordInput.value
})
});
const data = await res.json();
diff --git a/server/cache.js b/server/cache.js
index 0feac6d..422f124 100644
--- a/server/cache.js
+++ b/server/cache.js
@@ -1,32 +1,42 @@
const Redis = require('ioredis');
-const host = process.env.VALKEY_HOST || 'localhost';
-const port = parseInt(process.env.VALKEY_PORT) || 6379;
-const password = process.env.VALKEY_PASSWORD || undefined;
-const db = parseInt(process.env.VALKEY_DB) || 0;
-const ttl = parseInt(process.env.VALKEY_TTL) || 30;
-
let redis = null;
+let ttl = 30;
-try {
- redis = new Redis({
- host,
- port,
- password,
- db,
- lazyConnect: true,
- maxRetriesPerRequest: 1
- });
+function init() {
+ if (redis) {
+ redis.disconnect();
+ }
- redis.on('error', (err) => {
- // Fail silently after one retry, we just won't cache
- console.warn('[Cache] Valkey connection failed, caching disabled:', err.message);
- });
-} catch (err) {
- console.warn('[Cache] Valkey init failed:', err.message);
+ const host = process.env.VALKEY_HOST || 'localhost';
+ const port = parseInt(process.env.VALKEY_PORT) || 6379;
+ const password = process.env.VALKEY_PASSWORD || undefined;
+ const db = parseInt(process.env.VALKEY_DB) || 0;
+ ttl = parseInt(process.env.VALKEY_TTL) || 30;
+
+ try {
+ redis = new Redis({
+ host,
+ port,
+ password,
+ db,
+ lazyConnect: true,
+ maxRetriesPerRequest: 1
+ });
+
+ redis.on('error', (err) => {
+ // Fail silently after one retry, we just won't cache
+ console.warn('[Cache] Valkey connection failed, caching disabled:', err.message);
+ });
+ } catch (err) {
+ console.warn('[Cache] Valkey init failed:', err.message);
+ }
}
+init();
+
const cache = {
+ init,
async get(key) {
if (!redis) return null;
try {
diff --git a/server/index.js b/server/index.js
index 50b0064..8da6418 100644
--- a/server/index.js
+++ b/server/index.js
@@ -137,8 +137,29 @@ app.post('/api/setup/test', async (req, res) => {
}
});
+app.post('/api/setup/test-valkey', async (req, res) => {
+ const { host, port, password } = req.body;
+ try {
+ const Redis = require('ioredis');
+ const redis = new Redis({
+ host: host || 'localhost',
+ port: parseInt(port) || 6379,
+ password: password || undefined,
+ lazyConnect: true,
+ maxRetriesPerRequest: 1,
+ connectTimeout: 5000
+ });
+ await redis.connect();
+ await redis.ping();
+ await redis.disconnect();
+ res.json({ success: true, message: 'Valkey connection successful' });
+ } catch (err) {
+ res.status(400).json({ success: false, error: err.message });
+ }
+});
+
app.post('/api/setup/init', async (req, res) => {
- const { host, port, user, password, database } = req.body;
+ const { host, port, user, password, database, vHost, vPort, vPassword } = req.body;
try {
const mysql = require('mysql2/promise');
const connection = await mysql.createConnection({
@@ -211,6 +232,9 @@ MYSQL_PORT=${port || '3306'}
MYSQL_USER=${user || 'root'}
MYSQL_PASSWORD=${password || ''}
MYSQL_DATABASE=${dbName}
+VALKEY_HOST=${vHost || 'localhost'}
+VALKEY_PORT=${vPort || '6379'}
+VALKEY_PASSWORD=${vPassword || ''}
PORT=${process.env.PORT || 3000}
HOST=${process.env.HOST || '0.0.0.0'}
REFRESH_INTERVAL=${process.env.REFRESH_INTERVAL || 5000}
@@ -223,9 +247,13 @@ REFRESH_INTERVAL=${process.env.REFRESH_INTERVAL || 5000}
process.env.MYSQL_USER = user;
process.env.MYSQL_PASSWORD = password;
process.env.MYSQL_DATABASE = dbName;
+ process.env.VALKEY_HOST = vHost;
+ process.env.VALKEY_PORT = vPort;
+ process.env.VALKEY_PASSWORD = vPassword;
- // Re-initialize pool
+ // Re-initialize pools
db.initPool();
+ cache.init();
isDbInitialized = true;
res.json({ success: true, message: 'Initialization complete' });
@@ -607,6 +635,10 @@ app.get('/api/metrics/overview', async (req, res) => {
// Get network traffic history (past 24h) from Prometheus
app.get('/api/metrics/network-history', async (req, res) => {
try {
+ const cacheKey = 'network_history_all';
+ const cached = await cache.get(cacheKey);
+ if (cached) return res.json(cached);
+
const [sources] = await db.query('SELECT * FROM prometheus_sources');
if (sources.length === 0) {
return res.json({ timestamps: [], rx: [], tx: [] });
@@ -625,6 +657,7 @@ app.get('/api/metrics/network-history', async (req, res) => {
}
const merged = prometheusService.mergeNetworkHistories(validHistories);
+ await cache.set(cacheKey, merged, 300); // Cache for 5 minutes
res.json(merged);
} catch (err) {
console.error('Error fetching network history history:', err);