Sort order and purging fix

This commit is contained in:
Will Bradley
2025-10-12 05:14:35 -07:00
parent be243e3b50
commit 6a2148ad14
7 changed files with 219 additions and 124 deletions
+12
View File
@@ -50,5 +50,17 @@ module.exports = {
// Logging configuration
logging: {
level: process.env.LOG_LEVEL || 'info'
},
// Channel configuration
channels: {
0: process.env.CHANNEL_0_NAME || 'LongFast',
1: process.env.CHANNEL_1_NAME || 'Aether',
2: process.env.CHANNEL_2_NAME || 'Channel 2',
3: process.env.CHANNEL_3_NAME || 'Channel 3',
4: process.env.CHANNEL_4_NAME || 'Channel 4',
5: process.env.CHANNEL_5_NAME || 'Channel 5',
6: process.env.CHANNEL_6_NAME || 'Channel 6',
7: process.env.CHANNEL_7_NAME || 'Channel 7'
}
};
+68 -2
View File
@@ -34,7 +34,7 @@ const nodeQueries = {
hardware_model = COALESCE(excluded.hardware_model, hardware_model),
role = COALESCE(excluded.role, role),
firmware_version = COALESCE(excluded.firmware_version, firmware_version),
last_heard = COALESCE(excluded.last_heard, CURRENT_TIMESTAMP),
last_heard = CURRENT_TIMESTAMP,
battery_level = COALESCE(excluded.battery_level, battery_level),
voltage = COALESCE(excluded.voltage, voltage),
channel_utilization = COALESCE(excluded.channel_utilization, channel_utilization),
@@ -62,11 +62,77 @@ const nodeQueries = {
(SELECT altitude FROM positions WHERE node_id = n.node_id ORDER BY timestamp DESC LIMIT 1) as altitude,
(SELECT timestamp FROM positions WHERE node_id = n.node_id ORDER BY timestamp DESC LIMIT 1) as position_timestamp
FROM nodes n
ORDER BY n.last_heard DESC
ORDER BY
COALESCE(datetime(n.last_heard), datetime('1970-01-01')) DESC
`),
updateNodeLastHeard: db.prepare(`
UPDATE nodes SET last_heard = CURRENT_TIMESTAMP WHERE node_id = ?
`),
updateNullLastHeard: db.prepare(`
UPDATE nodes
SET last_heard = (
SELECT MAX(latest_time)
FROM (
SELECT MAX(created_at) as latest_time FROM messages WHERE from_node = nodes.node_id
UNION ALL
SELECT MAX(timestamp) as latest_time FROM positions WHERE node_id = nodes.node_id
UNION ALL
SELECT MAX(timestamp) as latest_time FROM telemetry WHERE node_id = nodes.node_id
)
)
WHERE last_heard IS NULL
AND EXISTS (
SELECT 1 FROM messages WHERE from_node = nodes.node_id
UNION
SELECT 1 FROM positions WHERE node_id = nodes.node_id
UNION
SELECT 1 FROM telemetry WHERE node_id = nodes.node_id
)
`),
getOldNodesWithData: db.prepare(`
SELECT
n.node_id,
n.last_heard,
(SELECT COUNT(*) FROM messages WHERE from_node = n.node_id) as message_count,
(SELECT COUNT(*) FROM positions WHERE node_id = n.node_id) as position_count,
(SELECT COUNT(*) FROM telemetry WHERE node_id = n.node_id) as telemetry_count
FROM nodes n
WHERE datetime(last_heard) < datetime('now', '-' || ? || ' hours') OR last_heard IS NULL
`),
deleteOldNodes: db.prepare(`
DELETE FROM nodes
WHERE (
datetime(last_heard) < datetime('now', '-' || ? || ' hours')
OR (
last_heard IS NULL
AND node_id NOT IN (
SELECT DISTINCT from_node FROM messages WHERE from_node IS NOT NULL
UNION
SELECT DISTINCT node_id FROM positions WHERE node_id IS NOT NULL
UNION
SELECT DISTINCT node_id FROM telemetry WHERE node_id IS NOT NULL
)
)
)
AND node_id NOT IN (
SELECT DISTINCT from_node FROM messages
WHERE from_node IS NOT NULL
AND datetime(created_at) >= datetime('now', '-' || ? || ' hours')
)
AND node_id NOT IN (
SELECT DISTINCT node_id FROM positions
WHERE node_id IS NOT NULL
AND datetime(timestamp) >= datetime('now', '-' || ? || ' hours')
)
AND node_id NOT IN (
SELECT DISTINCT node_id FROM telemetry
WHERE node_id IS NOT NULL
AND datetime(timestamp) >= datetime('now', '-' || ? || ' hours')
)
`)
};
+32 -5
View File
@@ -227,11 +227,31 @@ router.post('/purge', requireAuth, (req, res) => {
const { hours } = req.body;
const hoursToKeep = hours || 720; // Default to 30 days (720 hours)
const messagesDeleted = messageQueries.deleteOldMessages.run(hoursToKeep);
const positionsDeleted = positionQueries.deleteOldPositions.run(hoursToKeep);
const telemetryDeleted = telemetryQueries.deleteOldTelemetry.run(hoursToKeep);
logger.info(`Starting purge of data older than ${hoursToKeep} hours`);
logger.info(`Data purged: ${messagesDeleted.changes} messages, ${positionsDeleted.changes} positions, ${telemetryDeleted.changes} telemetry records`);
// First, update any nodes with NULL last_heard based on their most recent data
const nullLastHeardUpdated = nodeQueries.updateNullLastHeard.run();
logger.info(`Updated ${nullLastHeardUpdated.changes} nodes with NULL last_heard`);
const messagesDeleted = messageQueries.deleteOldMessages.run(hoursToKeep);
logger.info(`Deleted ${messagesDeleted.changes} old messages`);
const positionsDeleted = positionQueries.deleteOldPositions.run(hoursToKeep);
logger.info(`Deleted ${positionsDeleted.changes} old positions`);
const telemetryDeleted = telemetryQueries.deleteOldTelemetry.run(hoursToKeep);
logger.info(`Deleted ${telemetryDeleted.changes} old telemetry records`);
// Check which old nodes still have data before deleting
const oldNodesWithData = nodeQueries.getOldNodesWithData.all(hoursToKeep);
oldNodesWithData.forEach(node => {
logger.info(`Old node ${node.node_id} (last_heard: ${node.last_heard}): ${node.message_count} messages, ${node.position_count} positions, ${node.telemetry_count} telemetry`);
});
const nodesDeleted = nodeQueries.deleteOldNodes.run(hoursToKeep, hoursToKeep, hoursToKeep, hoursToKeep);
logger.info(`Deleted ${nodesDeleted.changes} old nodes`);
logger.info(`Data purged: ${messagesDeleted.changes} messages, ${positionsDeleted.changes} positions, ${telemetryDeleted.changes} telemetry records, ${nodesDeleted.changes} nodes`);
// Log activity
const timePeriod = hoursToKeep < 24
@@ -250,7 +270,8 @@ router.post('/purge', requireAuth, (req, res) => {
deleted: {
messages: messagesDeleted.changes,
positions: positionsDeleted.changes,
telemetry: telemetryDeleted.changes
telemetry: telemetryDeleted.changes,
nodes: nodesDeleted.changes
}
});
} catch (error) {
@@ -266,4 +287,10 @@ router.get('/mqtt/status', requireAuth, (req, res) => {
});
});
// Get channel configuration
router.get('/config/channels', requireAuth, (req, res) => {
const config = require('../config/config');
res.json(config.channels);
});
module.exports = router;