mirror of
https://github.com/agessaman/meshcore-bot.git
synced 2026-10-23 06:12:19 +00:00
fix: BUG-028 byte_data init; BUG-LOG-1/4 SocketIO and cleanup_database handler fixes
This commit is contained in:
1 parent
7679eb7e2c
commit
973d1fc947
7 files changed
+102
-10
No files matched your search
@@ -2924,6 +2924,15 @@ class RepeaterManager:
|
||||
async def cleanup_database(self, days_to_keep_logs: int = 90):
|
||||
"""Clean up old purging log entries"""
|
||||
try:
|
||||
# Guard: purging_log table may not exist on older installs
|
||||
with self.db_manager.connection() as conn:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute(
|
||||
"SELECT name FROM sqlite_master WHERE type='table' AND name='purging_log'"
|
||||
)
|
||||
if not cursor.fetchone():
|
||||
return
|
||||
|
||||
cutoff_date = datetime.now() - timedelta(days=days_to_keep_logs)
|
||||
|
||||
deleted_count = self.db_manager.execute_update(
|
||||
@@ -2935,7 +2944,7 @@ class RepeaterManager:
|
||||
self.logger.info(f"Cleaned up {deleted_count} old purging log entries")
|
||||
|
||||
except Exception as e:
|
||||
self.logger.error(f"Error cleaning up database: {e}")
|
||||
self.logger.error(f"Error cleaning up database: {type(e).__name__}: {e}")
|
||||
|
||||
def cleanup_repeater_retention(
|
||||
self,
|
||||
|
||||
@@ -516,6 +516,88 @@ class MessageScheduler:
|
||||
|
||||
self.logger.info("Scheduler thread stopped")
|
||||
|
||||
def _run_data_retention(self):
|
||||
"""Run data retention cleanup: packet_stream, repeater tables, stats, caches, mesh_connections."""
|
||||
import asyncio
|
||||
|
||||
def get_retention_days(section: str, key: str, default: int) -> int:
|
||||
try:
|
||||
if self.bot.config.has_section(section) and self.bot.config.has_option(section, key):
|
||||
return self.bot.config.getint(section, key)
|
||||
except Exception:
|
||||
pass
|
||||
return default
|
||||
|
||||
packet_stream_days = get_retention_days('Data_Retention', 'packet_stream_retention_days', 3)
|
||||
purging_log_days = get_retention_days('Data_Retention', 'purging_log_retention_days', 90)
|
||||
daily_stats_days = get_retention_days('Data_Retention', 'daily_stats_retention_days', 90)
|
||||
observed_paths_days = get_retention_days('Data_Retention', 'observed_paths_retention_days', 90)
|
||||
mesh_connections_days = get_retention_days('Data_Retention', 'mesh_connections_retention_days', 7)
|
||||
stats_days = get_retention_days('Stats_Command', 'data_retention_days', 7)
|
||||
|
||||
try:
|
||||
# Packet stream (web viewer integration)
|
||||
if hasattr(self.bot, 'web_viewer_integration') and self.bot.web_viewer_integration:
|
||||
bi = getattr(self.bot.web_viewer_integration, 'bot_integration', None)
|
||||
if bi and hasattr(bi, 'cleanup_old_data'):
|
||||
bi.cleanup_old_data(packet_stream_days)
|
||||
|
||||
# Repeater manager: purging_log and optional daily_stats / unique_advert / observed_paths
|
||||
if hasattr(self.bot, 'repeater_manager') and self.bot.repeater_manager:
|
||||
if hasattr(self.bot, 'main_event_loop') and self.bot.main_event_loop and self.bot.main_event_loop.is_running():
|
||||
future = asyncio.run_coroutine_threadsafe(
|
||||
self.bot.repeater_manager.cleanup_database(purging_log_days),
|
||||
self.bot.main_event_loop
|
||||
)
|
||||
try:
|
||||
future.result(timeout=60)
|
||||
except Exception as e:
|
||||
self.logger.error(f"Error in repeater_manager.cleanup_database: {type(e).__name__}: {e}")
|
||||
else:
|
||||
try:
|
||||
loop = asyncio.get_event_loop()
|
||||
except RuntimeError:
|
||||
loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(loop)
|
||||
loop.run_until_complete(self.bot.repeater_manager.cleanup_database(purging_log_days))
|
||||
if hasattr(self.bot.repeater_manager, 'cleanup_repeater_retention'):
|
||||
self.bot.repeater_manager.cleanup_repeater_retention(
|
||||
daily_stats_days=daily_stats_days,
|
||||
observed_paths_days=observed_paths_days
|
||||
)
|
||||
|
||||
# Stats tables (message_stats, command_stats, path_stats)
|
||||
if hasattr(self.bot, 'command_manager') and self.bot.command_manager:
|
||||
stats_cmd = self.bot.command_manager.commands.get('stats') if getattr(self.bot.command_manager, 'commands', None) else None
|
||||
if stats_cmd and hasattr(stats_cmd, 'cleanup_old_stats'):
|
||||
stats_cmd.cleanup_old_stats(stats_days)
|
||||
|
||||
# Expired caches (geocoding_cache, generic_cache)
|
||||
if hasattr(self.bot, 'db_manager') and self.bot.db_manager and hasattr(self.bot.db_manager, 'cleanup_expired_cache'):
|
||||
self.bot.db_manager.cleanup_expired_cache()
|
||||
|
||||
# Mesh connections (DB prune to match in-memory expiration)
|
||||
if hasattr(self.bot, 'mesh_graph') and self.bot.mesh_graph and hasattr(self.bot.mesh_graph, 'delete_expired_edges_from_db'):
|
||||
self.bot.mesh_graph.delete_expired_edges_from_db(mesh_connections_days)
|
||||
|
||||
ran_at = datetime.datetime.utcnow().isoformat()
|
||||
self._last_retention_stats['ran_at'] = ran_at
|
||||
try:
|
||||
self.bot.db_manager.set_metadata('maint.status.data_retention_ran_at', ran_at)
|
||||
self.bot.db_manager.set_metadata('maint.status.data_retention_outcome', 'ok')
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
except Exception as e:
|
||||
self.logger.exception(f"Error during data retention cleanup: {e}")
|
||||
self._last_retention_stats['error'] = str(e)
|
||||
try:
|
||||
ran_at = datetime.datetime.utcnow().isoformat()
|
||||
self.bot.db_manager.set_metadata('maint.status.data_retention_ran_at', ran_at)
|
||||
self.bot.db_manager.set_metadata('maint.status.data_retention_outcome', f'error: {e}')
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def check_interval_advertising(self):
|
||||
"""Check if it's time to send an interval-based advert"""
|
||||
try:
|
||||
|
||||
@@ -795,13 +795,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize connection manager when page loads
|
||||
// Create connection manager synchronously so page scripts in the extra_js
|
||||
// block can share the same socket without calling io() a second time.
|
||||
window.connectionManager = new ModernConnectionManager();
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
// Initialize dark mode manager first
|
||||
window.darkModeManager = new DarkModeManager();
|
||||
|
||||
window.connectionManager = new ModernConnectionManager();
|
||||
|
||||
|
||||
// Update timestamp immediately and every second
|
||||
updateTimestamp();
|
||||
setInterval(updateTimestamp, 1000);
|
||||
|
||||
@@ -1325,7 +1325,7 @@ window.addEventListener('beforeunload', () => {
|
||||
feed.scrollTop = dir === 'top' ? 0 : feed.scrollHeight;
|
||||
};
|
||||
|
||||
const socket = io({ transports: ['websocket', 'polling'] });
|
||||
const socket = window.connectionManager.socket;
|
||||
|
||||
socket.on('connect', () => {
|
||||
dot.className = 'status-indicator status-connected ms-2';
|
||||
|
||||
@@ -226,7 +226,7 @@
|
||||
});
|
||||
}
|
||||
|
||||
const socket = io({ transports: ['websocket', 'polling'] });
|
||||
const socket = window.connectionManager.socket;
|
||||
|
||||
socket.on('connect', function () {
|
||||
updateStatus('log-status', 'Connected', 'success');
|
||||
|
||||
@@ -2411,7 +2411,7 @@
|
||||
// re-stabilization layout (nodes clumping, edges tangling) that occurs when vis-network
|
||||
// runs physics again. User can refresh or switch to map and back to see updated graph.
|
||||
function setupSocketIO() {
|
||||
const socket = io();
|
||||
const socket = window.connectionManager.socket;
|
||||
|
||||
socket.emit('subscribe_mesh');
|
||||
|
||||
|
||||
@@ -818,8 +818,8 @@
|
||||
console.warn('MeshCore decoder unavailable:', e);
|
||||
});
|
||||
|
||||
// Initialize Socket.IO connection (plain io() with same defaults as base.html)
|
||||
const socket = io();
|
||||
// Reuse the shared socket from base.html's ModernConnectionManager
|
||||
const socket = window.connectionManager.socket;
|
||||
|
||||
// Connection status
|
||||
let commandConnected = false;
|
||||
|
||||
Reference in new issue
Block a user